• ベストアンサー

2重Func禁止。クリセク。セマフォ。

MyFunc( ) の実行中は WM_LBUTTONDOWN を無視されるように しようと思いました。 LRESULT CALLBACK WndProc(… {  static bool b = TRUE;  switch(msg){  case WM_LBUTTONDOWN:   if(b){    b = FALSE;    MyFunc( ); //  MessageBox(hWnd, "", "", MB_OK);    b = TRUE;   }  break; でもこれでは、例えば MyFunc( ) が実行中に3回クリックすると その後に MyFunc( ) は3回実行されてしまいます。 MessageBox( ) を使えばうまくいくけと、それは使いたくありません。 できるだけ簡単なソースで、 MyFunc( ) の実行中のクリックで、後で MyFunc( ) が 実行されないようにするにはどこを直したらいいですか?

  • A__
  • お礼率59% (194/328)

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

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

一応 terra5 さんのおっしゃっているヤツです。 --------------------------------------------- void XXFunc(HWND hwnd) // メッセージキュー削除 { MSG msg; // while(PeekMessage(&msg, hwnd, // WM_MOUSEFIRST, WM_MOUSELAST, // PM_REMOVE)); while(PeekMessage(&msg, hwnd, WM_LBUTTONDOWN, WM_LBUTTONDBLCLK, PM_REMOVE)); } --------------------------------------------- でも確かにあんまりお勧めできません。 素直にメッセージボックス出しといた方が良いような。

A__
質問者

補足

ありがとうございます。 その方法で解決しました。 お勧めでないのはどうしてですか?

その他の回答 (4)

noname#2009
noname#2009
回答No.5

>お勧めでないのはどうしてですか? いえ、解決したんでしたら良いです。 システムのメッセージループに関わる部分自体をイジる のは避けたいという感覚があるので、というだけです。 ユーザインターフェース動作の方針そのものを変更した 解決の方が、できれば望ましいので。 その部分の動作については仕様上譲れないという状況で あるのなら、全然問題無いと思います。

A__
質問者

お礼

ありがとうございます。

  • itohh
  • ベストアンサー率45% (210/459)
回答No.4

こんにちは。itohhといいます。 ボタンの押下を無効にしてしまうのはダメなのでしょうか? >LRESULT CALLBACK WndProc(… >{ > static bool b = TRUE; > switch(msg){ > case WM_LBUTTONDOWN: >  if(b){ >   b = FALSE;     HWND hwBtn = GetDlgItem(hWnd, IDC_BTN_XXX );    // (1)     EnableWindow(hwBtn, FALSE );            // (2) >   MyFunc( );     EnableWindow(hwBtn, TRUE );            // (3) >//  MessageBox(hWnd, "", "", MB_OK); >   b = TRUE; >  } > break; (1) ボタン(IDC_BTN_XXX)のハンドルを取得する。 (2) マウス入力とキーボード入力を無効する。 (3) マウス入力とキーボード入力を有効する。 これで、MyFunc関数が完了するまでボタンを押下することが出来なくなります。

A__
質問者

お礼

ありがとうございます。 今回の場合はボタンは無く、マウスクリックで 関数を実行するんだけど、ボタンクリックで 関数起動だったとしたら、ボタンを非活性にする法も使えますね。

  • terra5
  • ベストアンサー率34% (574/1662)
回答No.2

>クリックの回数はストックされていて、 >その回数だけ必ず MyFunc( ) が実行されてしまうんです。 それは、未処理のメッセージがあるためでしょうね。 MyFunc()終了後、バッファにたまっているメッセージをクリアするような処理が必要でしょう。 もしくは、処理を開始した時点で一時的にクリックで メッセージが発生しないようにしておき、 終わった時点で元に戻すとか。 今手元には参考になるものが無いので、 具体的にどうするかはわかりませんが(^^;

  • terra5
  • ベストアンサー率34% (574/1662)
回答No.1

多分この程度で大丈夫でしょう。 > static bool b = TRUE;  static int b = 0; >  if(b){   if(!b){ >   b = FALSE;    b++; >   b = TRUE;    b--; Windowsは詳しくないんですが, 多分マルチスレッドを使わなければ、 クリティカルセクションもセマフォも不要でしょう。

A__
質問者

お礼

ありがとうございます。 int もやってみたけど、bool と同じく、 クリックの回数はストックされていて、 その回数だけ必ず MyFunc( ) が実行されてしまうんです。

関連するQ&A

  • デスクトップをサブクラス

    デスクトップ以外のサブクラスなら何度もやったことがあります。 DLLを使わずにデスクトップをサブクラスにできますか? DLLを使わずにデスクトップをサブクラス化しようとしたけど、 サブクラスの対象がデスクトップだと特殊なのか、 サブクラスにできていないみたいでした。 MessageBeep(0xFFFFFFFF); が実行されなかったからそう思いました。 FARPROC Org_Proc; LRESULT CALLBACK DeskProc(HWND, UINT, WPARAM, LPARAM); OrgProc = (FARPROC)GetWindowLong(HWND_DESKTOP, GWL_WNDPROC); SetWindowLong(HWND_DESKTOP, GWL_WNDPROC, (LONG)DeskProc); LRESULT CALLBACK DeskProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp) {  if(msg == WM_LBUTTONDOWN)MessageBeep(0xFFFFFFFF);  return CallWindowProc((WNDPROC)Org_Proc, hWnd, msg, wp, lp); }

  • wsprintf( ) でポインタに代入

    wsprintf(p, "%d" , i); を書いたせいで、i の値が変わります。 wsprintf(p, "%d" , i); によってどんなことが起こっているのか詳しく知りたいです。 ポインタのことがまだよく分かってないんです。 #include <windows.h> LPCSTR szStr = "\n char c[255];\n char *p = \"\\0\";\n int i = 12345;\n\n switch (msg){\n case WM_LBUTTONDOWN:\n  wsprintf(c, \"%d\" , i);\n  wsprintf(p, \"%d\" , i);\n  MessageBox(hWnd , c , \"\" , MB_OK);\n break;"; LRESULT CALLBACK WndProc(HWND , UINT , WPARAM , LPARAM); int WINAPI WinMain(HINSTANCE hInstance , HINSTANCE , LPSTR , int){ 省略 return msg.wParam; } LRESULT CALLBACK WndProc(HWND hWnd , UINT msg , WPARAM wParam , LPARAM lParam){ HDC hDC; PAINTSTRUCT ps; RECT rt; char c[255]; char *p = "\0"; int i = 12345; switch (msg){ case WM_LBUTTONDOWN: wsprintf(c, "%d" , i); wsprintf(p, "%d" , i); MessageBox(hWnd , c , "" , MB_OK); break; case WM_PAINT: GetClientRect(hWnd, &rt); hDC = BeginPaint(hWnd, &ps); DrawText(hDC, szStr, lstrlen(szStr), &rt, DT_WORDBREAK); EndPaint(hWnd, &ps); break; case WM_DESTROY: PostQuitMessage(0); break; default: return(DefWindowProc(hWnd , msg , wParam , lParam)); } return (0L); }

  • MessageBoxについて

    次のようなプログラムを作りました。 /*ウィンドウプロシージャ内*/ LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam){   ・・・  case WM_LBUTTONDOWN:    hantei(hWnd);    break;   ・・・ } /* 判定関数 */ void hantei(HWND hWnd){   MessageBox(hWnd,"テスト","テストです。",MB_OK); } このようになって動かしてみた(左クリックした)ところ、 ウィンドウ自体は非アクティブになったのですが、 BEEP音が鳴るだけで肝心のメッセージボックスが表示されません。 ALTキーを押すと表示されるのですが・・・ 左クリックをするとすぐにメッセージボックスを表示させるにはどうしたらよいのでしょう? 言葉足らずの説明かもしれませんがお願いします。

  • 自作関数から WndProc( ) を止める

    自作関数から WndProc( ) を止めるにはどうしたらいいんですか? LRESULT CALLBACK WndProc(…){  switch(msg){  case WM_COMMAND:   if(function f( ) == "END")return 0;   処理A;  break;  } } function f( ){  return "END" } こんな流れにしたいけど、WndProc( ) 内からでなく、 外から WndProc( ) を止めたいんです。 LRESULT CALLBACK WndProc(…){  switch(msg){  case WM_COMMAND:   function f( );   処理A;  break;  } } function f( ){  ? // WndProc( ) に return 0 とさせて 処理A を実行させない }

  • DragQueryFile()でエラー

    現在、VC++2005SP1でダイアログベースのアプリを書いていますが、エディットコントールでのドラッグアンドドロップの実装で躓いています。なぜかDragQueryFile()で-1が返って来て直後にGetlastError()を呼ぶと6(無効なハンドル)が返って来ます。 現象の再現を確認しながらコードを以下のレベルまで簡略にしました。 どこかまずいところがあればご教示頂きたく思います。 #include "stdafx.h" #include <stdio.h> #include <locale.h> #include <shellapi.h> #include "Resource.h" TCHAR input_file[MAX_PATH]; void InitDialog( HWND hWnd ); LRESULT CALLBACK MyDragDropProc( HWND, unsigned, WORD, LONG ); WNDPROC lpfnOldEditProc; LRESULT CALLBACK DlgProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp); int APIENTRY _tWinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPTSTR lpCmdLine, int nCmdShow ) {   _tsetlocale(LC_ALL, _T(""));   INT_PTR dret = DialogBox(hInst, MAKEINTRESOURCE( IDD_DIALOG ), NULL, (DLGPROC)DlgProc );   return 0; } LRESULT CALLBACK DlgProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp) {   switch (msg) {   case WM_INITDIALOG: InitDialog( hWnd ); return TRUE;   case WM_COMMAND:     switch (LOWORD(wp)) {     case IDOK: EndDialog(hWnd, IDOK); return TRUE;     case IDCANCEL: EndDialog(hWnd, IDCANCEL); return TRUE;     }   }   return FALSE; } void InitDialog( HWND hWnd ) {   DragAcceptFiles( GetDlgItem( hWnd, IDC_EDIT_INPUT_FILE ), TRUE );   lpfnOldEditProc = (WNDPROC)SetWindowLong( GetDlgItem( hWnd, IDC_EDIT_INPUT_FILE ), GWL_WNDPROC, (LONG)MyDragDropProc ); } LRESULT CALLBACK MyDragDropProc( HWND hWnd, unsigned msg, WORD wp, LONG lp ) {   UINT wFilesDropped;   HDROP hDrop = (HDROP)wp;   TCHAR buff[256];   int err;   switch ( msg ) {   case WM_DROPFILES:     wFilesDropped = DragQueryFile( hDrop, (UINT)-1, NULL, 0 );     err = GetLastError();     _itot_s( err, buff, 256, 10 );     MessageBox( NULL, buff, NULL, MB_OK );     wFilesDropped = DragQueryFile( (HDROP)wp, 0, input_file, MAX_PATH );     MessageBox( hWnd, input_file, NULL, MB_OK );     DragFinish( hDrop );     break;   default:     return CallWindowProc( (WNDPROC)lpfnOldEditProc, hWnd, msg, wp, lp );   }   return 0; }

  • 子ウインドウの作成と破棄について

    CALLBACK のみを書きました。 メインウインドウを破棄したら 子ウインドウも破棄したいのですが、 うまく出来ません。 どうすればよろしいでしょうか? よろしくお願いします。 #include<windows.h> #include"ChildWindow.h" char MainWindowClassName[]="mainwindow"; LRESULT CALLBACK WndProc(HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam) { static HWND childWnd; switch(message) { case WM_ACTIVATEAPP: childWnd=Child_CreateWindow(hWnd,message,wParam,lParam); break; case WM_DESTROY: DestroyWindow(childWnd); PostQuitMessage(0); break; default: return DefWindowProc(hWnd,message,wParam,lParam); } } ///////////////////////////////////////////// #include<windows.h> char ChildWindowClassName[]="childwindow"; LRESULT CALLBACK ChildProc(HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam) { switch(message) { case WM_LBUTTONDOWN: MessageBox(NULL,"","",MB_OK); break; default: return DefWindowProc(hWnd,message,wParam,lParam); } } ATOM Child_RegistWindow(HINSTANCE hInstance){} HWND Child_InitInstance(HWND hParentWnd,HINSTANCE hInst,int CmdShow){} HWND Child_CreateWindow(HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam) { int CmdShow=1; Child_RegistWindow(NULL); HWND ChildWnd=Child_InitInstance(hWnd,NULL,CmdShow); MSG msg; while(GetMessage(&msg,NULL,0,0)) { TranslateMessage(&msg); DispatchMessage(&msg); } return ChildWnd; }

  • BCC32 右クリ イベント

    LRESULT CALLBACK WinWin(HWND hwnd,UINT mess,WPARAM wParam,LPARAM lParam) {  switch(mess){  case WM_LBUTTONDOWN:  処理;  break; これで、ウインドウ上でクリックした時の処理が実行できたけど。 ウインドウ上で右クリックした時の処理をさせるためには どういうソースを書けばいいのか教えてください。  case WM_RBUTTONDPWN: ではコンパイルエラーになりました。

  • リサイズで文字が消えちゃう

    LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) {  HDC hdc;  char *str;  switch (msg) {   case WM_KEYDOWN:   hdc = GetDC(hWnd);   str = "キーダウンした";   TextOut(hdc,1,1,str,strlen(str));   ReleaseDC(hWnd,hdc);   break; キーを押すと、LRESULT CALLBACK でウインドウに文字が 表示されるようにしました。 でも、この文字は別のウインドウに隠れて、再びウインドウが 表示された場合とかには消えています。 消えないようにするためにはどうしたらいいですか? void Swit(HWND hWnd) {  HDC hdc;  char *str;  if (キーダウンのフラグがあったとして、それが true なら) {   hdc = GetDC(hWnd);   str = "キーダウンした";   TextOut(hdc,1,1,str,strlen(str));   ReleaseDC(hWnd,hdc);  } return; } if ( ウインドウ再描画 == true ){ Swit() } というのを考えました。 LRESULT CALLBACK で、キーが押された場合にフラグを true にして ウインドウが再描画された場合にフラグをチェックして文字を 表示する という方法を考えたんだけど、これを BCC32 でコンパイル するためにはどういうソースを書いたらいいか分からないし、 もっといい方法があれば教えてください。

  • 何もしないメッセージだけ表示するウィンドウ

    ゲーム用に何もしないメッセージだけ表示するウィンドウを作りたいのですが、 猫でもわかるゲームプログラミングのコードが間違っているのか、 機能しません。 #include <windows.h> LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp); int WINAPI WinMain(HINSTANCE hCurInst, HINSTANCE hPrevInst, LPSTR lpsCmdLine, int nCmdShow) { return (int)msg.wParam; } LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp) { switch (msg){ } return 0; } このように、打ち込んだのですが、どこが間違っているのか解りません。 回答お願いいたします。

  • CallNextHookEx( ) == FALSE

    1つのアプリの中で、メインプロージャとフックプロージャを作りました。 フックはキーボードフックです。 HHOOK hHook; LRESULT CALLBACK MyHookProc(int nCode, WPARAM wParam, LPARAM lParam){  if(nCode < 0)return CallNextHookEx(hHook, nCode, wParam, lParam);  if(wParam == 0x31)return FALSE;  return TRUE; } フックしていても 「ぬ」 のキーは使えるようにしました。  if(wParam == 0x31)return FALSE; は  if(wParam == 0x31)return CallNextHookEx(hHook, nCode, wParam, lParam); にしても違いが分かりませんでした。 return FALSE では、メッセージをキューから削除らしいけど、メインの プロージャで LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam){  switch(msg){  case WM_KEYDOWN:   if(wParam == 0x31)MessageBox(hWnd, "メインプロージャから", "", MB_OK);  break; にしても、フックプロージヤの戻り値は CallNextHookEx( ) でも FALSE でも MessageBox() は表示されました。 CallNextHookEx( ) にした場合と FALSE にした場合、何が違うのか、 どういうソースなら違いを確かめられるのか教えてください。

専門家に質問してみよう