フレームウィンドウをフラッシュしたい – プログラミング – Home

フレームウィンドウをフラッシュしたい
 
通知
すべてクリア

フレームウィンドウをフラッシュしたい


NOR
 NOR
(@NOR)
ゲスト
結合: 23年前
投稿: 128
Topic starter  

Visual C++ 2008 MFC、XPです。

ダイアログをモーダルで出している状態で親ウィンドウをクリックすると
ダイアログがフラッシュしますが、これはダイアログ自身の機能なのでしょうか?
それとも、MFCのソースにそのようなコードがあるのでしょうか?

変な作りだと言われてしまうかもしれませんが、
フレームウィンドウから別のフレームウィンドウをモーダルで出していて、
その状態のときにもこの機能を付けられないかと思っています。

内部的には、フレームウィンドウから非表示のダイアログをモーダルで出し、
そこから別のフレームウィンドウを作成して、
ダイアログがタイマで終了を監視するようにしています。

親のフレームウィンドウをクリックすると、警告音はちゃんと鳴っています。
しかし、子のフレームウィンドウがフラッシュしません。
なにか伝達できるような仕組みはあるのでしょうか。


引用解決済
トピックタグ
仲澤@失業者
(@uncle_kei)
Prominent Member
結合: 5年前
投稿: 828
 

FlashWindow()
FlashWindowEx()
という関数があります。


返信引用
仲澤@失業者
(@uncle_kei)
Prominent Member
結合: 5年前
投稿: 828
 

蛇足。FlushもFlashも正しい英語(笑)。


返信引用
NOR
 NOR
(@NOR)
ゲスト
結合: 23年前
投稿: 128
Topic starter  

> FlashWindow()
> FlashWindowEx()
> という関数があります。

ありがとうございます。
ただ、この関数をどのタイミングで呼べば、
フレームウィンドウをモーダルダイアログのようにできるのでしょうか。

標準のモーダルダイアログはなにもしなくても勝手にフラッシュしますが、
「親ウィンドウがクリックされたよ」みないなメッセージでもあって、
モーダルダイアログ自身はそれを見て自分で処理しているのでしょうか?


返信引用
ロマ
 ロマ
(@ロマ)
ゲスト
結合: 18年前
投稿: 170
 

こういう関係なのですか。
main(WS_OVERLAPPED | WS_DISABLED)
modal-dialog(WS_POPUP, not WS_SHOW)
frame(WS_POPUP | WS_VISIBLE)

以下で実験したところ、フラッシュしました。
main(WS_OVERLAPPED | WS_DISABLED)
modal-dialog1(WS_POPUP | WS_DIABLED, not WS_SHOW) GWL_HWNDPARENT=main
modal-dialog2(WS_POPUP | WS_VISIBLE) GWL_HWNDPARENT=modal-dialog1

中間のウィンドウはWS_DISABLEDになっていますか。
それぞれの所有関係はどうなっていますか(GWL_HWNDPARENT)。
(Spy++/ウィドウ プロパティ/ウィンドウ/親ウィンドウで見ることができます)

ちなみに、
WS_DISABLEのウィンドウをクリックしたときにBeepが鳴るのは、
WM_SETSURSOR(HTERROR)のDefWindowProcのようです(msdn)。

# Spy++で観察すると、
# フラッシュは WM_SYSTIMER(0x118)で
# WM_NCACTIVATEをactive/inactiveに切り替えているようです。


返信引用
ロマ
 ロマ
(@ロマ)
ゲスト
結合: 18年前
投稿: 170
 

訂正です。

再試験の結果、
> 中間のウィンドウはWS_DISABLEDになっていますか。
これは関係なかったです。

あと、私は非MFCで実験しましたので、フラッシュはAPIの仕様と思います。

> # Spy++で観察すると、
> # フラッシュは WM_SYSTIMER(0x118)で
> # WM_NCACTIVATEをactive/inactiveに切り替えているようです。
これは、たぶんFlashWindowの実装の話です。


返信引用
NOR
 NOR
(@NOR)
ゲスト
結合: 23年前
投稿: 128
Topic starter  

いろいろ試していただきありがとうございます。

> こういう関係なのですか。
> main(WS_OVERLAPPED | WS_DISABLED)
> modal-dialog(WS_POPUP, not WS_SHOW)
> frame(WS_POPUP | WS_VISIBLE)

そのような感じです。
なお、frameのほうもWS_OVERLAPPEDとなっていました。
modal-dialogは、念のためサイズ0でWS_VISIBLEとしています。

ちなみに、今になって気づいたのですが、
操作中のフレームウィンドウからさらに設定用のモーダルダイアログを出し、

main(WS_OVERLAPPED | WS_DISABLED)
modal-dialog(WS_POPUP | WS_VISIBLE)
frame(WS_OVERLAPPED | WS_DISABLED)
modal-dialog(WS_POPUP | WS_VISIBLE)

という状態で親のフレームウィンドウをクリックすると、
一番下のダイアログがちゃんとフラッシュしました。
そのダイアログにはWM_NCACTIVATE(active/inactive)が来ていました。


返信引用
NOR
 NOR
(@NOR)
ゲスト
結合: 23年前
投稿: 128
Topic starter  

すみません、追記させていただきます。

> そのダイアログにはWM_NCACTIVATE(active/inactive)が来ていました。

モーダルで出しているフレームウィンドウ(frame)にも、
WM_NCACTIVATE(active/inactive)自体は届いていました。
ただし、ダイアログのようにフラッシュはしてくれません。

ダイアログはこのタイミングでなにかやっているということなのでしょうか。


返信引用
ロマ
 ロマ
(@ロマ)
ゲスト
結合: 18年前
投稿: 170
 

