Менубар исчезает, когда системные цвета меняются, а окно свернуто

Мое приложение имеет меню типа панели инструментов. Я разделил процедуру окна на подклассы, чтобы улучшить визуальное отображение. Это означает, что мое приложение рисует строку меню. Когда окно приложения свернуто и восстановлено, меню перерисовывается просто отлично.

Но если системные цвета изменяются, когда окно приложения свернуто, то меню восстанавливается при восстановлении окна приложения. Я обнаружил, что когда системные цвета меняются, а окно приложения свернуто, WM_PAINT не отправляется в строку меню после восстановления окна.

Я попробовал следующее:

  1. Принудительная отправка WM_PAINT в меню, позвонив InvalidateRect() в ответ на WM_SIZE, но это не вызвало WM_PAINT быть отправленным.

  2. Принудительная отправка WM_PAINT в меню, позвонив RedrawWindow() с RDW_INTERNALPAINT флаг. Удалось отправить WM_PAINTи процедура покраски меню называется. Но все равно меню не показывает.

  3. Восстановите окно при изменении системных цветов, вызвав 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(), показывающий инициализацию menubar

#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

2 ответа

Вы должны переслать WM_SYSCOLORCHANGE сообщение на панель инструментов управления.

case WM_SYSCOLORCHANGE:
    SendMessage( toolbar_hwnd, WM_SYSCOLORCHANGE, wparam, lparam );
    break;

Вы уже отправили TB_AUTOSIZE сообщение?

SendMessage( toolbar_hwnd, TB_AUTOSIZE, 0, 0 );

Благодаря Дэниелу Секу, я добавил строку, которую он предложил в ответ на WM_SIZE, и это решило проблему.

 case WM_SIZE :
     SendMessage (hwndMenuBar,TB_AUTOSIZE,0,0) ;
     return 0 ;

Мне не нужно было вызывать InvalidateRect () для панели меню. Сообщение TB_AUTOSIZE вызвало отправку сообщения WM_PAINT на панель меню и отображение меню.

Большое спасибо за вашу поддержку.

Другие вопросы по тегам