none
他の処理をさせながら、全面にダイアログを表示 RRS feed

  • 質問

  • いつも大変お世話になっております、鏑木です。
    現在Visual Studio 2005にてダイアログベースのアプリケーションを開発しているのですが、またわからない
    点がでてきたためにいつもながらにこちらで質問させて頂きます。

    現在、VC++にてダイアログベースのアプリケーションを作成しており、そのダイアログ(ダイアログAとします)のデザインは波形が
    ダイアログに設置されたピクチャーコントロール上に常に表示されており、ダイアログ上にあるボタンを押すことで
    別のサブダイアログ(ダイアログBとします)を表示させ、そのサブダイアログで設定した値をサブダイアログを呼び出したダイアログに反映
    させたいと思っております。
    現状としては、ダイアログBをよぶのにDoModal()としていたために、ダイアログA上の波形の描画がストップしてしまいます。
    そこで、モーダルではなうモーダレスにすれば現状を打開できるのではと思い、モーダルダイアログからモーダレスダイアログに変更
    (OnInitDialog()を呼び出すのではなくCreateで呼び出すように変更)したのですが、なぜかダイアログBをモーダレスで表示すると
    すぐにダイアログAの後ろに隠れてしまうようです。
    ダイアログA側で定期的にInvalidate()のような再描画処理をしているわけではないのに、このような現象に見舞われています。

    お聞きしたいことは2点で、
    ・前述したような現象の打開策として、モーダルダイアログをモーダレスダイアログに変更することは正しいでしょうか?
    ・モーダレスにしたときに、すぐにダイアログAの後ろに隠れてしまう原因としてはどのようなことが考えられますでしょうか?

    です。
    参考となるご意見をお待ちしております、よろしくお願いいたします。
    開発環境は
    Windows CE 6.0
    Visual Studio 2005
    です。
    2009年9月16日 7:45

回答

  • ・前述したような現象の打開策として、モーダルダイアログをモーダレスダイアログに変更することは正しいでしょうか?
    間違ってないと思います。

    ・モーダレスにしたときに、すぐにダイアログAの後ろに隠れてしまう原因としてはどのようなことが考えられますでしょうか?
    どういうことがきっかけになって後ろに隠れてしまうのかはよく分かりませんが、
    ダイアログAをモードレスダイアログのオーナーとすれば、
    モードレスダイアログがダイアログAの下に行くことはなくなります。
    それには、CDialog::Create()の第2引数に、ダイアログAのポインタを渡すようにしてください。

    http://msdn.microsoft.com/en-us/library/ms632599(VS.85).aspx#owned_windows あたりをみて、
    Windowsの所有・被所有関係とZ-Orderとの関連について勉強された方がいいと思います。
    • 回答としてマーク 鏑木肆星 2009年9月16日 10:32
    2009年9月16日 8:17