> main(WS_OVERLAPPED | WS_DISABLED)
> modal-dialog(WS_POPUP | WS_VISIBLE)
> frame(WS_OVERLAPPED | WS_DISABLED)
> modal-dialog(WS_POPUP | WS_VISIBLE)

これだと、mainをクリックすると、
上から2番目のdialogがWS_DISABLEDでは無いので、
2番目のdialogをフラッシュすることになりませんか。
(サイズがゼロだからみえないけど)。
ウィンドウの検索は2番目で止まってしまうような気がします。


返信引用
NOR
 NOR
(@NOR)
ゲスト
結合: 23年前
投稿: 128
Topic starter  

> これだと、mainをクリックすると、
> 上から2番目のdialogがWS_DISABLEDでは無いので、
> 2番目のdialogをフラッシュすることになりませんか。

ご意見ありがとうございます。
そう思ってダイアログを見えるようにしてテストしてみたのですが、
このダイアログがフラッシュしていることはありませんでした。

また、WM_NCACTIVATE(active/inactive(合計6回?))自体は
フレームウィンドウやそこから出すモーダルダイアログには届いているようなので、
2番目で検索が止まっているというわけではないようです。

フレームウィンドウは、このメッセージが来ても
ダイアログのようにフラッシュしてくれないということなのでしょうか。


返信引用
ロマ
 ロマ
(@ロマ)
ゲスト
結合: 18年前
投稿: 170
 

私は課題を取り違えているのでしょうか。

VS2003のMFCで実験してみました。
(MFCアプリケーション(MDI Doc/View)。

CAboutにメンバーCWnd m_Wnd を追加し、
CAbout::OnInitDialogに
m_Wnd.CreateEx(WS_EX_CLIENTEDGE,
AfxRegisterWndClass(0, ::LoadCursor(NULL, IDC_ARROW),
(HBRUSH)(COLOR_WINDOW+1)),
_T(Hello World!),
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, 0, CW_USEDEFAULT, 0,
*this, NULL, 0);
m_Wnd.ShowWindow(SW_SHOW);
を追加する。

このウィンドウをマウスでクリックしてアクティブにすると、
メインウィンドウをクリックしたときにこのウィンドウはフラッシュしました。


返信引用
NOR
 NOR
(@NOR)
ゲスト
結合: 23年前
投稿: 128
Topic starter  

試していただきありがとうございます。

> VS2003のMFCで実験してみました。
> (MFCアプリケーション(MDI Doc/View)。

とりあえずメモリリークなどは全く想定してませんが、
ロマさんに試していただいたケースと同じように、VS2005のSDI(Doc/Viewなし)で、
CAboutDlg::OnInitDialog()を以下のようにやってみたところ、
「Hello World!」のウィンドウはちゃんとフラッシュしました。

CWnd* pWnd = new CWnd;
pWnd->CreateEx(
WS_EX_CLIENTEDGE,
AfxRegisterWndClass(
0, ::LoadCursor(NULL, IDC_ARROW), (HBRUSH)(COLOR_WINDOW+1)),
_T(Hello World!), WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, 0,
CW_USEDEFAULT, 0, *this, NULL, 0);
pWnd->ShowWindow(SW_SHOW);

ただ、CWndのかわりにフレームウィンドウを出してみたところ、
やはり音が鳴るだけでフラッシュはしませんでした。

CMainFrame* pFrame = new CMainFrame;
pFrame->LoadFrame(
IDR_MAINFRAME, WS_OVERLAPPEDWINDOW | FWS_ADDTOTITLE, this, NULL);
pFrame->ShowWindow(SW_SHOW);
pFrame->UpdateWindow();

上のコードは、Doc/Viewなしで作成したプロジェクトの
InitInstance()に書かれているものと同じものです
(親ウィンドウはCAboutDlg自身に変更)

内部的に、フレームウィンドウはフラッシュしない仕組みになっているのでしょうか。

また、VS2005でも再現したので、
以下のときのように、Feature Packのクラスの問題というわけでもないようです。
http://rarara.cafe.coocan.jp/cgi-bin/lng/vc/vclng.cgi?print+201011/10110006.txt


返信引用
ロマ
 ロマ
(@ロマ)
ゲスト
結合: 18年前
投稿: 170
 

ソースを追ってみました。
CFrameWnd::OnActivateでWF_STAYACTIVEを立てて
CFrameWnd::OnNActivateでは、このフラグを見ていました。、
CFrameWndはフラッシュしませんね、残念。


返信引用
NOR
 NOR
(@NOR)
ゲスト
結合: 23年前
投稿: 128
Topic starter  

> CFrameWnd::OnActivateでWF_STAYACTIVEを立てて
> CFrameWnd::OnNActivateでは、このフラグを見ていました。、

やはりCFrameWndのときだけフラッシュしないようになっていたのですね。
試しに前述のテストアプリのCMainFrameにOnNcActivate()を追加し、

BOOL CMainFrame::OnNcActivate(BOOL bActive)
{
return CWnd::OnNcActivate(bActive);
}

と、CFrameWnd::OnNActivate()を通さないようにしてみたら、
あっけなくフラッシュしました。

ただ、デスクトップなどクリックしてから再度タイトルバーをクリックした際に
うまくアクティブ表示に戻らないなど、いろいろ問題が発生するようです。

このあたりをもうちょっといろいろ探ってみたいと思いますが、
このWF_STAYACTIVEはどういうことをしたいために立てているものなのか、
ご存じのかたがいらっしゃれば、引き続きご意見いただけると嬉しいです。

ありがとうございます。


返信引用

返信する

投稿者名

投稿者メールアドレス

タイトル *

プレビュー 0リビジョン 保存しました
共有:
タイトルとURLをコピーしました