• ベストアンサー

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

  • ショートカットメニューについて

    TrackPopupMenu()APIと、GetCursorPos()APIなどを使って、カーソルの位置にメニューを表示することはできたのですが、表示した後にメニュー以外の場所をクリックしたら消す動作をさせたいのですが、どうしてもできません。 だれか教えてください。

  • マウスポインタを移動させるには

    C++でプログラムしています。 MessageBoxのOKのボタンの上にマウスカーソルを移動させるAPI関数を教えてください。

  • マウス移動イベントでMessageBox終了

    Visual C++ 2010 Expressでプログラム開発している初心者です。 現在、オペレータに確認させるため、MessageBox::Show()によりメッセージを表示して OKボタン押下により、MessageBoxを終了しておりますが、ボタン押下する前に マウス移動イベントにより、MessageBoxを終了できないか、調査しております。 MessageBoxのメソッドには、このような機能はないようなので、自前で作成するしか ないかな、と考えております。 その場合には、まず (1)ウィンドウを作成し、マウスイベントを取得できるプログラムを登録 (2)ウィンドウ(メッセージ含む)表示 (3)マウスイベントを取得 (4)イベント解析 (5)ウィンドウ終了 上記のように動かすには、初心者の自分にはとても難しいので 他に方法はないでしょうか? こんな方法があるよ、とヒントでも構いませんので、是非ご教示ください。 よろしくお願い致します。

  • | (or) を使った関数の引数の作り方

    たとえば、 MessageBoxの4つ目の引数のような感じで、 MessageBox(NULL, \"本文\",\"タイトル\", MB_YESNO|MB_ICONQUESTION); の、 4つ目の引数が|(or)で引数の指定ができますが、 こういった関数を自分で作る場合に、 どのように関数作成して、 4つ目の引数は関数内でどのように取得していけばいいのでしょうか? 基本的なことなのかとは思うのですが・・・ 良い解説のあるHPなど、 ご教授いただきたく思います。 よろしくお願いいたします。

  • | (or) を使った関数の引数の作り方

    たとえば、 MessageBoxの4つ目の引数のような感じで、 MessageBox(NULL, "本文","タイトル", MB_YESNO|MB_ICONQUESTION); の、 4つ目の引数が|(or)で引数の指定ができますが、 こういった関数を自分で作る場合に、 どのように関数作成して、 4つ目の引数は関数内でどのように取得していけばいいのでしょうか? 基本的なことなのかとは思うのですが・・・ 良い解説のあるHPなど、 ご教授いただきたく思います。 よろしくお願いいたします。

  • WM_CREATE について

    Windows API の勉強を始めた者です。 CreateWindow関数を使ったときに発行されるWM_CREATEについて質問させていただきます。 以下のようなプログラムを作りました。このプログラムはウインドウを作るプログラムなのですが、はじめにウインドウを作るかどうかをWindowProcの中で聞いています。 このプログラムでウインドウを作らないという選択肢をとった時が分かりません。 WindowProcでは return -1 をするのでウインドウは作られず、従ってhWndにはNULLが入ります。そして次の文で、  if (hWnd == NULL) {   MessageBox(NULL,TEXT("CreateWindow failed"),NULL,MB_OK);   return 0;  } メッセージボックスが表示されてからプログラムが終了すると思ったのですが、実際にはメッセージボックスは表示されませんでした。 なぜでしょうか。return -1 をした時点で、ウインドウが作られないのでWM_DESTROYがウインドウプロシージャにSendされるのかと考えたのですが、そうなのでしょうか。 よろしくお願いします。 /* 作ったプログラム */ #include <windows.h> LRESULT CALLBACK WindowProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {  int YESNO;  switch(uMsg) {  case WM_DESTROY:   PostQuitMessage(0);  return 0;  case WM_CREATE:  YESNO = MessageBox(NULL, TEXT("Create a new window?"),        ((LPCREATESTRUCT)lParam)->lpszName, MB_YESNO);  if (YESNO == IDYES)   return 0;  if (YESNO == IDNO)   return -1;  }  return DefWindowProc(hWnd, uMsg, wParam, lParam); } int WINAPI WinMain(HINSTANCE hInstance,           HINSTANCE hPrevInstance,           PSTR lpCmdLine,            int nCmdShow) {  WNDCLASS wc;  ATOM atom;  MSG msg;  HWND hWnd;  wc.style = CS_HREDRAW| CS_VREDRAW;  wc.lpfnWndProc = WindowProc;  wc.cbClsExtra = 0;  wc.cbWndExtra = 0;  wc.hInstance = hInstance;  wc.hIcon = NULL;  wc.hCursor = NULL;  wc.hbrBackground = (HBRUSH)COLOR_BACKGROUND + 1;  wc.lpszMenuName = NULL;  wc.lpszClassName = TEXT("sample_window");  if ((atom = RegisterClass(&wc)) == 0) {   MessageBox(NULL,TEXT("RegisterClass failed"),NULL,MB_OK);   return 0;  }  hWnd = CreateWindow((LPCTSTR)atom, TEXT("Sampe window"),              WS_OVERLAPPEDWINDOW | WS_VISIBLE,              100, 100, 400, 300,              NULL, NULL, hInstance, NULL);                if (hWnd == NULL) {   MessageBox(NULL,TEXT("CreateWindow failed"),NULL,MB_OK);   return 0;  }  while (GetMessage(&msg, NULL, 0, 0) > 0) {   DispatchMessage(&msg);  }  return msg.wParam; }

  • ダイアログへ文字列を表示させる方法(API)

    TCHAR s[80] = "Test"; MessageBox(NULL, s, "題名", MB_YESNO); としてダイアログを表示させるのと同じように、 ダイアログボックスをリソースエディタで作成し 作成したダイアログ内に、文字列を表示させるには どのようにしたら良いでしょうか? 作成したダイアログは、MessageBox関数で作成されるものと同じ。 表示させたい文字列は、MessageBox関数の第2パラメータのTCHAR型変数sと同じ。 ダイアログ内の表示させたい所の識別子は、IDC_STATIC。 MS VC++ & Win98 の環境で作成してます。

  • ウィンドウ非表示に時に表示したポップアップメニューを閉じるには?

    質問させて頂きます。 現在C++にてWin32SDKを使用し開発を行っております そこで、メインウィンドウが非表示の時にポップアップメニューを表示するようにしているのですが 非表示の際、ホットキーを起因にポップアップメニューを表示すると ポップアップメニュー以外をクリックしても消えますが WM_TIMER等、一定時間経過時に表示した場合 ポップアップメニュー以外をクリックしても消えません 下記が一部コードを抜粋した物です case WM_CREATE: hMenu = CreatePopupMenu( ); AppendMenu( hMenu, MF_STRING, 0x01, TEXT("HOGE1") ); AppendMenu( hMenu, MF_STRING, 0x02, TEXT("HOGE2") ); return 0; case WM_HOTKEY: GetCursorPos( &pos ); SetForegroundWindow( hWnd ); TrackPopupMenu( hMenu, TPM_LEFTALIGN | TPM_BOTTOMALIGN, pos.x, pos.y, 0, hWnd, NULL ); return 0; case WM_TIMER: GetCursorPos( &pos ); SetForegroundWindow( hWnd ); TrackPopupMenu( hMenu, TPM_LEFTALIGN | TPM_BOTTOMALIGN, pos.x, pos.y, 0, hWnd, NULL ); return 0; ホットキーの設定と、タイマーの設定の処理を付随しておりませんが ホットキー、タイマーの処理は同じものです ポップアップメニューを表示の際、WM_INITMENUPOPUPからポップアップメニューをサブクラス化し WM_KILLFOCUS等のメッセージが来た際に破棄する処理を試しても上手く行きません この場合、マウスをグローバルフックしなければならないでしょうか? 極力フックは避けて解決したいと思っております。 ご教授の程よろしくお願いします。

  • win32APIとC(C++)を使ってカーソルがクライアント領域内に入

    win32APIとC(C++)を使ってカーソルがクライアント領域内に入ったときだけマウスカーソルが非表示になるようにしたいのですがどうしたらいいでしょうか。 今現在は、ShowCursor()という関数を使って引数をfalseにして非表示に使用としているのですがうまくいきません。 以下のように記述して実行してみると、 ShowCursor(false); MessageBox( hWnd, _T("キーダウン"), _T("メッセージ"), MB_OK ); メッセージボックスが出ている間はマウスカーソルが消えるのですが、メッセージボックスを閉じるとカーソルが自動的に再表示されてしまいます。 プログラム実行中は常にマウスカーソルを非表示にしたいのですが、どなたか教えていただけないでしょうか。

  • Windowsプログラミングについて。

    プログラム初心者です。現在Win32APIを用いて、簡単なプログラムを作成中です。質問させてください! 今、現在私の作っているアプリケーションのウインドウ上にあるボタンを押すと(例 case IDC_BUTTON1の時、) (1)そのボタンを押してから10秒ほどたったあとに、 あるMessageBoxを表示させたいと考えております。 ↑の(1)のところをどうプログラムで書けばいいのかわかりません。 アドバイスよろしくお願い致します!!

専門家に質問してみよう