6

アプリケーションが別のアプリケーションの背後にあり、アプリケーションのタスクバー アイコンをクリックすると、アプリケーション モーダルの WS_POPUP ダイアログ ボックスが開いていても、アプリケーション全体が z オーダーの一番上に来ると思います。

ただし、私の (および他の) ダイアログ ボックスの一部では、ダイアログ ボックスのみが前面に表示されることがあります。アプリケーションの残りの部分は残ります。

Spy++ を調べたところ、正常に動作するものについては、WM_WINDOWPOSCHANGING がダイアログの親に送信されていることがわかります。アプリケーションの残りの部分を残すものについては、WM_WINDOWPOSCHANGING がダイアログの親に送信されていません。

通常、1 つのダイアログでアプリ全体が表示され、もう 1 つのダイアログでは表示されない例があります。作業ダイアログ ボックスと非作業ダイアログ ボックスの両方で、同じウィンドウ スタイル、サブスタイル、親、所有者、個体発生があります。

つまり、どちらも DialogBoxParam() で作成された WS_POPUPWINDOW ウィンドウであり、3 番目の引数として同一の HWND を渡しています。

Windows プログラムのこの奇妙な動作に気付いた人はいますか? ボタンをクリックすると、TaskBar はどのようなメッセージをアプリケーションに送信しますか? アプリケーションのすべてのウィンドウが前面に表示されるようにするのは誰の責任ですか?

私の場合、基本親子関係は MDI フレームです...それはどういうわけか考慮されますか?

4

3 に答える 3

5

私はこれが非常に古いことを知っていますが、偶然出くわしただけで、答えを知っています.

ダイアログ ボックスを前面に表示してもメイン ウィンドウが表示されない、これまで見てきた (および作成した) アプリケーションでは、開発者はダイアログ ボックスの所有者を指定することを単に怠っています。

これは、ダイアログ ボックスやメッセージ ボックスなどのモーダル ウィンドウとモードレス ウィンドウの両方に適用されます。モードレス ポップアップの所有者を設定すると、ポップアップは常にその所有者の上に保持されます。

Win32 API では、ダイアログ ボックスまたはメッセージ ボックスを表示する関数は、オーナー ウィンドウをパラメーターとして受け取ります。

INT_PTR DialogBox(
    HINSTANCE hInstance,
    LPCTSTR lpTemplate,
    HWND hWndParent,      /* this is the owner */
    DLGPROC lpDialogFunc
);

int MessageBox(
    HWND hWnd,            /* this is the owner */
    LPCTSTR lpText,
    LPCTSTR lpCaption,
    UINT uType
);

同様に、.NET WinForms では、所有者を指定できます。

public DialogResult ShowDialog(
    IWin32Window owner
)

public static DialogResult Show(
    IWin32Window owner,
    string text
) /* ...and other overloads that include this first parameter */

さらに、WinForms では、モードレス ウィンドウの所有者を簡単に設定できます。

public void Show(
    IWin32Window owner,
)

または、同等に:

form.Owner = this;
form.Show();

そのままの WinAPI コードでは、ウィンドウの作成時にモードレス ウィンドウの所有者を設定できます。

HWND CreateWindow(
    LPCTSTR lpClassName,
    LPCTSTR lpWindowName,
    DWORD dwStyle,
    int x,
    int y,
    int nWidth,
    int nHeight,
    HWND hWndParent, /* this is the owner if dwStyle does not contain WS_CHILD */
    HMENU hMenu,
    HINSTANCE hInstance,
    LPVOID lpParam
);

またはその後:

SetWindowLong(hWndPopup, GWL_HWNDPARENT, (LONG)hWndOwner);

または (64 ビット互換)

SetWindowLongPtr(hWndPopup, GWLP_HWNDPARENT, (LONG_PTR)hWndOwner);

MSDN はSetWindowLong[Ptr]について次のように述べていることに注意してください。

子ウィンドウの親を変更するために、GWLP_HWNDPARENT インデックスを指定してSetWindowLongPtrを呼び出さないでください。代わりに、SetParent関数を使用してください。

上記の最後の 2 つのスニペットが間違っていることを暗示しているように見えるため、これはやや誤解を招く可能性があります。そうではありません。呼び出すSetParentと、目的のポップアップが所有ウィンドウになるのではなく、親ウィンドウの子になります (そのビットを設定します)。WS_CHILD上記のコードは、既存のポップアップを所有ウィンドウにする正しい方法です。

于 2009-11-22T05:14:03.430 に答える
1

タスクバー アイコンをクリックすると、Windows はWM_ACTIVATEメッセージをアプリケーションに送信します。

コードがWM_ACTIVATEメッセージをDefWindowProcウィンドウ プロシージャに渡して処理していることは確かですか?

于 2008-09-19T04:08:19.307 に答える
0

ダイアログの親ウィンドウは正しく設定されていますか?

これを投稿した後、独自の Windows フォーム アプリケーションを起動し、あなたが説明した問題を再現しました。私は2つのダイアログを持っています.1つは正しく動作し、もう1つは正しく動作しません.すぐには動作が異なる理由がわかりません. わかったらこの記事を更新します。

レイモンド・チェンはどこだ!

于 2008-09-09T03:16:05.490 に答える