2016-06-29 19 views
1

私は、(モデルレス)ダイアログをCreateWindowで作成されたウィンドウの子として埋め込む方法がなければならないことを知っています。私の場合、スクロール可能なコンテナウィンドウにそれらを埋め込みたいので、このコンテナウィンドウはメインウィンドウの子です(図参照)。モードレスダイアログを子ウィンドウとしてWindows APIに埋め込む

Embedded Dialogs

私が遭遇した最初の問題は、私はまだTABキーや他のダイアログの特定のナビゲーションを使用できるようにしたいということ、です。しかしどうですか?

私のメッセージループ:

while (GetMessage(&msg, NULL, 0, 0)) { 
    if (IsDialogMessage(msg.hwnd, &msg)) continue; 
    if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg)) { 
     TranslateMessage(&msg); 
     DispatchMessage(&msg); 
    } 
} 

編集:テスト目的のために、私はループを修正:Using the TAB key to navigate in non-dialogs, redux

:それは正しい方法は、ここで見つけることができるようにする方法を

while (GetMessage(&msg, NULL, 0, 0)) { 
    if (IsEmbeddedDialogWindow(msg.hwnd)) { 
     if (IsDialogMessage(msg.hwnd, &msg)) continue; 
    } 
    if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg)) { 
     TranslateMessage(&msg); 
     DispatchMessage(&msg); 
    } 
} 

while (GetMessage(&msg, NULL, 0, 0)) { 
    if (IsScrollableContainerWindow(msg.hwnd)) { 
     if (IsDialogMessage(msg.hwnd, &msg)) continue; 
    } 
    if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg)) { 
     TranslateMessage(&msg); 
     DispatchMessage(&msg); 
    } 
} 

さらに詳しい情報

このメッセージループでは、メッセージが処理されないかのようにいくつかのダイアログテキストを入力すると何も起こりません。 IsDialogMessageが削除された場合、埋め込みダイアログの編集コントロールにテキストを入力できますが、ダイアログナビゲーションは意図したとおりに機能しません。もちろん、ダイアログの子コントロールにはWS_TABSTOPスタイルが設定されています。

スクロール可能なコンテナはCreateWindowExスタイルで作成され、スタイルは WS_CHILD, WS_VISIBLE, WS_VSCROLL, WS_TABSTOP, WS_EX_CONTROLPARENTであり、このコンテナの子としてダイアログが作成されます。

HWND hWndContainer = GroupBarPanelCreate(WS_CHILD | WS_VISIBLE | WS_VSCROLL | WS_TABSTOP, WS_EX_CONTROLPARENT, hWndMain, 0, 0, 400, 400); 
    GROUPBAR_PANEL* GroupBarPanel = (GROUPBAR_PANEL*) GetWindowLongPtr(hWndContainer, 0); 
    // Test embedding dialogs 
    for (unsigned int i = 0; i < 10; i++) { 
     HWND hWndDlg = CreateDialogParam(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWndContainer, About, 0); 
     GroupBarPanelInternalAddLast(GroupBarPanel, hWndChild, hWndDlg, nullptr); 
    } 

マイGroupBarPanelInternalAddLastキャプションや境界線を除去することによって、モードレスダイアログのスタイルを変更し、WS_CHILDWS_VISIBLEWS_TABSTOPが設定されていることを確認(SetWindowLong(hWndDlg, GWL_STYLE, ...))。 (WS_EX_CONTROLPARENTスタイルもテスト済み)SetParent(hWndDlg, hWndContainer)モードレスダイアログの親を変更しました。

Working Demo

だから私はここで何をしないのですか?私が知っているように、コンテナウィンドウプロシージャや組み込み(テスト目的のサブクラス化された)ダイアログプロシージャは、ほとんど決してWM_SETFOCUSまたはWM_KILLFOCUSメッセージを受け取ることはありませんが、それはなぜですか?

解決策:トップレベルウィンドウでIsDialogMessageを呼び出します。

while (GetMessage(&msg, NULL, 0, 0)) { 
    if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg)) { 
     if (IsDialogMessage(hWndTopLevel, &msg)) { 
      continue; 
     } 
     TranslateMessage(&msg); 
     DispatchMessage(&msg); 
    } 
} 
+1

'IsDialogMessage'は、メッセージが対象とするウィンドウではなく、候補ダイアログの' HWND'を渡す必要があります。 –

+0

これは、 'WS_EX_CONTROLPARENT'スタイルを持ち、他のダイアログの親であるウィンドウの' HWND'を与えなければなりません。 –

+2

作成時に入力フォーカスを手動で設定する必要があります。そうしないと、キーボード操作が機能しません。私はこれが確実に動作するように作られているとは確信していません。なぜ、代わりに通常のウィンドウを作成していないのですか? – IInspectable

答えて

2

あなたは正しくIsDialogMessage()を使用していない、とあなたはいくつかの悪いチュートリアルから学んだと述べました。あなたが見たチュートリアルは分からないので、何が間違っているのかは分かりません。私はそれを正しく使う方法を言うだけです。

IsDialogMessage()は、メッセージそのものと、トップレベルウィンドウのウィンドウハンドルの2つのパラメータをとります。この太字の部分は重要な部分です:IsDialogMessage()関数は、タブナビゲーションやEnter/Esc処理の場合に、どのダイアログを操作するかを知る必要があります。

msg.hwndを渡す必要はありません。それはコントロール自体です。

あなたがここにいるようなネストされた子ダイアログの場合は、子ダイアログのハンドルを渡したくありません。それはIsDialogMessage()をそのダイアログに限定するでしょう。

したがって、スクリーンショットでは、メインウィンドウのハンドル、つまりWin32ApiDemo1というウィンドウを渡したいとします。

また、すべての子ダイアログとカスタムエクスパンダコントロールがWS_EX_CONTROLPARENTであることを確認して、タブナビゲーションを繰り返すことができます。

関連する問題