2

以下の投稿で

オーナー描画メニュー項目のメニューアクセラレータキー(下線)

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
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 に答える