teratail header banner
teratail header banner
質問するログイン新規登録

質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.30%
C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

Q&A

解決済

1回答

734閲覧

マウスを右クリックした直後か瞬間に右クリックは無関係か分からないですが左クリックとして見なす事は可能ですか?(Windows)

littlestream

総合スコア37

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

0グッド

3クリップ

投稿2024/02/12 10:48

編集2024/02/12 12:27

0

3

イメージ説明### 実現したいこと
質問失礼します。当方、ドット絵の
グラフィックソフトをソフトウェアでトレース(出来るか分からないですが)
したいソフトを作っています。
エラーはコンパイルエラーの途中はいいとして、ウィンドウが消えたり、ウィンドウ内で
マウスポインタがあまり動かずに固定されることです。なので何度もCtrl+Alt+Delで
ログオフしてエラーというかバグを回避している状況です。

で、マウスは右半分にマウスにある時か、左半分にある時で弄れればこのようなバグを回避出来ると
思いました。さらにShiftキーとマウスクリックとの同時判定のやり方がよく分からないですが、それが
可能ならShiftキー+右クリック、Shiftキー+左クリックは、スポイトと点の描画で、
普通のクリックは単にソフトの機能の操作にしたいのですが、こんなソフトウェアというのは
可能でしょうか?

今のところ、Edge(TAKABO-SOFT様)の設定をいじって、同時起動を可能にした後に
左右のウィンドウハンドル取得、MoveWindowで左右最大化に
成功しました。で、さきほどのバグに遭遇しました。

WinAPIやWindowsプログラミングとc言語に詳しい方にお聞きしますが、
どうすれば可能でしょうか?

発生している問題・分からないこと

具体的には、右クリックした直後に
SetFocusの後にSetCursorPosとmouse_eventを行うと、
マウスカーソルやウィンドウが制御できなくなります。

エラーメッセージ

error

1エラーメッセージは、無いですが、エラーはバグとして存在します。

該当のソースコード

