Мое приложение имеет меню типа панели инструментов.Я разделил процедуру окна на подклассы, чтобы улучшить визуальное отображение, что означает, что мое приложение рисует строку меню.Когда окно приложения свернуто и восстановлено, меню перерисовывается очень хорошо.
Но, если системные цвета изменяются, пока окно приложения свернуто, то меню исчезает при восстановлении окна приложения.Я обнаружил, что когда системные цвета меняются, когда окно приложения свернуто, WM_PAINT
не отправляется на панель меню после восстановления окна.
Я пробовал следующее:
Принудительная отправка WM_PAINT
на строку меню путем вызова InvalidateRect()
в ответ на WM_SIZE
, но это не привело к отправке WM_PAINT
.
Принудительная отправка WM_PAINT
в меню, позвонив по номеру RedrawWindow()
с флагом RDW_INTERNALPAINT
.Удалось отправить WM_PAINT
, и вызывается процедура раскраски меню.Но все равно меню не отображается.
Восстановите окно при изменении цвета системы, вызвав ShowWindow()
в ответ на WM_SYSCOLORCHANGE
.Это сработало.WM_PAINT
отправляется на строку меню, и появляется меню.Тем не менее, я считаю, что было бы грубо заставлять мое окно внезапно всплывать, прерывая все, что пользователь делает с какой-либо другой программой.
Может кто-нибудь посоветовать мне, как правильно сохранить рисование меню безвосстановление окна?
Ниже я попытался это сделать.
В процедуре главного окна:
LRESULT CALLBACK DlgWndProc (HWND hDlg,UINT msg,WPARAM wParam,LPARAM lParam)
{
static int HighContrastOn ;
static HWND hwndMenuBar ;
static HINSTANCE hThisInst ;
static NMTOOLBAR nmtb = { NULL , IDC_MENUBAR , TBN_DROPDOWN , 0 } ;
static HIGHCONTRAST HighContrast = { sizeof (HIGHCONTRAST) , 0 , 0 } ;
switch (msg) {
case WM_CREATE :
hThisInst = ((LPCREATESTRUCT) lParam)->hInstance ;
SystemParametersInfo (SPI_GETHIGHCONTRAST,0,&HighContrast,0) ;
HighContrastOn = HighContrast.dwFlags & HCF_HIGHCONTRASTON ;
return 0 ;
case WM_DESTROY :
PostQuitMessage (0) ;
return 0 ;
case WM_CLOSE :
DestroyMenu (hMenu) ;
DestroyWindow (hDlg);
return 0 ;
case WM_SYSCOLORCHANGE :
ShowWindow (hDlg,SW_NORMAL) ;
SendMessage (hwndMenuBar,WM_SYSCOLORCHANGE,0,0) ;
return 0 ;
case WM_SETTINGCHANGE :
// Catch change in HighContrast status missed by WM_SYSCOLORCHANGE
SystemParametersInfo (SPI_GETHIGHCONTRAST,0,&HighContrast,0) ;
if (HighContrastOn == (HighContrast.dwFlags & HCF_HIGHCONTRASTON))
return 0 ;
HighContrastOn = HighContrast.dwFlags & HCF_HIGHCONTRASTON ;
SendMessage (hwndMenuBar,WM_SYSCOLORCHANGE,0,0) ;
return 0 ;
case WM_NOTIFY :
OnNotify (hDlg,wParam,lParam) ;
break ;
case WM_COMMAND :
OnCommand (hDlg,wParam,lParam) ;
break ;
case WM_INITMENUPOPUP :
int SubMenu ;
SubMenu = (int) SendMessage (hwndMenuBar,TB_GETHOTITEM,0,0) ;
for (int i = 0 ; i < 5 ; i++) {
if (GetSubMenu (hMenu,i) == (HMENU) wParam)
SendMessage (hwndMenuBar,WM_INITMENUPOPUP,SubMenu,0) ;
} /* for (int i = 0 ; i < 5 ; i++) */
InitMenuPopup ((HMENU) wParam,SubMenu) ;
return 0 ;
case WM_UNINITMENUPOPUP :
int i ;
// Find out whther the closing menu is sub menu or sub-sub menu
for (i = 0 ; i < 5 ; i++) {
if ((HMENU) wParam == GetSubMenu (hMenu,i))
break ;
} /* for (i = 0 ; i < 5 ; i++) */
if (i < 5) {
UnhookWindowsHookEx (DefaultMsgHook) ;
SendMessage (hDlg,WM_NOTIFY,IDC_MENUBAR,(LPARAM) &nmtb) ;
SendMessage (hwndMenuBar,WM_UNINITMENUPOPUP,0,0) ;
} /* if (i < 5) */
return 0 ;
case IDM_INIT :
InitDialog (hDlg) ;
hMenu = LoadMenu (hThisInst,"MyProgram") ;
hwndMenuBar = GetDlgItem (hDlg,IDC_MENUBAR) ;
nmtb.hdr.hwndFrom = hwndMenuBar ;
SetWindowSubclass (hwndMenuBar,MenuBarProc,0,0) ;
SendMessage (hwndMenuBar,WM_NULL,0,0) ;
return 0 ;
} /* switch (msg) */
/* Pass unprocessed messages to DefDlgProc */
return DefDlgProc (hDlg,msg,wParam,lParam) ;
} /* DlgWndProc */
LRESULT WINAPI MenuBarMsgHook (int Code,WPARAM wParam,LPARAM lParam)
{
static NMTOOLBAR nmtb ;
switch (Code) {
case MSGF_MENU :
#define Msg ((LPMSG) lParam)
HWND hwndMenuBar ;
hwndMenuBar = GetDlgItem (Msg->hwnd,IDC_MENUBAR) ;
switch (Msg->message) {
POINT pt ;
case WM_LBUTTONDOWN :
case WM_RBUTTONDOWN :
pt = Msg->pt ;
ScreenToClient (hwndMenuBar,(LPPOINT) &pt) ;
SendMessage (hwndMenuBar,Msg->message,wParam,
(LPARAM) MAKELONG (pt.x,pt.y)) ;
break ;
case WM_MOUSEMOVE :
pt = Msg->pt ;
ScreenToClient (hwndMenuBar,(LPPOINT) &pt) ;
SendMessage (hwndMenuBar,WM_MOUSEMOVE,wParam,
(LPARAM) MAKELONG (pt.x,pt.y)) ;
break ;
} /* switch (Msg->message) */
#undef Msg
} /* switch (Code) */
return CallNextHookEx (NULL,Code,wParam,lParam) ;
} /* MenuBarMsgHook */
LRESULT CALLBACK MenuBarProc (HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam,
UINT_PTR uIdSubclass,DWORD_PTR dwRefData)
{
static bool BtnDown ;
static int HighContrastOn ;
static int yc ;
static int xr ;
static int yb ;
static int HBtn = -1 ;
static char* Text[] = {"File","Edit","Settings","Design","Help"} ;
static RECT Rect[5] ;
static HFONT Font ;
static HPEN Pen ;
static HPEN HPen ;
static HPEN SPen ;
static HBRUSH Brush ;
static HBRUSH HBrush ;
static HBRUSH SBrush ;
static COLORREF BtnTextColor = GetSysColor (COLOR_BTNTEXT) ;
static COLORREF MenuColor = GetSysColor (COLOR_MENUBAR) ;
static COLORREF HotLightColor = GetSysColor (COLOR_HOTLIGHT) ;
static COLORREF HighLightColor = GetSysColor (COLOR_HIGHLIGHT) ;
static COLORREF HiLightTextColor = GetSysColor (COLOR_HIGHLIGHTTEXT) ;
static COLORREF WindowFrameColor = GetSysColor (COLOR_WINDOWFRAME) ;
static HIGHCONTRAST HighContrast = { sizeof (HIGHCONTRAST) , 0 , 0 } ;
static TRACKMOUSEEVENT tme = {sizeof (TRACKMOUSEEVENT),TME_LEAVE,NULL,
HOVER_DEFAULT} ;
HDC hDC ;
switch (msg) {
case WM_NULL :
SystemParametersInfo (SPI_GETHIGHCONTRAST,0,&HighContrast,0) ;
HighContrastOn = HighContrast.dwFlags & HCF_HIGHCONTRASTON ;
Font = CreateMenuFont (hwnd) ;
Pen = (HPEN) GetStockObject (NULL_PEN) ;
Brush = CreateSolidBrush (MenuColor) ;
if (HighContrastOn) {
HPen = CreatePen (PS_SOLID,0,WindowFrameColor) ;
SPen = CreatePen (PS_SOLID,0,WindowFrameColor) ;
HBrush = CreateSolidBrush (HighLightColor) ;
SBrush = CreateSolidBrush (HighLightColor) ;
} /* if (HighContrastOn) */
else {
HPen = CreatePen (PS_SOLID,0,0xF87400) ;
SPen = CreatePen (PS_SOLID,0,HotLightColor) ;
HBrush = CreateSolidBrush (0xFFF4E6) ;
SBrush = CreateSolidBrush (0xFED8B0) ;
} /* else */
for (int Btn = 0 ; Btn < 5 ; Btn++)
SendMessage (hwnd,TB_GETRECT,IDM_FILEMENU + Btn,(LPARAM) (Rect + Btn)) ;
hDC = GetDC (hwnd) ;
TEXTMETRIC tm ;
GetTextMetrics (hDC,&tm) ;
ReleaseDC (hwnd,hDC) ;
yc = (Rect[0].bottom - Rect[0].top - tm.tmHeight) / 2 + tm.tmAscent - 1 ;
xr = Rect[4].right ;
yb = Rect[0].bottom ;
tme.hwndTrack = hwnd ;
return 0 ;
case WM_PAINT :
if (! GetUpdateRect (hwnd,NULL,false))
break ;
#define rc (Rect[Btn])
PAINTSTRUCT ps ;
hDC = BeginPaint (hwnd,&ps) ;
SelectObject (hDC,Font) ;
SelectObject (hDC,Pen) ;
SelectObject (hDC,Brush) ;
SetTextAlign (hDC,TA_BASELINE | TA_CENTER) ;
SetTextColor (hDC,BtnTextColor) ;
SetBkMode (hDC,TRANSPARENT) ;
for (int Btn = 0 ; Btn < 5 ; Btn++) {
Rectangle (hDC,rc.left,rc.top,rc.right,rc.bottom) ;
if (Btn == HBtn)
continue ;
int xc = (rc.right + rc.left) / 2 ;
ExtTextOut (hDC,xc,yc,ETO_NUMERICSLATIN,&rc,Text[Btn],
(UINT) strlen (Text[Btn]),NULL) ;
} /* for (int Btn = 0 ; Btn < 5 ; Btn++) */
#undef rc
#define rc (Rect[HBtn])
if (HBtn > -1) {
SelectObject (hDC,BtnDown ? SPen : HPen) ;
SelectObject (hDC,BtnDown ? SBrush : HBrush) ;
SetTextColor (hDC,HighContrastOn ? HiLightTextColor : BtnTextColor) ;
RoundRect (hDC,rc.left + 1,rc.top + 1,rc.right - 1,rc.bottom - 2,2,2) ;
int xc = (rc.right + rc.left) / 2 ;
ExtTextOut (hDC,xc,yc,ETO_NUMERICSLATIN,&rc,Text[HBtn],
(UINT) strlen (Text[HBtn]),NULL) ;
} /* if (HBtn > -1) */
#undef rc
EndPaint (hwnd,&ps) ;
return 0 ;
case WM_SYSCOLORCHANGE :
DeleteObject (HPen) ;
DeleteObject (SPen) ;
DeleteObject (Brush) ;
DeleteObject (HBrush) ;
DeleteObject (SBrush) ;
HighLightColor = GetSysColor (COLOR_HIGHLIGHT) ;
WindowFrameColor = GetSysColor (COLOR_WINDOWFRAME) ;
HotLightColor = GetSysColor (COLOR_HOTLIGHT) ;
HiLightTextColor = GetSysColor (COLOR_HIGHLIGHTTEXT) ;
BtnTextColor = GetSysColor (COLOR_BTNTEXT) ;
MenuColor = GetSysColor (COLOR_MENUBAR) ;
SystemParametersInfo (SPI_GETHIGHCONTRAST,0,&HighContrast,0) ;
HighContrastOn = HighContrast.dwFlags & HCF_HIGHCONTRASTON ;
if (HighContrastOn) {
HPen = CreatePen (PS_SOLID,0,WindowFrameColor) ;
SPen = CreatePen (PS_SOLID,0,WindowFrameColor) ;
HBrush = CreateSolidBrush (HighLightColor) ;
SBrush = CreateSolidBrush (HighLightColor) ;
} /* if (HighContrastOn) */
else {
HPen = CreatePen (PS_SOLID,0,0xF87400) ;
SPen = CreatePen (PS_SOLID,0,HotLightColor) ;
HBrush = CreateSolidBrush (0xFFF4E6) ;
SBrush = CreateSolidBrush (0xFED8B0) ;
} /* else */
Brush = CreateSolidBrush (MenuColor) ;
return 0 ;
case WM_NCDESTROY:
DeleteObject (Font) ;
DeleteObject (HPen) ;
DeleteObject (SPen) ;
DeleteObject (Brush) ;
DeleteObject (HBrush) ;
DeleteObject (SBrush) ;
RemoveWindowSubclass (hwnd,MenuBarProc,0) ;
break ;
case WM_INITMENUPOPUP :
HBtn = (int) wParam ;
BtnDown = true ;
InvalidateRect (hwnd,NULL,true) ;
break ;
case WM_UNINITMENUPOPUP :
HBtn = -1 ;
BtnDown = false ;
InvalidateRect (hwnd,NULL,true) ;
break ;
case WM_MOUSEMOVE :
#define rc (Rect[Btn])
int x ;
int y ;
x = LOWORD (lParam) ;
y = HIWORD (lParam) ;
if (HBtn > -1 && x > xr && ! BtnDown) {
HBtn = -1 ;
InvalidateRect (hwnd,NULL,true) ;
break ;
} /* if (HBtn > -1 && x > xr && ! BtnDown) */
for (int Btn = 0 ; Btn < 5 ; Btn++) {
if (y < rc.bottom && x > rc.left && x < rc.right) {
if (Btn == HBtn)
break ;
HBtn = Btn ;
InvalidateRect (hwnd,NULL,true) ;
break ;
} /* if (y < rc.bottom && x > rc.left && x < rc.right) */
} /* for (int Btn = 0 ; Btn < 5 ; Btn++) */
TrackMouseEvent (&tme) ;
#undef rc
break ;
case WM_MOUSELEAVE :
if (! BtnDown) {
HBtn = -1 ;
InvalidateRect (hwnd,NULL,true) ;
} /* if (! BtnDown) */
return 0 ;
} /* switch (msg) */
return DefSubclassProc (hwnd,msg,wParam,lParam) ;
} /* MenuBarProc */
Вот выдержка из фн.InitDialog (), показывающий инициализацию меню
#define NUMBUTTONS 5
static TBBUTTON tbButtons[NUMBUTTONS] =
{{I_IMAGENONE, IDM_FILEMENU , TBSTATE_ENABLED, BTNS_DROPDOWN | BTNS_AUTOSIZE, {0}, 0,(INT_PTR) " File"} ,
{I_IMAGENONE, IDM_EDITMENU , TBSTATE_ENABLED, BTNS_DROPDOWN | BTNS_AUTOSIZE, {0}, 0,(INT_PTR) " Edit"} ,
{I_IMAGENONE, IDM_SETTINGSMENU,TBSTATE_ENABLED, BTNS_DROPDOWN | BTNS_AUTOSIZE, {0}, 0,(INT_PTR) " Settings"} ,
{I_IMAGENONE, IDM_DESIGNMENU , TBSTATE_ENABLED, BTNS_DROPDOWN | BTNS_AUTOSIZE, {0}, 0,(INT_PTR) " Design"} ,
{I_IMAGENONE, IDM_HELPMENU , TBSTATE_ENABLED, BTNS_DROPDOWN | BTNS_AUTOSIZE, {0}, 0,(INT_PTR) " Help"}} ;
HFONT MenuFont = CreateMenuFont (hwndMenuBar) ;
SendMessage (hwndMenuBar,WM_SETFONT,(WPARAM) MenuFont,false) ;
SendMessage (hwndMenuBar,TB_BUTTONSTRUCTSIZE,(WPARAM) sizeof(TBBUTTON),0) ;
SendMessage (hwndMenuBar,TB_ADDBUTTONS, (WPARAM) NUMBUTTONS,
(LPARAM) (LPTBBUTTON) &tbButtons) ;
SendMessage (hwndMenuBar,TB_AUTOSIZE,0,0) ;
SendMessage (hwndMenuBar,TB_SETINDENT,2,0) ;
ShowWindow (hwndMenuBar,SW_SHOW) ;
SetWindowSubclass (hwndMenuBar,MenuBarProc,0,0) ;
SendMessage (hwndMenuBar,WM_NULL,0,0) ;
DeleteObject (MenuFont) ;
Меню определяется в ресурсе диалогового окна следующим образом
CONTROL " ",IDC_MENUBAR,"ToolbarWindow32",TBSTYLE_FLAT | TBSTYLE_LIST | WS_CLIPCHILDREN,0,0,0,0,0,HIDC_MENUBAR