メッセージボックスが何度も表示される理由は?

このQ&Aのポイント
  • スクロールバーを作り下のプログラムのようにSB_LINEDOWN:の所でメッセージボックスを表示するとなぜかメッセージボックスが何個も表示されてしまいます(20個ぐらい)。
  • メッセージボックスを表示する行を消し、実行される回数をカウントする変数を記入してデバッグしてみると正常に1回実行されているようです。
  • SB_ENDSCROLLの中で表示した場合も正常に1回だけ表示されます。どうしてこうなるのでしょうか?
回答を見る
  • ベストアンサー

メッセージボックスが何度も表示される理由は?

スクロールバーを作り下のプログラムのようにSB_LINEDOWN:の所でメッセージボックスを表示するとなぜかメッセージボックスが何個も表示されてしまいます(20個ぐらい)。しかも表示される個数が変わる時もあります。 メッセージボックスを表示する行を消し、実行される回数をカウントする変数を記入してデバッグしてみると正常に1回実行されているようです。 SB_ENDSCROLLの中で表示した場合も正常に1回だけ表示されます。 どうしてこうなるのでしょうか? --- 実行環境 --- Microsoft Visual C++ 2010 Express WIN32 ユニコードビルド C言語 case WM_VSCROLL: switch(LOWORD(wParam)){ case SB_LINEDOWN: MessageBox(hwnd,TEXT("スクロールバーのテスト中"),TEXT("メッセージボックス"),MB_OK); break; } break;

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

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

スクロールバーのメッセージ生成の特殊性と、MessageBoxの弊害が組み合わさって起こる現象のようです。 通常のウィンドウをクリックした場合、メッセージは1回(というか一組)しか送信されませんが、スクロールバーの場合はマウスのボタンを押し続けることでメッセージが連続して発生するようになっています。通常の状態であれば、マウスのボタンを離すことでメッセージの生成は止まるですが、MessageBoxを生成することによって別のメッセージループがメッセージ処理を行うことになり、その際にスクロールバーにボタンが離されたことが通知されなくなってしまいます(生成されたメッセージボックスがアクティブウィンドウになり、ボタンを離したメッセージがそちらに送信されるためだと思います)。そのため、スクロールバーのボタンの上にマウスカーソルがある状態だと、スクロールバーがメッセージを送信し続けてしまうようです。

nazoda
質問者

お礼

回答ありがとうございました。

その他の回答 (2)

  • MSZ006
  • ベストアンサー率38% (390/1011)
回答No.2

垂直スクロールバーの下矢印▽を押すとそのようになるのですよね。 下矢印を押している間は継続してSB_LINEDOWNがmsgから発せられているので、 ボタンを離すまでの僅かな時間の間でも数回case SB_LINEDOWN:の部分が実行されるのではないでしょうか。

nazoda
質問者

お礼

回答ありがとうございました。 いろいろ試してみましたがcase SB_LINEDOWN:の部分でメッセージボックスを表示しようとするとcase SB_LINEDOWN:の中でのプログラムは正常に動作しなかったです。 なぜだか全く分かりませんがこれはMessageBox関数との相性が悪いと考えるしかなさそうですね。

回答No.1

この部分だけ抜き出されても、原因はわからないですよ。 メッセージループが正しく処理されていなくて、何度も同じメッセージを処理していたり、他のメッセージの処理に問題があるような場合には、その部分のソースがわからないと原因が突き止められません。

nazoda
質問者

補足

