• ベストアンサー

MessageBox()について

■C言語とWIN32APIで下記の様にコーテイングしています。 ■MessageBox(NULL,text,"条件",MB_YESNO); [質問-1] ・[はい][いいえ]の2個のボタンが表示されるが、当初からカーソルが[はい]ボタンの上にある様に出来ませんか? [質問-2] 表示位置や表示サイズなどを制御出来ませんか ウインドウの場合、下記の関数など使用して対応しました ・GetWindowRect(); ・SetCursorPos(); ・GetCursorPos(); ・SetForegroundWindow(); ......... ......... MessageBox()の場合はどうすれば良いですか?

質問者が選んだベストアンサー

  • ベストアンサー
回答No.1

初期ボタンはMB_DEFBUTTON1あたりのスタイルでできそうでは。 MSDN http://msdn.microsoft.com/ja-jp/library/cc410914.aspx サイズ等はフックするぐらいでしょうか? あまりいじるのであればダイアログを自作したほうがベターかも。 参考 http://park15.wakwak.com/~opapa/cpp/Hook.htm

smiyaf
質問者

補足

ご教示ありがとうございます。 >初期ボタンはMB_DEFBUTTON1あたりのスタイルでできそうでは。 ■私も一応ここを見たのですが・・・ ・初期状態で有効なボタンを指定する事は出来るのですが ・マウスカーソルをそこに設定する方法が分かりません。 ・ウィンドウ(hWnd,hButton,hCombo,hStatic....)ですと GetWindowsRect(); SetCursorPos(); で何とか成ったのですが MessageBox()の場合はどうすれば良いですか?

その他の回答 (2)

回答No.3

 こんばんは。  MessageBox()を呼び出す前にスレッドを回して、モーダルループを通り抜け、スレッドの中からMessageBox()のハンドルを掴めば良いのでは。  MessageBox()のウィンドウクラス名が"#32770"なので、此れを利用してFindWindow()でハンドルを摘まみ出して、いじくれば目的は達成されます。  強引ですが、以下参考程度に。 DWORD WINAPI ThreadProc(LPVOID p) { volatile HWND hWnd = static_cast<HWND>(p); MSG msg; while(::PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE) == FALSE) { ::Sleep(0); HWND hMsgBox = ::FindWindow(TEXT("#32770"), NULL); if(hWnd == ::GetParent(hMsgBox)) { //MessageBoxを移動する RECT rc; ::GetWindowRect(hMsgBox, &rc); ::MoveWindow(hMsgBox, 0, 0, rc.right - rc.left, rc.bottom - rc.top, TRUE); //OKボタンの中央にマウスカーソルを持ってくる HWND hButton = ::GetDlgItem(hMsgBox, IDOK); ::GetWindowRect(hButton, &rc); ::SetCursorPos(rc.left + ((rc.right - rc.left) / 2), rc.top + ((rc.bottom - rc.top) / 2)); ::ExitThread(0); } } return 0; } LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { switch (message) { case WM_CLOSE: ::DestroyWindow(hwnd); return 0; case WM_NCDESTROY: ::PostQuitMessage(0); return 0; } return ::DefWindowProc(hwnd, message, wParam, lParam); } int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR pszArgs, int showCmd) { MSG msg; WNDCLASSEX wc = {sizeof(wc)}; wc.lpszClassName = TEXT("TEST"); wc.lpfnWndProc = &::WndProc; wc.hbrBackground = (HBRUSH)(COLOR_WINDOW); wc.hInstance = hInst; wc.hCursor = LoadCursor(NULL, IDC_ARROW); if(!::RegisterClassEx(&wc)) return 0; HWND hWnd = ::CreateWindowEx( 0, wc.lpszClassName, NULL, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInst, 0); ::ShowWindow(hWnd, SW_SHOW); DWORD dwTID; HANDLE hThread = ::CreateThread(NULL, 0, &::ThreadProc, hWnd, 0, &dwTID); ::MessageBox(hWnd, TEXT("test"), TEXT("test"), IDOK); //万が一MessageBoxを発見出来なかった時に備えて、WM_QUITをポストする ::PostThreadMessage(dwTID, WM_QUIT, 0, 0); ::WaitForSingleObject(hThread, INFINITE); ::CloseHandle(hThread); while(::GetMessage(&msg, NULL, 0, 0) == TRUE) { ::TranslateMessage(&msg); ::DispatchMessage(&msg); } return msg.wParam; }

smiyaf
質問者

お礼

ありがとうございます。 サンプルプログラム有難う御座います 私がパットみて理解できないので、しばらく勉強させて下さい。

  • redfox63
  • ベストアンサー率71% (1325/1856)
回答No.2

やるとすれば MessageBoxの第一引数を表示するための(親)ウィンドウのハンドルを渡してやったほうがいいかもしれません こうすれば 親ウィンドウの中心にMessageBoxが表示されると思います 後は MessageBox()を呼ぶ前に [はい]ボタンが来るであろう位置を計算しておいて SetCursorPosを先に実行してから MessageBox()を呼んでやるという具合になると思います MessageBox自体が特殊なモーダルダイアログなので表示後に外部からの割り込み操作ができません 別の方法としては マウスドライバー側の設定で デフォルトボタンを追いかける機能を使うようにするとかでしょう # ユーザーが設定を解除してしまった場合は無効になりますが ・・・

smiyaf
質問者

補足

ご教示すありがとうございます、 >MessageBox()を呼ぶ前に [はい]ボタンが来るであろう位置を計算しておいて SetCursorPosを先に実行してから MessageBox()を呼んでやるという具合になると思います ■上記の方法で出来ました、「関数をを呼ぶ前...」これもミソですね ■しかしMessageBox()のハンドル等はどこかで得られないものなのでしょうか、 >別の方法としては マウスドライバー側の設定で デフォルトボタンを追いかける機能を使うようにするとかでしょう ■もう少し、ヒントをください。

関連するQ&A