2

在下面的帖子中

Owner-Draw 菜单项的菜单加速键(下划线)

我问了一个关于“如何”在用户使用Alt键导航系统菜单时绘制下划线的问题,如果菜单栏是所有者绘制的。完成了(谢谢Hans Passant)。

但现在出现了另一个问题:“何时”绘制(和隐藏)下划线。

Alt关闭后,将生成WM_DRAWITEM消息(针对所有项目),然后生成消息WM_SYSCOMMAND with wParam == SC_KEYMENU,最后WM_DRAWITEM针对所选项目生成消息。

请参阅最后的消息列表。

由于在 WM_SYSCOMMAND 之后,没有其他项目的 WM_DRAWITEM,我必须使用WM_SYSKEYDOWN with VK_MENU来指示用户正在使用该键来导航系统菜单。所以我得到了以下代码:(这byKey是一个静态布尔变量)

    case WM_SYSKEYDOWN:
    {
        if (wParam == VK_MENU)
            byKey = true;
        return DefWindowProc(hwnd, msg, wParam, lParam);
    }

    case WM_EXITMENULOOP:
    {
        if (wParam == 0)
            byKey = false;
        return DefWindowProc(hwnd, msg, wParam, lParam);
    }

我的问题是:有没有更好的方法来知道“何时”绘制(和隐藏)下划线?

<00686> 000B0444 P WM_SYSKEYDOWN nVirtKey:VK_MENU cRepeat:1 ScanCode:38 fExtended:0 fAltDown:1 fRepeat:0 fUp:0 [wParam:00000012 lParam:20380001]
<00687> 000B0444 S WM_DRAWITEM idCtl:0 lpdis:003EF080 [wParam:00000000 lParam:003EF080]
<00688> 000B0444 R WM_DRAWITEM fProcessed:True [lResult:00000001]
<00689> 000B0444 S WM_DRAWITEM idCtl:0 lpdis:003EF080 [wParam:00000000 lParam:003EF080]
<00690> 000B0444 R WM_DRAWITEM fProcessed:True [lResult:00000001]
<00691> 000B0444 S WM_DRAWITEM idCtl:0 lpdis:003EF080 [wParam:00000000 lParam:003EF080]
<00692> 000B0444 R WM_DRAWITEM fProcessed:True [lResult:00000001]
<00693> 000B0444 S WM_DRAWITEM idCtl:0 lpdis:003EF080 [wParam:00000000 lParam:003EF080]
<00694> 000B0444 R WM_DRAWITEM fProcessed:True [lResult:00000001]
<00695> 000B0444 S WM_DRAWITEM idCtl:0 lpdis:003EF080 [wParam:00000000 lParam:003EF080]
<00696> 000B0444 R WM_DRAWITEM fProcessed:True [lResult:00000001]
<00697> 000B0444 S WM_DRAWITEM idCtl:0 lpdis:003EF080 [wParam:00000000 lParam:003EF080]
<00698> 000B0444 R WM_DRAWITEM fProcessed:True [lResult:00000001]
<00699> 000B0444 S WM_DRAWITEM idCtl:0 lpdis:003EF080 [wParam:00000000 lParam:003EF080]
<00700> 000B0444 R WM_DRAWITEM fProcessed:True [lResult:00000001]
<00701> 000B0444 S WM_DRAWITEM idCtl:0 lpdis:003EF080 [wParam:00000000 lParam:003EF080]
<00702> 000B0444 R WM_DRAWITEM fProcessed:True [lResult:00000001]
....
<00708> 000B0444 P WM_SYSKEYUP nVirtKey:VK_MENU cRepeat:1 ScanCode:38 fExtended:0 fAltDown:0 fRepeat:1 fUp:1 [wParam:00000012 lParam:C0380001]
<00709> 000B0444 S WM_SYSCOMMAND uCmdType:SC_KEYMENU xPos:0 yPos:0 (used mnemonic) [wParam:0000F100 lParam:00000000]
<00710> 000B0444 S WM_ENTERMENULOOP fIsTrackPopupMenu:False [wParam:00000000 lParam:00000000]
<00711> 000B0444 R WM_ENTERMENULOOP lResult:00000000
....

<00714> 000B0444 S WM_INITMENU hmenuInit:01B10471 [wParam:01B10471 lParam:00000000]
<00715> 000B0444 R WM_INITMENU lResult:00000000
    <00716> 000B0444 S WM_DRAWITEM idCtl:0 lpdis:003EECE8 [wParam:00000000 lParam:003EECE8]
<00717> 000B0444 R WM_DRAWITEM fProcessed:True [lResult:00000001]
<00718> 000B0444 S WM_MENUSELECT uItem:0 fuFlags:MF_POPUP | MF_HILITE | MF_OWNERDRAW hmenu:01B10471 [wParam:01900000 lParam:01B10471]
<00719> 000B0444 R WM_MENUSELECT lResult:00000000
4

2 回答 2

3

您的WM_DRAWITEM消息包含一个指向DRAWITEMSTRUCT. 在该结构中,如果应隐藏下划线,ODS_NOACCEL将设置标志。itemState

于 2013-02-17T15:07:08.677 回答
0

查看消息WM_UPDATEUISTATEhttp://msdn.microsoft.com/en-us/library/windows/desktop/ms646361%28v=vs.85%29.aspx)。

它的实现可能如下所示:

DWORD dwUiState = 0;  // current control state, usually a member in per-control struct.

switch(uMsg) {
   case WM_UPDATEUISTATE:
      switch(LOWORD(wParam)) {
         case UIS_INITIALIZE:  dwUiState = HIWORD(wParam); break;
         case UIS_CLEAR:       dwUiState &= ~HIWORD(wParam); break;
         case UIS_SET:         dwUiState |= HIWORD(wParam); break;
      }
      InvalidateRect(hWnd, NULL, TRUE);
      break;

   // ... handling of other messages
}

而在WM_PAINT,你应该画下划线的时候!(dwUiState & UISF_HIDEACCEL)

于 2013-02-17T11:18:57.740 回答