これがすべてのソースですがどこかおかしいところがあるでしょうか? #include<windows.h> LRESULT CALLBACK WndProc(HWND,UINT,WPARAM,LPARAM); TCHAR szWinName[] = TEXT("MyWin"); int WINAPI WinMain(HINSTANCE hThisInst,HINSTANCE hPrevInst, LPSTR lpszArgs,int nWinMode) { HWND hwnd; MSG msg; WNDCLASS wcl; wcl.hInstance = hThisInst; wcl.lpszClassName = szWinName; wcl.lpfnWndProc = WndProc;//ウィンドウプロシージャ wcl.style = 0; wcl.hIcon = LoadIcon(NULL, IDI_APPLICATION); wcl.hCursor = LoadCursor(NULL,IDC_ARROW); wcl.lpszMenuName = NULL; wcl.cbClsExtra = 0; wcl.cbWndExtra = 0; wcl.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH); if(!RegisterClass (&wcl)) return 0; hwnd =CreateWindow( szWinName, TEXT("スクロールバーのテスト"), WS_OVERLAPPEDWINDOW | WS_HSCROLL |WS_VSCROLL, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, HWND_DESKTOP, NULL, hThisInst, NULL ); ShowWindow(hwnd,nWinMode); UpdateWindow(hwnd); while(GetMessage(&msg,NULL,0,0)) { TranslateMessage(&msg); DispatchMessage(&msg); } return (int)msg.wParam; } LRESULT CALLBACK WndProc(HWND hwnd,UINT message, WPARAM wParam,LPARAM lParam) { switch(message){ case WM_VSCROLL: switch(LOWORD(wParam)){ case SB_LINEDOWN: MessageBox(NULL,TEXT("スクロールバーのテスト中"),TEXT("メッセージボックス"),MB_OK); break; } break; case WM_DESTROY: PostQuitMessage(0); break; default: return DefWindowProc(hwnd,message,wParam,lParam); } return 0; }

