メッセージハンドラが呼ばれない – プログラミング – Home

メッセージハンドラが呼ばれない
 
通知
すべてクリア

[解決済] メッセージハンドラが呼ばれない


aetos
(@aetos)
Noble Member
結合: 6年前
投稿: 1480
Topic starter  

環境は WinXP Pro SP1 + VC++.NET 2003 です。

タスクトレイに常駐するプログラムを作ろうとしています。
タスクトレイアイコンをクリックするとメニューが表示され、このメニュー経由ですべ
ての操作を行うため、ユーザーインターフェイスとしてのウィンドウを必要としませ
ん。
ドキュメントもビューも必要ないので、SDI でプロジェクトをつくり、InitInstance の
処理を以下のように書き換えました。
すると、ファイル→終了 を選んでもプログラムが終了しなくなってしまいました。
システムメニューからは終了できるので、どうやらメニューをクリックしたメッセージ
が飛んでこないようです。
どうすれば、メッセージを捕まえられるでしょうか?

以下、InitInstance 抜粋

WNDCLASS wc;
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = AfxWndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = AfxGetInstanceHandle();
wc.hIcon = NULL;
wc.hCursor = ::LoadCursor( NULL, IDC_ARROW );
wc.hbrBackground = reinterpret_cast< HBRUSH >( COLOR_WINDOW + 1 );
wc.lpszMenuName = MAKEINTRESOURCE( IDR_MAINFRAME );
wc.lpszClassName = AxClass;

if( ! AfxRegisterClass( &wc ) )
{
return FALSE;
}

CAxWnd *pWnd = new CAxWnd;
if( ! pWnd )
{
return FALSE;
}

pWnd->CreateEx( 0, AxClass, AxWindow, WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
NULL, NULL );

pWnd->ShowWindow( SW_SHOW );
pWnd->UpdateWindow();

m_pMainWnd = pWnd;


引用
トピックタグ
ちい
 ちい
(@ちい)
ゲスト
結合: 23年前
投稿: 5
 

>どうすれば、メッセージを捕まえられるでしょうか?
普通に作れば飛んできます。
ハンドラを作ってるクラスがまずいのでは?
CAxWnd::OnXXXXになってる?


返信引用
wood
 wood
(@wood)
ゲスト
結合: 23年前
投稿: 895
 

この事象の場合「InitInstance」に問題があるのではなく
「CALLBACK WndProc」に問題があるのだと思われます
そちらを提示してみてはどうでしょうか?

http://www.kumei.ne.jp/c_lang/sdk/sdk_06.htm
を眺めてみてはどうでしょうか
SDKに疎いものですみません


返信引用
aetos
(@aetos)
Noble Member
結合: 6年前
投稿: 1480
Topic starter  

言葉が足りませんでした。申し訳ありません。

自作のメニューではまだ試していないのですが、とりあえず「アプリケーションの終
了」というメニューのクリックを捕まえたいのです。
これは ID が ID_APP_EXIT で、既定では CWinApp::OnAppExit でハンドリングされてい
ます。
AppWizard で作っただけの、まったくいじっていないプログラムを見ると、このハンド
ラは定義されてなく、既定のハンドラが呼ばれますが、今回はこれが呼ばれません(ア
プリが終了しません)。

また、バージョン情報(ID_APP_ABOUT)もこの上のほうに
BEGIN_MESSAGE_MAP(CAxApp, CWinApp)
ON_COMMAND(ID_APP_ABOUT, OnAppAbout)
END_MESSAGE_MAP()
とマッピングされていますが、やはり OnAppAbout が呼ばれません。

CAxWnd はただ CWnd を継承しただけの、何もしないコンストラクタとデストラクタがあ
るだけのクラスなのですが、ここに何か書かなければならないのでしょうか?


返信引用
ハートレー
 ハートレー
(@ハートレー)
ゲスト
結合: 22年前
投稿: 3
 

> タスクトレイアイコンをクリックするとメニューが表示され、このメニュー経由ですべ
> ての操作を行うため、ユーザーインターフェイスとしてのウィンドウを必要としません。

そのメニューはどのように表示しているのでしょうか?
TrackPopupMenu ですか?

CMenu::TrackPopupMenu を使っているとして,(メニュー選択時には)
その 3 番目の引数 pWnd に指定したウィンドウに WM_COMMAND が送られているはずです。
まずここまで確認してください。

でここから先,CWinApp::OnAppExit が呼ばれるかどうかは,
メッセージルーティングの話が関わってきます。↓を読んで下さい。
http://www.microsoft.com/japan/developer/library/vccore/_core_command_routing.ht
m


返信引用
ハートレー
 ハートレー
(@ハートレー)
ゲスト
結合: 22年前
投稿: 3
 

> メッセージルーティングの話が関わってきます。

失礼。コマンドのルーティングです。


返信引用
aetos
(@aetos)
Noble Member
結合: 6年前
投稿: 1480
Topic starter  

ウィンドウにコマンドハンドラ(CAxWnd::OnAppExit)を追加したところ、これが呼ばれ
ていることが確認できました。

提示していただいた文書によると…
フレームワークは、メインフレームが捕まえたコマンドをルーティングに従って転送し
ていって、そのメッセージをハンドリングできるオブジェクトをメッセージマップを見
ながら探していく。
どこでもハンドリングされていなかったら、元のオブジェクト(メインフレーム)で処
理する。

つまり、フレームウィンドウを排して自作のウィンドウに置き換えたこの場合、CAxWnd
にハンドラを作ってそこで捕まえて、CWinApp::OnAppExit を呼びたければ CWinApp の
メッセージマップを見て自分で転送してやるしかない、と。

こういう理解でよろしいでしょうか?


返信引用
yukihiro
 yukihiro
(@yukihiro)
ゲスト
結合: 23年前
投稿: 24
 

OnCmdMsgをオーバーライドして
AfxGetApp()->OnCmdMsgすればOKと思います。


返信引用
aetos
(@aetos)
Noble Member
結合: 6年前
投稿: 1480
Topic starter  

yukihiko さんありがとうございます。
面倒かと思ってたら、そんな簡単な方法でできたんですね。

レスをいただいたハートレーさん、woodさん、ちいさんもありがとうございました。

以下、今回のコードを掲載しておきます。

BOOL CAxWnd::OnCmdMsg(UINT nID, int nCode, void* pExtra, AFX_CMDHANDLERINFO*
pHandlerInfo)
{
if( CWnd::OnCmdMsg(nID, nCode, pExtra, pHandlerInfo) )
{
return TRUE;
}

if( AfxGetApp()->OnCmdMsg( nID, nCode, pExtra, pHandlerInfo ) )
{
return TRUE;
}

return FALSE;
}


返信引用

返信する

投稿者名

投稿者メールアドレス

タイトル *

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