Менубар исчезает, когда системные цвета меняются, а окно свернуто - PullRequest
0 голосов
/ 25 сентября 2018

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

Но, если системные цвета изменяются, пока окно приложения свернуто, то меню исчезает при восстановлении окна приложения.Я обнаружил, что когда системные цвета меняются, когда окно приложения свернуто, 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 (), показывающий инициализацию меню

#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 ]

0 голосов
/ 28 сентября 2018

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

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

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

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

0 голосов
/ 26 сентября 2018

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

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

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

SendMessage( toolbar_hwnd, TB_AUTOSIZE, 0, 0 );
...