//ウィンドウプロシージャ LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp) { int id; POINTS pts; POINT pt; HWND hTarget2[2]={0};//[0]はソース、[1]は送信先 HWND hTarget; HDC hdc, hdc_mem; PAINTSTRUCT ps; HBITMAP hBit; BITMAP bmp_info; static int wx, wy; RECT rc; static POINT Mem_PntXY; static int RightDragFlag=0; switch (msg) { case WM_CREATE: SetCursor(LoadCursor(NULL, IDC_ARROW));//マウスカーソルをセットする pts = MAKEPOINTS(lp); ScreenWidth = GetSystemMetrics(SM_CXSCREEN);//スクリーンの大きさをセット ScreenHeight = GetSystemMetrics(SM_CYSCREEN); SetTimer(hWnd,100,1000/60,NULL);//タイマーをセット MoveWindow(hWnd,(ScreenWidth-800)/2,(ScreenHeight-180-30+5),800,165,TRUE);         //ウィンドウを下画面に収める break; case WM_PAINT: if (!bCap) { GetClientRect(hWnd, &rc); hdc = BeginPaint(hWnd, &ps); hBit = LoadBitmap(hInst, "MYBMP"); GetObject(hBit, sizeof(BITMAP), &bmp_info); wx = bmp_info.bmWidth; wy = bmp_info.bmHeight; hdc_mem = CreateCompatibleDC(hdc); SelectObject(hdc_mem, hBit); BitBlt(hdc, (rc.right - wx)/2, (rc.bottom-wy)/2, wx, wy, hdc_mem, 0, 0, SRCCOPY); pts=MAKEPOINTS(lp); ShowPoint(hWnd,pts); DeleteDC(hdc_mem); DeleteObject(hBit); EndPaint(hWnd, &ps); } break; case WM_TIMER: if(GetAsyncKeyState(VK_SPACE)<0 && flagcounter==3) { flagcounter=5; pts=MAKEPOINTS(lp); ShowPoint(hWnd,pts); } if(GetAsyncKeyState(VK_LSHIFT)<0) { if(flagcounter==5 && RightDragFlag==1) { // RightDragFlag=0; // ウィンドウを最前面に SetForegroundWindow(hTarget2[0]); // フォーカスがあるウィンドウハンドルを取得 //GetFocus(); int MX=Mem_PntXY.x-ScreenWidth/2; int MY=Mem_PntXY.y; GetCursorPos(&Pnt); SetCursorPos(MX,MY); mouse_event(MOUSEEVENTF_LEFTDOWN,MX ,MY, 0, 0); //mouse_event(MOUSEEVENTF_MOVE, 0, 0, 0, 0); mouse_event(MOUSEEVENTF_LEFTUP, MX, MY, 0, 0); } }else{ if(flagcounter==5) { // RightDragFlag=0; // ウィンドウを最前面に SetForegroundWindow(hTarget2[1]); // フォーカスがあるウィンドウハンドルを取得 //GetFocus(); int MX=Mem_PntXY.x-ScreenWidth/2; int MY=Mem_PntXY.y; SetCursorPos(MX,MY); mouse_event(MOUSEEVENTF_LEFTDOWN,MX ,MY, 0, 0); //mouse_event(MOUSEEVENTF_MOVE, 0, 0, 0, 0); mouse_event(MOUSEEVENTF_LEFTUP, MX, MY, 0, 0); } } pts=MAKEPOINTS(lp); if(flagcounter==5 && RightDragFlag==1) { SetCursorPos(100,200); mouse_event(MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0); //mouse_event(MOUSEEVENTF_MOVE, 0, 0, 0, 0); mouse_event(MOUSEEVENTF_LEFTUP, 0, 0, 0, 0); //char str[100]; //sprintf(str,"X=%d:Y=%d",Mem_PntXY.x,Mem_PntXY.y); //TextOut(GetDC(hWnd),0,0,str,strlen(str)); } InvalidateRect(hWnd,NULL,TRUE); break; case WM_LBUTTONDOWN://左クリックされたら { //if(flagcounter<3) { bCap = TRUE; SetCapture(hWnd); SetCursor(LoadCursor(hInst, "MYCURSOR")); pts = MAKEPOINTS(lp); ShowPoint(hWnd,pts); InvalidateRect(hWnd, NULL, TRUE); //MessageBox(hTarget2[1],"MOUSE CLICK EVENT OCCURED","OK?",MB_OK); } //if(flagcounter==4) //static int flag=0; break; } case WM_RBUTTONDOWN://右クリックされたら //if(GetAsyncKeyState(VK_RSHIFT)<0) { if(flagcounter==5){ GetCursorPos(&Mem_PntXY); } } break; case WM_RBUTTONUP: break; case WM_MOUSEMOVE: if(GetAsyncKeyState(VK_RBUTTON)<0) { RightDragFlag=1; }else{ RightDragFlag=0; } if (bCap) //&& flagcounter<3) { SetCursor(LoadCursor(hInst, "MYCURSOR")); pts = MAKEPOINTS(lp); ShowPoint(hWnd, pts); } else SetCursor(LoadCursor(NULL, IDC_ARROW)); break; case WM_LBUTTONUP: //if(flagcounter==4) // PostMessage(hTarget2[1],WM_LBUTTONUP,NULL,(MouseY<<8) | (MouseX-ScreenWidth/2)); //else { SetCursor(LoadCursor(NULL, IDC_ARROW)); pts = MAKEPOINTS(lp); pt.x = pts.x; pt.y = pts.y; ClientToScreen(hWnd, &pt); hTarget = WindowFromPoint(pt); } if (hTarget == NULL || hTarget==hWnd) { // MessageBox(hWnd, "失敗です", "失敗", MB_OK); //return (DefWindowProc(hWnd, msg, wp, lp)); }else if(hTarget!=NULL && hTarget!=hWnd && flagcounter<4){ if(flagcounter==0) { hTarget2[0]=hTarget; flagcounter=1; } else if(flagcounter==1) { hTarget2[1]=hTarget; flagcounter=2; } if(flagcounter==1) { SetWindowText(hTarget2[0], "ソースウィンドウ"); MoveWindow( hTarget2[0], // ウィンドウのハンドル ScreenWidth/2, // 横方向の位置 0, // 縦方向の位置 ScreenWidth/2, // 幅 ScreenHeight-200, // 高さ TRUE // 再描画オプション ); //flagcounter=1; } else if(flagcounter==2) { SetWindowText(hTarget2[1], "送信先ウィンドウ"); flagcounter=3; MoveWindow( hTarget2[1], // ウィンドウのハンドル 0, // 横方向の位置 0, // 縦方向の位置 ScreenWidth/2, // 幅 ScreenHeight-200, // 高さ TRUE // 再描画オプション ); } char str[100]; sprintf(str,"flagcounter=%d",flagcounter); TextOut(GetDC(hWnd),0,100,str,strlen(str)); } //if(flagcounter==5) { ReleaseCapture(); bCap = FALSE; } InvalidateRect(hWnd, NULL, TRUE); break; case WM_CLOSE: DestroyWindow(hWnd); break; case WM_DESTROY: PostQuitMessage(0); break; default: return (DefWindowProc(hWnd, msg, wp, lp)); } return 0L; }

