在下面的帖子中
Menu Accelerator Keys (underline) for Owner-Draw menu items
当用户使用Alt
键导航系统菜单时,如果菜单栏是所有者抽奖,我问了一个关于“如何”绘制下划线的问题。完成了(感谢Hans Passant
)。
但现在又出现了另一个问题:“何时”绘制(并隐藏)下划线。
Alt
关闭后,系统会为所有项目生成WM_DRAWITEM
消息,然后WM_SYSCOMMAND with wParam == SC_KEYMENU
,最后为所选项目生成WM_DRAWITEM
。
请参阅最后的消息列表。
由于在WM_SYSCOMMAND之后,其他项目没有WM_DRAWITEM,我必须使用WM_SYSKEYDOWN with VK_MENU
来指示用户正在使用该键来导航系统菜单。所以我得到了以下代码:(这里byKey
是一个静态bool变量)
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
答案 0 :(得分:3)
您的WM_DRAWITEM
消息包含指向DRAWITEMSTRUCT
的指针。在该结构中,如果应隐藏下划线,则ODS_NOACCEL
标志将在itemState
中设置。
答案 1 :(得分:0)
查看邮件WM_UPDATEUISTATE
(http://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)
时绘制下划线。