お世話になっております。
VC++6.0MFCでダイアログベースで作成しているのですが、
ボタンを押下したその位置にMessageBoxを表示させたいのですが、
解りません。過去スレにも目を通してみましたがなかなか有りませんでした。
サンプル等で教えてくれたら嬉しいです。
MessageBoxでは僕もどうやるか解りません。
(メッセージボックスのハンドルが取得できないと出来ないと思う。
無理すれば出来そうだけど面倒そうだし・・・。)
メッセージボックスに似たような簡単なダイアログボックスを作って、
OnInitialize()などでボタン位置を取得してMoveWindowする、
なんてのはどうでしょう?
メッセージボックスは、親ウィンドウの中央に出ます。
メッセージボックスの機能を作り込むのが面倒なら、
メッセージボックスを表示してすぐ閉じるだけの
ダイアログを作って、そのダイアログの位置を調整する
というのはどうですか?
>メッセージボックスは、親ウィンドウの中央に出ます。
デスクトップの中央では?
>>メッセージボックスは、親ウィンドウの中央に出ます。
>デスクトップの中央では?
Win2K,Sp3で確認してみましたが、
ダイアログの中央に出ますよ。
>>メッセージボックスは、親ウィンドウの中央に出ます。
>デスクトップの中央では?
MessageBoxのオーナによるんじゃないすか?
>Win2K,Sp3で確認してみましたが、
>ダイアログの中央に出ますよ。
昔からの慣習でデスクトップの中央だと思いこんでましたが、MFCならば仰る通りです
ね。
SDKでは思いこんでいた通り、デスクトップ中央にしか出ないようです。
(当方の勘違いかも知れませんが・・)
質問者の環境はMFCなので当方の疑問はとりあえず関係ないですね。
失礼しました。>dairygoods殿,επιστημη殿
フックとサブクラス化でやってみました(やっぱり面倒ですね)
void MoveMsgbx( HWND hwnd )
{
// OKボタンの中央に合わせる
POINT mouse;
RECT ok, mbox;
GetCursorPos( &mouse );
::GetWindowRect( ::GetDlgItem( hwnd, 2 ), &ok );// OKボタンのIDが何故か2
::GetWindowRect( hwnd, &mbox );
int x = mbox.left + mouse.x - ( ok.right + ok.left ) / 2;
int y = mbox.top + mouse.y - ( ok.bottom + ok.top ) / 2;
::SetWindowPos( hwnd, 0, x, y, 0, 0, SWP_NOZORDER | SWP_NOSIZE );
}
// サブクラス化
WNDPROC g_wndproc;
LONG CALLBACK WindowProc( HWND hwnd, UINT uMsg, UINT wp, LONG lp );
void Subclass( HWND hwnd )
{
g_wndproc = ( WNDPROC )::GetWindowLong( hwnd, GWL_WNDPROC );
::SetWindowLong( hwnd, GWL_WNDPROC, LONG( WindowProc ) );
}
void Unsubclass( HWND hwnd )
{
::SetWindowLong( hwnd, GWL_WNDPROC, LONG( g_wndproc ) );
g_wndproc = 0;
}
LONG CALLBACK WindowProc( HWND hwnd, UINT uMsg, UINT wp, LONG lp )
{
LONG ret = ::CallWindowProc( g_wndproc, hwnd, uMsg, wp, lp );
if ( WM_INITDIALOG == uMsg )
{
MoveMsgbx( hwnd );
Unsubclass( hwnd );
}
return ret;
}
// フック
HHOOK g_hhook;
LONG CALLBACK CallWndRetProc( int code, UINT wp, LONG lp );
void Hook( HINSTANCE hi, DWORD id )
{
g_hhook = ::SetWindowsHookEx( WH_CALLWNDPROCRET, CallWndRetProc, hi, id );
}
void Unhook()
{
::UnhookWindowsHookEx( g_hhook );
g_hhook = 0;
}
LONG CALLBACK CallWndRetProc( int code, UINT wp, LONG lp )
{
const CWPRETSTRUCT* p = ( const CWPRETSTRUCT* )lp;
if ( WM_NCCREATE == p->message )
{// 最初に捕まるWM_NCCREATEがメッセージボックスのものと決め付け(怪しいかも
Unhook();
Subclass( p->hwnd );
}
return ::CallNextHookEx( g_hhook, code, wp, lp );
}
// 使用
void CxxDlg::OnButtonX()
{
Hook( AfxGetApp()->m_hInstance, GetCurrentThreadId() );
AfxMessageBox( Hook );// ::MessageBox() でも可
}
みなさん、いろいろレス有難うございます。
nさんのフックとサブクラス化で実験してみたいと
思います。結構複雑のなのですね。
ん。当方の疑問、関係無いかと思ったけど関係あるかも。
先程まで”まあそういうものなのだろう”と深く考えていなかったのですが・・
只のMessageBox・・APIのくせにSDKとMFCで挙動が違うのに納得行かないし、MFCが特別
なにかしらの仕掛けを用意しているとは考えにくいと思い、再びテストしました。
SDKで試してみる。
やはり1st引数にどのようなウィンドウハンドルでも動かしてみるとデスクトップ中央に
表示される。
MFCで試してみる。
WINCORE.CPPを覗いてみると1stにはGetSafeHwndが指定されているのが確認され、動かし
てみると呼び出し元ウィンドウの中央に表示される。
そういうことで、どうやらMessageBoxは1st引数次第で表示位置を弄る事が出来そうです
ね。
GetSafeHwndで返されるハンドルにヒントがあるんだろうと仮定すれば、フック等使わな
くとも簡単に表示位置を制御出来るのではないかと・・思ったが、当方の知識ではこれ
以上はよく分かりません。
MFC も フックとサブクラス化で MessageBox API のメッセージボックスを
親の中央に表示してます。
フックプロシージャ:_AfxCbtFilterHook()
サブクラスのウィンドウプロシージャ:_AfxActivationWndProc()
のようです。