試したこと・調べたこと

  • teratailやGoogle等で検索した
  • ソースコードを自分なりに変更した
  • 知人に聞いた
  • その他
上記の詳細・結果

case WM_RBUTTONDOWN://右クリックされたら

//if(GetAsyncKeyState(VK_RSHIFT)<0) { if(flagcounter==5){ GetCursorPos(&Mem_PntXY); if(flagcounter==5) { // RightDragFlag=0; // ウィンドウを最前面に SetForegroundWindow(hTarget2[0]); // フォーカスがあるウィンドウハンドルを取得 GetFocus(); int MX=Mem_PntXY.x-ScreenWidth/2; int MY=Mem_PntXY.y; GetCursorPos(&Pnt); SetCursorPos(MX,MY); mouse_event(MOUSEEVENTF_LEFTDOWN,MX ,MY, 0, 0); //mouse_event(MOUSEEVENTF_MOVE, 0, 0, 0, 0); mouse_event(MOUSEEVENTF_LEFTUP, MX, MY, 0, 0); } } }

ここで入力するためにソースを弄ったので合っているかは分からないですので勘でものを言うのですが
失礼します。)
上のようにソースをいじるとマウスカーソルが恐らく左ウィンドウで固まるか、
あるいは、左右のウィンドウが画面上から消えます。

補足

Windows11 home,Memory16GB,VisualC++2008

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

hiroki-o

2024/02/12 12:57

現象を再現するために確認します。 1. 以下の変数はグローバルでしょうか?型は? ScreenWidth ScreenHeight bCap flagcounter Pnt 2. ShowPoint関数は自作関数でしょうか?何かのAPIでしょうか?
littlestream

2024/02/12 13:09

hiroki-oさん、コメントありがとうございます。 int ScreenWidth=0,ScreenHeight=0; static(?何故かstatic) int flagcounter=0; BOOL bCap = FALSE; はグローバルです。 Pntはローカルですが、VC++2008のメインのソース(しかないですが) 検索しても現在のソースにはどこにも宣言が見当たらなかったです。 なので、もしかしたらリビルドしたらエラーが出るかもです。 ShowPoint関数は情けないですが、猫でも分かるWindowプログラミング内のソースの流用です。
hiroki-o

2024/02/12 14:34

質問は、 1. TAKABO-SOFTのEdgeというソフトにフォーカスがある状態でマウスを右クリックすると、マウスカーソルやウィンドウが制御できなくなるので、その解決方法 2. Shiftキーとマウスクリックの同時判定方法 の2点でしょうか? 作った本人がPntが何だかわからないと、私にもわからないので、ビルドが通らないので現象を再現できません。 ちなみに、ShowPoint関数は「猫でもわかるプログラミング」から持ってきました。
littlestream

2024/02/13 03:51

hiroki-oさん、 Pntは、恐らく一時的なGetCursorPosによる マウスカーソルの取得用変数です。
littlestream

2024/02/13 04:35

PntはPOINT型で宣言されたはずです。 どこかでMAKEPOINTS(lp)の戻り値に代入して使われていたので バグの温床だと勝手に判断して使わなくなった可能性があります。
guest

回答1

0

ベストアンサー

