我的应用程序具有工具栏类型菜单。我对窗口过程进行了子分类,以实现视觉增强,这意味着我的应用程序正在绘制菜单栏。在最小化和还原应用程序窗口后,菜单会重新绘制。
但是,如果在最小化应用程序窗口的同时更改了系统颜色,则在恢复应用程序窗口时,菜单栏将消失。我发现,当在最小化应用程序窗口的同时系统颜色发生变化时,恢复窗口后,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 */
这里是fn的一部分。 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
答案 0 :(得分:0)
您应该将WM_SYSCOLORCHANGE
消息转发到工具栏控件。
case WM_SYSCOLORCHANGE:
SendMessage( toolbar_hwnd, WM_SYSCOLORCHANGE, wparam, lparam );
break;
您发送了TB_AUTOSIZE
条消息吗?
SendMessage( toolbar_hwnd, TB_AUTOSIZE, 0, 0 );
答案 1 :(得分:0)
感谢Daniel Sek,我添加了他针对WM_SIZE提出的建议,并解决了问题。
case WM_SIZE :
SendMessage (hwndMenuBar,TB_AUTOSIZE,0,0) ;
return 0 ;
我不需要为MenuBar调用InvalidateRect()。 TB_AUTOSIZE消息导致WM_PAINT消息被发送到菜单栏并显示菜单。
非常感谢您的支持。