fix: sing-box status styling

This commit is contained in:
Ixniy Evonniy 2026-07-01 01:19:32 +03:00
parent 38aed01ac1
commit d745efbf87
3 changed files with 159 additions and 2 deletions

BIN
cache.db

Binary file not shown.

View File

@ -590,8 +590,7 @@ show_context_menu :: (app: *App_State) {
if !hMenu return; if !hMenu return;
defer DestroyMenu(hMenu); defer DestroyMenu(hMenu);
status_str := ifx app.singbox_running then "Sing-box: Running" else "Sing-box: Stopped"; AppendMenuW(hMenu, MF_OWNERDRAW, CMD_STATUS, null);
AppendMenuW(hMenu, MF_STRING | MF_GRAYED | MF_DISABLED, CMD_STATUS, utf8_to_wide(status_str));
AppendMenuW(hMenu, MF_SEPARATOR, 0, null); AppendMenuW(hMenu, MF_SEPARATOR, 0, null);
@ -802,6 +801,89 @@ app_wnd_proc :: (hwnd: HWND, msg: u32, wparam: WPARAM, lparam: LPARAM) -> LRESUL
SetWindowLongPtrW(hwnd, GWLP_USERDATA, cast(LONG_PTR) app); SetWindowLongPtrW(hwnd, GWLP_USERDATA, cast(LONG_PTR) app);
return 0; return 0;
} }
case WM_MEASUREITEM; {
lpmis := cast(*MEASUREITEMSTRUCT) lparam;
if lpmis.CtlType == ODT_MENU {
lpmis.itemWidth = 160;
lpmis.itemHeight = 22;
return TRUE;
}
}
case WM_DRAWITEM; {
lpdis := cast(*DRAWITEMSTRUCT) lparam;
if lpdis.CtlType == ODT_MENU {
if app {
hDC := lpdis.hDC;
rect := lpdis.rcItem;
// Draw menu background
hMenuBrush := GetSysColorBrush(COLOR_MENU);
FillRect(hDC, *rect, hMenuBrush);
// Create a bold Segoe UI font for high readability
face_name := utf8_to_wide("Segoe UI");
hBoldFont := CreateFontW(
-13, 0, 0, 0, FW_BOLD, 0, 0, 0,
DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
CLEARTYPE_QUALITY, DEFAULT_PITCH | FF_DONTCARE, face_name
);
hOldFont := SelectObject(hDC, hBoldFont);
defer {
SelectObject(hDC, hOldFont);
DeleteObject(hBoldFont);
}
// Status and status dot color selection
status_text := "";
dot_color: u32 = 0;
if app.is_connecting {
status_text = "Sing-box: Connecting...";
dot_color = RGB(241, 196, 15); // Yellow/Orange
} else if app.is_updating {
status_text = "Sing-box: Updating...";
dot_color = RGB(241, 196, 15); // Yellow/Orange
} else if app.singbox_running {
status_text = "Sing-box: Running";
dot_color = RGB(39, 174, 96); // Green
} else {
status_text = "Sing-box: Stopped";
dot_color = RGB(219, 68, 85); // Red
}
// Draw status dot (filled circle) in GDI in the 16x16 area
// Centered 10x10 dot at x: rect.left+9, y: rect.top+6
hBrush := CreateSolidBrush(dot_color);
hOldBrush := SelectObject(hDC, hBrush);
hPen := CreatePen(PS_NULL, 0, 0);
hOldPen := SelectObject(hDC, hPen);
dot_left := rect.left + 9;
dot_top := rect.top + 6;
Ellipse(hDC, dot_left, dot_top, dot_left + 10, dot_top + 10);
SelectObject(hDC, hOldPen);
DeleteObject(hPen);
SelectObject(hDC, hOldBrush);
DeleteObject(hBrush);
// Draw status text next to the dot (using standard menu text color, which is highly readable)
text_color := GetSysColor(COLOR_MENUTEXT);
SetTextColor(hDC, text_color);
SetBkMode(hDC, TRANSPARENT);
text_rect: RECT;
text_rect.left = rect.left + 28;
text_rect.top = rect.top + 3;
text_rect.right = rect.right;
text_rect.bottom = rect.bottom;
DrawTextW(hDC, utf8_to_wide(status_text), -1, *text_rect, DT_SINGLELINE | DT_VCENTER);
}
return TRUE;
}
}
case WM_TRAY_CALLBACK; { case WM_TRAY_CALLBACK; {
if lparam == WM_RBUTTONUP || lparam == WM_LBUTTONUP { if lparam == WM_RBUTTONUP || lparam == WM_LBUTTONUP {
show_context_menu(app); show_context_menu(app);

View File

@ -47,6 +47,52 @@ MF_DISABLED : u32 : 0x00000002;
MF_SEPARATOR : u32 : 0x00000800; MF_SEPARATOR : u32 : 0x00000800;
MF_CHECKED : u32 : 0x00000008; MF_CHECKED : u32 : 0x00000008;
MF_POPUP : u32 : 0x00000010; MF_POPUP : u32 : 0x00000010;
MF_OWNERDRAW : u32 : 0x00000100;
ODT_MENU :: 1;
COLOR_MENU :: 4;
TRANSPARENT :: 1;
DT_SINGLELINE :: 0x00000020;
DT_VCENTER :: 0x00000004;
DI_NORMAL :: 0x0003;
PS_NULL :: 5;
COLOR_MENUTEXT :: 7;
FW_BOLD :: 700;
DEFAULT_CHARSET :: 1;
OUT_DEFAULT_PRECIS :: 0;
CLIP_DEFAULT_PRECIS :: 0;
CLEARTYPE_QUALITY :: 5;
DEFAULT_PITCH :: 0;
FF_DONTCARE :: 0;
WM_MEASUREITEM :: 0x002C;
WM_DRAWITEM :: 0x002B;
HPEN :: *void;
HFONT :: *void;
// Structs
DRAWITEMSTRUCT :: struct {
CtlType: u32;
CtlID: u32;
itemID: u32;
itemAction: u32;
itemState: u32;
hwndItem: HWND;
hDC: HDC;
rcItem: RECT;
itemData: u64;
}
MEASUREITEMSTRUCT :: struct {
CtlType: u32;
CtlID: u32;
itemID: u32;
itemWidth: u32;
itemHeight: u32;
itemData: u64;
}
// NIM constants // NIM constants
NIM_ADD : u32 : 0x00000000; NIM_ADD : u32 : 0x00000000;
@ -70,6 +116,31 @@ SetForegroundWindow :: (hWnd: HWND) -> BOOL #foreign user32;
EnableWindow :: (hWnd: HWND, bEnable: BOOL) -> BOOL #foreign user32; EnableWindow :: (hWnd: HWND, bEnable: BOOL) -> BOOL #foreign user32;
PostMessageW :: (hWnd: HWND, Msg: u32, wParam: WPARAM, lParam: LPARAM) -> BOOL #foreign user32; PostMessageW :: (hWnd: HWND, Msg: u32, wParam: WPARAM, lParam: LPARAM) -> BOOL #foreign user32;
SetTextColor :: (hdc: HDC, color: u32) -> u32 #foreign gdi32;
SetBkMode :: (hdc: HDC, mode: s32) -> s32 #foreign gdi32;
DrawTextW :: (hdc: HDC, lpchText: *u16, cchText: s32, lprc: *RECT, format: u32) -> s32 #foreign user32;
GetSysColorBrush :: (nIndex: s32) -> HBRUSH #foreign user32;
FillRect :: (hDC: HDC, lprc: *RECT, hbr: HBRUSH) -> s32 #foreign user32;
DrawIconEx :: (hdc: HDC, xLeft: s32, yTop: s32, hIcon: HICON, cxWidth: s32, cyWidth: s32, istepIfAniCur: u32, hbrFlickerFreeDraw: HBRUSH, diFlags: u32) -> BOOL #foreign user32;
CreateFontW :: (
nHeight: s32,
nWidth: s32,
nEscapement: s32,
nOrientation: s32,
fnWeight: s32,
fdwItalic: DWORD,
fdwUnderline: DWORD,
fdwStrikeOut: DWORD,
fdwCharSet: DWORD,
fdwOutputPrecision: DWORD,
fdwClipPrecision: DWORD,
fdwQuality: DWORD,
fdwPitchAndFamily: DWORD,
lpszFace: *u16
) -> HFONT #foreign gdi32;
CreatePen :: (iStyle: s32, cWidth: s32, color: u32) -> HPEN #foreign gdi32;
Ellipse :: (hdc: HDC, left: s32, top: s32, right: s32, bottom: s32) -> BOOL #foreign gdi32;
GetSysColor :: (nIndex: s32) -> u32 #foreign user32;
// Custom message IDs // Custom message IDs
WM_USER :: 0x0400; WM_USER :: 0x0400;
WM_TRAY_CALLBACK :: WM_USER + 1; WM_TRAY_CALLBACK :: WM_USER + 1;
@ -280,6 +351,10 @@ set_windows_system_proxy :: (enable: bool, server: string) -> bool {
return true; return true;
} }
RGB :: (r: u32, g: u32, b: u32) -> u32 {
return r | (g << 8) | (b << 16);
}