いくつかの問題があるように思います。まず、右クリックと左クリックを区別するための特定の条件や処理が見当らない気がします。そのため、右クリックが行われた直後でも、それを左クリックとして扱うことはできません。
また、マウスの動作を制御するための SetCursorPos と mouse_event を使用していますが、これらの関数は非推奨となっています。代わりに、SendInput 関数を使用することが推奨します。
さらに、Shiftキーとマウスクリックとの同時判定についても、それを実現するためのコードがありません。
このような機能を実現するためには、WinAPIのマウスイベントを検出し、それに応じて処理を行う必要があります。具体的には、WM_MOUSEMOVE、WM_LBUTTONDOWN、WM_LBUTTONUP、WM_RBUTTONDOWN、WM_RBUTTONUP などのマウス関連のメッセージを処理する必要があります。
Shiftキーとの同時判定を行うには、GetAsyncKeyState 関数を使用して Shiftキーの状態を確認し、その結果に応じて処理を行うのがベターだと思います。
サンプルを載せておくので、このコードを参考に必要な機能を追加してください。

case WM_RBUTTONDOWN: // 右クリックされたら { if (GetAsyncKeyState(VK_SHIFT) < 0) // Shiftキーが押されているかチェック { // Shiftキーとの同時判定 // ここにShiftキーと右クリックが同時に押されたときの処理を追加 } else { // 単独の右クリックが行われたときの処理 } } break; case WM_LBUTTONDOWN: // 左クリックされたら { if (GetAsyncKeyState(VK_SHIFT) < 0) // Shiftキーが押されているかチェック { // Shiftキーとの同時判定 // ここにShiftキーと左クリックが同時に押されたときの処理を追加 } else { // 単独の左クリックが行われたときの処理 } } break;

投稿2024/02/13 00:42

shoshinsha123

総合スコア215

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

littlestream

2024/02/13 03:56

shoshinsha123さん、そうですね。Shiftキーとマウスクリックの処理は、まだ実装していませんでした。 それを実現しようとまではいかなかったのは、まだテストプログラムの状態だったからというのも ありました。少しヒントを貰ったので今からSendInputも含めてプログラムを組んでみます。
littlestream

2024/02/13 05:13

とりあえず、作成中のアプリの画面上からマウスの左ボタンのドラッグと LSHIFTキーのドラッグ中に右側の画面上でマウスの右ボタンをドラッグしたら うまくうまく左側の画面と右側の画面と同期した座標にマウスカーソルが動きました。 ありがとうございます。あとは、どうすればペンでクリックした状態にするかという問題だけです。 個人的には左側のSHIFTキーをよく使うのとAキーが近くにあるのとAddのAという意味でも SHIFT+左クリック+右ドラッグ+Aキーで描画にしてみるつもりです。
littlestream

2024/02/13 08:09

SendInputでも実装しましたが、 マウスの右クリックした状態でどうあがいても、どうやら マウスが左クリックしたようにならない気がしてきました。やはり、これは難しすぎると 思って鬼門として避けてきた(DLLは必要?)のマウスフックが必要な気がします。
littlestream

2024/02/13 08:19 編集

case WM_RBUTTONDOWN://右クリックされたら if(GetAsyncKeyState(VK_SHIFT)<0) { static POINT Pnt={0}; if(flagcounter==5){ GetCursorPos(&Mem_PntXY); if(flagcounter==5) { // RightDragFlag=0; // ウィンドウを最前面に SetForegroundWindow(hTarget2[1]); // フォーカスがあるウィンドウハンドルを取得 GetFocus(); GetCursorPos(&Pnt); GetCursorPos(&Pnt); int MX=Pnt.x-ScreenWidth/2; int MY=Pnt.y; INPUT inp[2]={0}; inp[0].type = INPUT_MOUSE; inp[0].mi.dx = MX * (65535 / ScreenWidth); inp[0].mi.dy = MY * (65535 / ScreenHeight); inp[0].mi.dwFlags = 0;//MouseState(); inp[0].mi.dwExtraInfo = GetMessageExtraInfo(); //マウスの左ボタンを押す inp[1].type = INPUT_MOUSE; inp[1].mi.dwFlags = MOUSEEVENTF_LEFTDOWN; inp[1].mi.dx = 0; inp[1].mi.dy = 0; inp[1].mi.mouseData = 0; inp[1].mi.dwExtraInfo = 0; inp[1].mi.time = 0; SendInput(1, inp, sizeof(inp));
littlestream

2024/02/14 03:10

まだまだ自分の実力では難しいのを感じました。 しばらくしたらプログラムに取り組みたいです。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.30%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問