すべての返信

  • ・前述したような現象の打開策として、モーダルダイアログをモーダレスダイアログに変更することは正しいでしょうか?
    間違ってないと思います。

    ・モーダレスにしたときに、すぐにダイアログAの後ろに隠れてしまう原因としてはどのようなことが考えられますでしょうか?
    どういうことがきっかけになって後ろに隠れてしまうのかはよく分かりませんが、
    ダイアログAをモードレスダイアログのオーナーとすれば、
    モードレスダイアログがダイアログAの下に行くことはなくなります。
    それには、CDialog::Create()の第2引数に、ダイアログAのポインタを渡すようにしてください。

    http://msdn.microsoft.com/en-us/library/ms632599(VS.85).aspx#owned_windows あたりをみて、
    Windowsの所有・被所有関係とZ-Orderとの関連について勉強された方がいいと思います。
    • 回答としてマーク 鏑木肆星 2009年9月16日 10:32
    2009年9月16日 8:17
  • Atsushi777様、ご回答ありがとうございます。

    モーダルダイアログにするという考え方は間違っていないんですね。

    モーダレスにしたときにダイアログAの後ろに隠れたように見えた原因は、よびだすモーダレスダイアログのオブジェクトを
    newで作成したオブジェクトのポインタにしていなかった為のようです、newで作成することでダイアログを表示することは
    出来ました。

    しかし、モーダレスとして表示はされるものの、状態はモーダルダイアログの呼び出しと同じで、波形の描画がストップします。
    モーダルとの違いは、モーダレスで呼ぶことで、ダイアログBが表示されている状態で下のダイアログAのコントロールを操作
    することができるという点です。

    波形の描画についてなのですが、描画の方法がメインダイアログからのユーザー定義メッセージをうけて、ダイアログA内で
    SetTimer()をし、波形描画処理をさせるといった方法をとっているので、波形が止まってしまうということは、モーダレスダイアログ
    表示時は、メッセージを受け取れない状態になるといいうことなのですが、これはモーダレスダイアログ表示時の動作としてはおかしい
    動作なのでしょうか?
    2009年9月16日 8:46
  • 鏑木です。

    呼び出されるダイアログBのstyleをポップアップから子に変更することで
    目的の動作を実現できました。

    考えて頂いた皆様、ありがとうございました。
    2009年9月16日 9:05

  • 聞きたい事とされている2点については既に返答が付いているので省略。


    現状としては、ダイアログBをよぶのにDoModal()としていたために、ダイアログA上の波形の描画がストップしてしまいます。
    この波形の描画はどのようにして行っているのでしょうか ?
    OnPaintやOnTimer等であれば、DoModalでも問題なく描画される筈です。


    (OnInitDialog()を呼び出すのではなくCreateで呼び出すように変更)したのですが、なぜかダイアログBをモーダレスで表示す
    OnInitDialogではなく、DoModalをCreateに・・・ですね。

    Sorry, I am not good at English.
    2009年9月16日 9:59
  • FC-Shiro様、ご返答が遅くなり大変申し訳ございませんでした。

    >この波形の描画はどのようにして行っているのでしょうか ?
    >OnPaintやOnTimer等であれば、DoModalでも問題なく描画される筈です。
    全くその通りですね。私もそう思い、プログラムを見直してみたところ、波形描画のSetTimer
    を呼び出されるメッセージの送信方法が
    GetForegroundWindow()
    のハンドルに対して送信していました。そのために、一番前にポップアップされる画面へメッセージ
    が送信され、波形を描画しているダイアログのほうへ送信されなかった為に描画がストップして
    しまったようです。

    通常GetForegroundWindow()を使ってのメッセージ送信なんてしないものなのでしょうか?
    今回作成中のアプリケーションがさまざまなダイアログがあり、そのどのダイアログにも同様の
    波形を表示させておく箇所があり、そのために波形描画のメッセージを様々なダイアログに対して
    メインダイアログから送信したいと思っているのですが、そのために今回のようなGetForegroundWindow
    を使ってしまったのでした。
    現状はフラグを作って、現在、どのダイアログかアクティブかを調べて、そのダイアログに対してメッセージを
    送信するようにしているのですが、もっとスマートな方法があればなと思っているのですが。。

    >OnInitDialogではなく、DoModalをCreateに・・・ですね。
    ダイアログの表示の仕方をDoModalからCreateに、ですよね、ご指摘ありがとうございます。

    鏑木



    2009年9月18日 0:19
  • 通常GetForegroundWindow()を使ってのメッセージ送信なんてしないものなのでしょうか?
    GetForegroundWindow()はどういうときにどういうウィンドウを返すかということをちゃんと理解していますか?
    今回作成中のアプリケーションがさまざまなダイアログがあり、そのどのダイアログにも同様の
    波形を表示させておく箇所があり、そのために波形描画のメッセージを様々なダイアログに対して
    メインダイアログから送信したいと思っているのですが、そのために今回のようなGetForegroundWindow
    を使ってしまったのでした。
    現状はフラグを作って、現在、どのダイアログかアクティブかを調べて、そのダイアログに対してメッセージを
    送信するようにしているのですが、もっとスマートな方法があればなと思っているのですが。。
    アクティブなダイアログだけを更新すればいいということなのでしょうか?
    ということは、メインダイアログでSetTimer()で自分自身にWM_TIMERを送られるようにしておいて、
    WM_TIMERがきたときに、アクティブなダイアログにとあるメッセージを送って再描画を行っている、
    ということでしょうか。

    何やらデータが更新されたときにメッセージを送るとかならともかく、タイマーでいいのであれば、
    各ダイアログ自身が自身にSetTimer()すればいいのではないでしょうか。
    その上で、自身がアクティブではなくなった時には描画更新したくなければ、
    その時タイマーを止めるというやり方がいいような気がします。(WM_ACTIVATEを使う)
    2009年9月18日 0:47