関連するQ&A

  • WM_VSCROLL内の実行回数について

    Visual Studio 2010 Express WIN32 ユニコードビルド C言語 でクライアント領域に縦スクロールバーを貼り付け次のようなプログラムを作りました。 スクロールバーの勉強中に適当に作ったプログラムです。 LRESULT CALLBACK WndProc(HWND hwnd,UINT message,WPARAM wParam,LPARAM lParam) { PAINTSTRUCT ps; TCHAR moji[256]; static int countout=0; static int countin=0;       switch(message){       case WM_PAINT: BeginPaint(hwnd,&ps); wsprintf(moji,TEXT("switch文の外=%d回 switch文の中=%d"),countout,countin); TextOut(ps.hdc,0,0,moji,lstrlen(moji)); EndPaint(hwnd,&ps); break; case WM_VSCROLL: countout=countout+1; switch(LOWORD(wParam)){ case SB_LINEDOWN: countin=countin+1; break; } InvalidateRect(hwnd,NULL,TRUE); break; case WM_DESTROY: PostQuitMessage(0); break; default: return DefWindowProc(hwnd,message,wParam,lParam); } return 0; } 私はこのプログラムの実行結果は スクロールバーのどこをクリックしてもcountoutは+1され下の矢印をクリックしたときはcountinが+1 されるという動作になると思ったのですが実行してみると スクロールバーの矢印をクリック countout が+2 スクロールバーのつまみをクリック countout が+3 スクロールバーの下矢印をクリック countout が+2,countinが+1 されるという結果になりました。 この結果から推測するとVSCROLLバーをクリックしたときはWM_VSCROLL:メッセージが複数回送られているということになると思うのですがどうしてこうなるのでしょうか? プログラミングの本などではWM_VSCROLL:の中のswitch文の外に初期化やInvalidateRectがあるのでWM_VSCROLLメッセージが送られるのは1回だけだと思ったのですが・・・・。

  • エディットボックス内でキー押されたときのメッセージ

    VC++6.0です。 メインウインドウ内のエディットボックス(一行)で、特定のキー入力を検知したいのですが、どのようにすればよいでしょうか。 mfcは使ってません。 //ウインドウプロシージャ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {  switch( message )  {   case WM_CREATE:    //エディットボックスを作成    CreateWindowEx( WS_EX_CLIENTEDGE, "EDIT","",          WS_CHILD|WS_VISIBLE|ES_AUTOHSCROLL,          0,0,2000, 20, hWnd, (HMENU)IDC_EDIT, g_hInst, NULL );    break;   case WM_COMMAND:    //エディットボックス内の変更はEN_CHANGEで受け取れるが、    //キーコードは送られてこない    break;  } }

  • スクロールバーの動作で困っております。

    スクロールバーの動作で困っております。 下記に抜粋のコーディングを示しましたが、横のサイズnMaxを例えば80000(※1)としスクロールボックスを移動させると、ある地点を過ぎると変数wpの上位2バイトがオーバーフローし、スクロールボックスを後部に移動させることが出来ません。 この様な場合どう設定すればスクロールボックスを画面の隅まで移動させられるのでしょうか。どなたかよい解決策をご存知でしたらご教示いただきたく、宜しくお願いします。 LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp){ : case WM_CREATE: FlatSB_SetScrollProp(hWnd, WSB_PROP_HSTYLE, FSB_FLAT_MODE, TRUE); break; : case WM_SIZE: sih.cbSize = sizeof(SCROLLINFO); sih.fMask = SIF_ALL; sih.nMin = 0; sih.nMax = 80000; // ※1 sih.nPage = LOWORD(lp) / 8; // 8 = 文字幅 sih.nPos = posh; // corrent sih.nPos FlatSB_SetScrollInfo(hWnd, SB_HORZ, &sih, TRUE); break; : case WM_HSCROLL: switch (LOWORD(wp)) { case SB_THUMBTRACK: dx = HIWORD(wp) - sih.nPos; // ※2 wpの上位ワードがオーバーフローしてしまう break; }

  • 1 ページスクロール(WM_VSCROLL )が連続で来る

    Visual Studio .NET 2003 で VC++ の開発をしています。 OSはW2KとWinMXです。 CViewクラスを基底にした子ウィンドウの 1 ページスクロール(WM_VSCROLLのSB_PAGEDOWN/SB_PAGEUP)時に、スクロールバーのツマミの上下部分をクリックすると、ボタンを押し続けていなくても、ツマミがマウスカーソルのある位置に移動するまでスクロールし続ける現象が出て困っています。 トレースを出したり、Spy++で確認しましたが、正常動作時はWM_VSCROLL(SB_PAGEDOWN/SB_PAGEUP)の後、必ずWM_VSCROLL(SB_ENDSCROLL)メッセージが来ますが、異常動作時はSB_PAGEDOWN/SB_PAGEUP)メッセージが連続して来ています。 ツマミがマウスカーソルの位置に来るとWM_VSCROLL(SB_THUMBPOSITION)メッセージに変わる為、それに対するWM_VSCROLL(SB_ENDSCROLL)メッセージが来て止まるようです。 MicrosoftのMSDNサイトを探してみたのですが、それらしい記述もありませんでした。 この現象の原因、または原因の可能性、回避法等ご存知の方がいらっしゃいましたら是非ご教示ください。 よろしくお願い致します。

  • VC++6.0で新しいウィンドウを表示したい

    VC++6.0のダイアログベースでプログラミングを行っています。 IDC_BOTTOB6が押されたら、IDD_ABOUTBOXを表示するようにしたいのですが、 うまくいきません。 // // DialogProc - ダイアログボックス プローシジャ // LRESULT CALLBACK DlgProc(HWND hDlg, UINT uMessage, WPARAM wParam, LPARAM lParam) { switch (uMessage) { case WM_COMMAND: switch(LOWORD(wParam)){ case IDCANCEL: TermApp(hDlg); if (hDll != NULL) // DLLロード済み? { FreeLibrary(hDll); // DLLのハンドラ開放 } DestroyWindow(hDlg); break; case IDC_BUTTON6: { CDialog aboutDlg(IDD_ABOUTBOX); INT_PTR nRet = -1; nRet = aboutDlg.DoModal(); // Handle the return value from DoModal switch ( nRet ) { case -1: { MessageBox(NULL,"Dialog box could not be created!", NULL, MB_OK); } break; case IDABORT: // Do something break; case IDOK:{ // Do something } break; default:{ // Do something } break;                 };                } 上記のようにプログラムしていますが、コンパイルは通るのですが、実行するとエラーで落ちます。 Debug Assertion Failed Program: C:/.....test.exe File: afxwin1.inl Line: 22 何か原因が分かりましたら、ご教授頂けると幸いです。 以上、宜しくお願いします。

  • C# テキストボックスで常にスクロールバーを表示するには

    テキストボックスでスクロールバーを表示する機能はありますが、 テキストが少ない状態でも常にスクロールバーを表示しておくためには どうすればよいのでしょうか。 よろしくお願いいたします。

  • ダイアログ表示後に1回だけ実行

    ダイアログベースのプログラムで、ダイアログを表示後にメッセージボックスを表示しようとして、下のプログラムのようにしたのですがダイアログが表示される前にメッセージボックスが表示されてしまいます。 ダイアログが表示された直後に1回だけ表示されるようにするにはどうすればいいですか? #include<Windows.h> #include "resource.h" HINSTANCE hinst; INT_PTR CALLBACK dlgproc(HWND,UINT,WPARAM,LPARAM); int APIENTRY WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow) { hinst=hInstance; DialogBox(hinst,TEXT("mydlgmain"),NULL,dlgproc); } INT_PTR CALLBACK dlgproc(HWND hwnd,UINT msg,WPARAM wp,LPARAM lp) { TCHAR moji[]=TEXT("ダイアログ表示"); switch(msg) { case WM_INITDIALOG: MessageBox(hwnd,moji,TEXT(""),MB_OK); return(INT_PTR)TRUE; case WM_CLOSE: EndDialog(hwnd,LOWORD(wp)); return (INT_PTR)TRUE; } return(INT_PTR)FALSE; } --- 実行環境 --- Microsoft Visual C++ 2010 Express WIN32 ユニコードビルド C言語

  • テキストボックスからフォーカス外す

     editBox = CreateWindow(   "EDIT",   "あああ",   SS_CENTER | WS_CHILD | WS_VISIBLE,   0,0,100,20,   hWnd,   NULL,   hInstance,   NULL); テキストボックスのフォーカスを外すにはどうしたら いいんですか? ESCキーでフォーカスを外そうと思ったら、 テキストボックスにフォーカスがあるせいで case WM_KEYDOWN が動作しません。 フォーカスを外すというソース自体も分かっていません。  case WM_KEYDOWN:   if( wParam == VK_ESCAPE )    ?  break;

  • C#:ListViewでのスクロールイベントの取得について

    .Net2003 C# にてアプリを作成しています。 .Netを始めて初心者です。(プログラミング経験も浅いです) ListView1とListView2を作成して、 ListView2がスクロールしたら、ListView1も同じくスクロールさせる と言ったListViewのスクロールの同期化処理を行いたいのですが、 ソースコードが思いつきません。 ListViewのイベント、プロパティにはスクロール情報を取得するモノが みつかりませんでした。 現在は下記サイトを参考にさせて頂き、スクロールイベントの発生をキャッチする所までは なんとかたどり着いたのですが、ここからどうやって ListView1にスクロール同期化をさせるコードを書いていいのかが 思いつきません。 何か参考になるHPや、コードがありましたら教えてください。 http://dobon.net/vb/dotnet/control/firescrollevent.html から以下コードを参考にしました。 protected override void WndProc(ref Message m) { const int WM_HSCROLL = 0x114; const int WM_VSCROLL = 0x115; switch (m.Msg) { case WM_HSCROLL: Console.WriteLine( "水平スクロールバーがスクロールされました。"); break; case WM_VSCROLL: Console.WriteLine( "垂直スクロールバーがスクロールされました。"); break; } base.WndProc(ref m); }

  • マウスホイールでテキストボックスのスクロールバーを

    マウスホイールでテキストボックスのスクロールバーを移動させたいです 帳票フォームにしています。 フォームのテキストボックスにスクロールバーありにしてるのですが そのテキストボックスがアクティブになった時に、 マウスホイールをクリクリした時に、 テキストボックスのスクロールバーを移動させたいのですが フォーム上スクロールバーが動いてしまいのレコードが移動してしまいます。 テキストボックスがアクティブの時に↓キーを押せばテキストボックスの スクロールバーは移動しますが、 マウスホイールで操作することは不可能でしょうか? テキストボックスには 1 2 3 4 5 6 7 8 9 10 がはいっています。