SendMessageの使い方について

このQ&Aのポイント
  • SendMessageを使ってプログラムを完成させたいのですが、どこを修正すれば良いのでしょうか?
  • 上記のサンプルプログラムを実行すると、SendMessageが動いていないため、新規に作成したカーソルが表示されないと思われます。
  • 以下のように修正すれば、SendMessageを使わなくても正しく動くことは分かっています。case WM_SETCURSOR:   hCrsrButton = LoadCursor((HINSTANCE)GetWindowLong(hButton,GWL_HINSTANCE),MAKEINTRESOURCE(IDC_BUTTON));SetCursor(hCrsrButton);break;
回答を見る
  • ベストアンサー

SendMessageの使い方について

http://kerochan.no-ip.com/vcsdk/letsprog/chap30.htm 上記のサンプルプログラムを実行すると、SendMessageが動いていないため、新規に作成したカーソルが表示されないと思われます。 SendMessageを使ってプログラムを完成させたいのですが、 どこを修正すれば良いのでしょうか? お分かりの方、どうぞよろしくお願いします。 ************************** 以下のように修正すれば、SendMessageを使わなくても正しく動くことは分かっています。 case WM_SETCURSOR:    hCrsrButton = LoadCursor((HINSTANCE)GetWindowLong(hButton,GWL_HINSTANCE),MAKEINTRESOURCE(IDC_BUTTON)); SetCursor(hCrsrButton); break;

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

  • ベストアンサー
  • taka_tetsu
  • ベストアンサー率65% (1020/1553)
回答No.3

//不要 //#define WM_FIRST WM_USER 省略 WNDPROC OrgProc; //追加 UINT guiFirst; //登録メッセージ 省略 ------------------------------ case WM_INITDIALOG: 省略 //メッセージIDの登録 guiFirst = RegisterWindowMessage("sukinamojiretsu"); //登録したメッセージをボタンに送信 //SendMessage(hButton,WM_FIRST,0L,0L); SendMessage(hButton,guiFirst,0L,0L); break; 省略 ------------------------------ 省略 //guiFirstは、定数ではないのでcase文で判断不能のため //ifで個別に確認する必要あり if(msg == guiFirst) { hCrsrButton = LoadCursor((HINSTANCE)GetWindowLong(hButton,GWL_HINSTANCE),MAKEINTRESOURCE(IDC_BUTTON)); return TRUE; } switch(msg){ //削除 //case WM_FIRST: //hCrsrButton = LoadCursor((HINSTANCE)GetWindowLong(hButton,GWL_HINSTANCE),MAKEINTRESOURCE(IDC_BUTTON)); //break; case WM_SETCURSOR: SetCursor(hCrsrButton); break; 省略 という感じかな?

VitaminBB
質問者

お礼

コードありがとうございます。 期待どおり動きました。

VitaminBB
質問者

補足

オリジナルが動かないことが不思議です。 あれから調べてみたのですが、SendMessageの使い方も特に問題ないと思うのですが、やはり”既存”のコントロールに使ったことがまずいのでしょうか? RegisterWindowMessageも面白い関数ですね。 "sukinamojiretsu"を登録してもその後”sukinamojiretsu”そのものは使わないのですね。

その他の回答 (3)

  • taka_tetsu
  • ベストアンサー率65% (1020/1553)
回答No.4

>オリジナルが動かないことが不思議です。 VitaminBBさんのOSはXPですか? サンプルはWinMe以前のようですし。 バージョンが変わって内部処理が変更になったのでしょう。 >やはり”既存”のコントロールに使ったことがまずいのでしょうか? ブラックボックス化されているウィンドウには WM_USERは使えないということで。 つまり、サンプルのバグです。 "sukinamojiretsu"なんですが、他のプロセスがRegisterWindowMessageで登録した文字列とかぶらなければ、何でもかまいません。 同じ文字列を使用すると、同じメッセージIDが返されますのでおかしなことになるかもしれません。 他の使い方としては、プロセス間で独自のメッセージIDでメッセージを送信するときに、同一の文字列でRegisterWindowを呼び出して使用します。

VitaminBB
質問者

お礼

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

VitaminBB
質問者

補足

>VitaminBBさんのOSはXPですか? WIN98 VC++6.0です >つまり、サンプルのバグです。 そういうことで納得です。

  • taka_tetsu
  • ベストアンサー率65% (1020/1553)
回答No.2

あと、このサンプル、WM_FIRSTにWM_USERを使ってるのはまずいですね。 既存のコントロールに対して独自のメッセージを投げたいときは、WM_USER(およびそれ以降)は使わないほうがいいですよ。 理由は、コントロール内部でも使用される可能性があるからです。作ったときは動いていても、Windowsのバージョンが変わって動作が変わるかもしれませんし。 今回のようなケースでは、RegisterWindowMessageを使用してメッセージIDを取得し、それを使用するようにします。 もし、PostMessageにしても動かなかったらこちらも試してみてください。

VitaminBB
質問者

お礼

RegisterWindowMessageの使い方が分かりません。 今回の例で具体的にどう記述すれば良いか教えていただけると助かります。

  • taka_tetsu
  • ベストアンサー率65% (1020/1553)
回答No.1

SendMessageじゃなくて、PostMessageにすれば動くと思います。 あとは、SendMessageの次の行のbreak;を return TRUE; に変えてみるとか。 未確認です。

VitaminBB
質問者

お礼

回答ありがとうございます。 やってみましたが、変わり有りませんでした。

関連するQ&A

  • カーソルを手に変更

    スタティックウインド上でカーソルを手にしているところなんだけど カーソルが手になるはずが透明になっています。 その他はうまく行っているから、スタティックウインドの外に出ると カーソルは矢印に戻ります。 ソースを直してください。 #include <windows.h> HINSTANCE hInstanceForCursor; ~ WinMain() で  wc.hInstance = hInstance;  hInstanceForCursor = hInstance; ~ WndProc()  case 101:   if(ChildWindowFromPoint(hWnd, pt) == hSWnd){    hCursor = LoadCursor(hInstanceForCursor, IDC_HAND);    SetCursor(hCursor);   }else SetCursor((HCURSOR)IDC_ARROW);  break;

  • マウスの動き

    どなたか答えてください。 WM_LBUTTONDOWNにて、 マウスの位置がウィンドウの右端だった場合、 サイズ変更が出来るようにしたいのです。 ですので処理に、 SetCursor(LoadCursor(NULL, IDC_SIZEWE)); SendMessage(hWnd,WM_SYSCOMMAND,SC_SIZE | WMSZ_LEFT,0); を入れサイズ変更が出来るようにしました。 ですがそのときマウスが上下に動くのが動くのが気になります(マウスカーソルがウィンドウの外に出ることもあるので)。 それを解消したいのですがどのようにしたらいいかわかりません。 どなたかいい方法を知らないでしょうか?

  • LoadImageとSetCursorについて

    開発環境は,Visual studio 2008 Professional Edition/ Visual C++ 2008/Windows Vista/です。 Windowsプログラミングをしています。 猫でもわかる~を読んだ程度のレベルです。 現在,ツールバーは作成し,今後以下のような動作を実現させたいと考えています。 1)ボタンをクリックしたら,自作のカーソルファイル(cursor1.cur)を読み込んでその形にカーソルが変わる。 2)そのカーソルのまま,ドラッグ&ドロップし,フォームにその図形を置く(描く)。 3)図形を置いたら,カーソルを元に戻す。 このような流れです。 たぶん,LoadImage()でカーソルファイルを読み込み, SetCursor()でカーソルの形を変えると思うのですが, 以下のようなプログラムを書いてもうまくいきませんでした。 LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp) { INITCOMMONCONTROLSEX cc; static HWND hTool; static HMENU hMenu; switch (msg) { case WM_CREATE: hMenu = GetMenu(hWnd); cc.dwSize = sizeof(INITCOMMONCONTROLSEX); cc.dwICC = ICC_BAR_CLASSES; InitCommonControlsEx(&cc); hTool = MyCreateToolbar(hWnd); break; case WM_COMMAND: switch (LOWORD(wp)) { case ID_BUTTON1: HCURSOR hcur; hcur = (HCURSOR)LoadImage(NULL, MAKEINTRESOURCE(IDC_CURSOR1), IMAGE_CURSOR, 0, 0, LR_SHARED); SetCursor(hcur); //ドラッグ&ドロップ処理 //hcur = (HCURSOR)GetClassLongPtr(hwnd, GCL_HCURSOR); //カーソルを元に戻す break; 一部分ですが,このような感じです。 ちなみにLoadImageの第一引数をNULLからhInst(HINSTANCE hInst;グローバル変数)に変えたところ,式を定義できないなどのエラーがでました。 ウインドウクラスの定義は, //ウィンドウ・クラスの登録 ATOM InitApp(HINSTANCE hInst) { WNDCLASSEX wc; wc.cbSize = sizeof(WNDCLASSEX); wc.style = CS_HREDRAW | CS_VREDRAW; wc.lpfnWndProc = WndProc; //プロシージャ名 wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = hInst;//インスタンス wc.hIcon = NULL; wc.hCursor = NULL; wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); wc.lpszMenuName = TEXT("MYMENU"); //メニュー名 wc.lpszClassName = szClassName; wc.hIconSm = NULL; return (RegisterClassEx(&wc)); } 以上の通りです。 ボタンを押してもうんともすんともいいません。 例えば,ウインドプロシージャのところを, case ID_BUTTON1: SendMessage(hWnd, WM_CLOSE, 0, 0); break; と変更したら,普通に終了メッセージが出ます。 プログラム上どこがおかしいのか教えてください。 よろしくお願いします。 ※字下げされずに読みづらくてすいません。

  • ドラッグしたときにマウスカーソルを変更するには?

    こんにちは。 VC6.0 MFCで開発しています。 マウスカーソルの形状をウィンドウをドラッグしているときとしていないときで 違ったものに変更したいのですが、うまくいきません。 ソースはこんなふうにしています。 ↓ void CTest::OnLButtonDown(UINT nFlags, CPoint point) { //変更する SetCursor(AfxGetApp()->LoadCursor( IDC_CUR2 )); CDialog::OnLButtonDown(nFlags, point); } void CTest::OnLButtonUp(UINT nFlags, CPoint point) { //元に戻す SetCursor(AfxGetApp()->LoadCursor( IDC_CUR1 )); CDialog::OnLButtonUp(nFlags, point); } どうぞ宜しくお願いします。

  • WM_CTLCOLORDLG

    WIN32、VC++2005で開発中です。 ダイアログが複数あり各々に違う背景色を着けたい場合、 下記のようなプログラムを書いたのですが、IF文の中に行けません。 「i」には0が入ってしまうんですが、なぜでしょうか? ほかにいい方法ありませんか? ボタンコントロールではちゃんと判別してくれました。 case WM_CTLCOLORDLG: i = GetWindowLong( (HWND)lParam, GWL_ID ); if ( i == IDD_ICHI_D ) { //位置出し画面描画 return (BOOL)CreateSolidBrush( RGB( 255,170,255 )); } break; WIN32初心者なのでなるべくわかりやすくご教授お願いします。

  • C言語でのEDITコントロールからの数字の取得について質問があります。

    C言語でのEDITコントロールからの数字の取得について質問があります。 case WM_CREATE: hwndTempo = CreateWindowEx(WS_EX_CLIENTEDGE, TEXT("EDIT") , TEXT("120") , WS_CHILD | WS_VISIBLE | ES_LEFT | ES_NUMBER , 0 , 0 , 200 , 30 , hWnd, (HMENU)3, (HINSTANCE)GetWindowLong(hWnd, GWL_HINSTANCE) , NULL); break; このようにEDITコントロールを作成したとき、どのように書かれている数字(初期設定では120)を取得することができるのでしょうか? ためしに文字型で取得してから変換しようと思い、 ボタンを押した時の処理として char szEdit1[128]; GetDlgItemText(hWnd, hwndTempo, szEdit1,64); と入力してみたのですが、 「error C2664: 'GetDlgItemTextW' : 2 番目の引数を 'HWND' から 'int' に変換できません。」 となってしまいました。 最近始めたばかりでインスタンスやウィンドウハンドルの指定などが間違っているのではないかと思いますが、いまひとつよくわかりません。 「GetDlgItemText」の行をコメントアウトすればエディットとボタンコントロールは正常に表示されます。 開発環境がVisual C++ 2008 Express Editionであるため、リソースエディタは使っていません。 サンプルの多くがIDC_EDIT1を使っているのでどう参考にすればよいか良く見えません。 この方法を学習したら「GetDlgItemInt」を使って直接取得してみる予定です。 出来れば単純なサンプルソースを提示していただけると助かります。 ではよろしくお願いします。

  • ダイアログボックスで指定したサイズどおり表示されない

    ダイアログボックスで指定したサイズがメイン上では約2倍の大きさになって表示されてしまい、困っています。 メニューリソースは以下のとおりです。 MYDLG DIALOG DISCARDABLE 25, 50, 100, 150 STYLE WS_VISIBLE | WS_CHILD | DS_CONTROL CAPTION "Dialog" FONT 9, "MS Pゴシック" BEGIN END WndProc内にダイアログを貼り付けています。 if(hDlgWnd) break; hDlgWnd = CreateDialog((HINSTANCE)GetWindowLong(hWnd,GWL_HINSTANCE),"MYDLG",hWnd,DialogProc); それが実際にウィンドウを開くとダイアログがだいたいですが(50,115,200,340)のように表示されてしまいます。 VC++ Ver.6.0です。コンパイラ等の問題でしょうか。 ご存知の方、宜しくお願いします。

  • c++ 電卓制作

    今使ったのはMicrosoft Visual Studio 2010のアプリ 以下のプログラムはダイアログボックス表示で0から9のボタン入れでます、普通の電卓作りたいです、計算のプログラムわからないので、どうすればいいですか? #include <windows.h> #include "resource.h" #include <tchar.h> // プロトタイプ宣言 BOOL CALLBACK DlgWndProc ( HWND , UINT , WPARAM , LPARAM ) ; void sub( int no , HWND hWnd ) ; static int cnt ; int a , b ; static int c ; // エントリポイント int APIENTRY WinMain ( HINSTANCE hInstance , HINSTANCE hPrevInstance , LPSTR lpCmdLine , int nCmdShow ) { DialogBox(hInstance , MAKEINTRESOURCE(IDD_DIALOG1) , NULL , (DLGPROC) DlgWndProc ) ; return 0 ; } /* ------ ダイアログボックスウインドウプロシージャ ----- */ BOOL CALLBACK DlgWndProc ( HWND hWnd , UINT message , WPARAM wParam , LPARAM lParam ) { TCHAR s[80] ; switch( message ) { case WM_INITDIALOG : cnt = 0 ; return TRUE ; case WM_COMMAND : switch ( LOWORD(wParam) ) { case IDC_1 : sub ( 1 , hWnd ) ; return TRUE ; case IDC_2 : sub ( 2 , hWnd ) ; return TRUE ; case IDC_3 : sub ( 3 , hWnd ) ; return TRUE ; case IDC_4 : sub ( 4 , hWnd ) ; return TRUE ; case IDC_5 : sub ( 5 , hWnd ) ; return TRUE ; case IDC_6 : sub ( 6 , hWnd ) ; return TRUE ; case IDC_7 : sub ( 7 , hWnd ) ; return TRUE ; case IDC_8 : sub ( 8 , hWnd ) ; return TRUE ; case IDC_9 : sub ( 9 , hWnd ) ; return TRUE ; case IDC_0 : sub ( 0 , hWnd ) ; return TRUE ; case IDC_CLOSE : EndDialog( hWnd , 0 ) ; return TRUE ; default : return FALSE ; } default : return FALSE ; } } /* ------------------------------------- */ /* 表示 */ /* ------------------------------------- */ void sub( int no , HWND hWnd ) { TCHAR s[20] ; cnt *= 10 ; cnt += no ; wsprintf( s , TEXT("%d") , cnt ) ; SetWindowText( GetDlgItem(hWnd , IDC_EDIT1) , s ) ; }

  • excelVBAからC#へsendmessage

    excelのVBAから文字列をsendmessageで C#のプログラムに文字列を渡せないかと考えています。 ネットで調べつつなんとか作ってみたのですが、 どうしてもうまく動作しません。 変な文字列が表示されてしまいます。 どこがおかしいか教えて頂けないでしょうか。 windows7、Excel2010、.netFramework4になります。 ※※※excel VBA側プログラム※※※※※※※※※※※※ //外部functionを使いますよ Declare Function SendMessage Lib "user32.dll" Alias "SendMessageA" _ (ByVal hwd As Long, ByVal Msg As Long, ByVal wpara As Long, lpara As COPYDATASTRUCT) As Long //構造体 Public Type COPYDATASTRUCT dwData As Long cbData As Long lpData As String End Type //メッセージを送信するsub Public Sub sousin() Dim result As Longv Dim hWnd As Long Dim cds As COPYDATASTRUCT Dim str As String Dim strby() As Byte Dim length As Long  ~ ウィンドウハンドルの取得 ~ str = "test" strby = StrConv(str, vbFromUnicode) length = UBound(strby) - LBound(strby) + 1 cds.dwData = 0 cds.lpData = str cds.cbData = length result = SendMessage(hWnd, WM_COPYDATA, 0, cds) End Sub ※※※C#側プログラム※※※※※※※※※※※※※※※ //構造体 public struct COPYDATASTRUCT { public long dwData; public long cbData; public string lpData; } //WndProc関数 protected override void WndProc(ref Message m) { switch (m.Msg) { case WM_COPYDATA: COPYDATASTRUCT mystr = new COPYDATASTRUCT(); Type mytype = mystr.GetType(); mystr = (COPYDATASTRUCT)m.GetLParam(mytype); label1.Text = mystr.lpData;           ←※無茶苦茶な文字列になります break; } base.WndProc(ref m); }

  • [excel vba] マウスポインタの変更

    お世話になります。 excel vba でマウスポインタの変更を教えてほしいのですが、「Application.Cursor」で使用可能な  ・xlDefault  ・xlNorthwestArrow  ・xlIBeam   ・xlWait 以上の4つではなく、クロス型(+のような形)のポインタに変更することはできないでしょうか? 図形をコピー⇒貼り付けするタイミングでこのマウスポインタ型に変更できたらと思っています。 windowsAPIを使用した下記の方法では、一時的には可能ですが、マウスポインタを動かすと元に戻ってしまいます。 書き方、使用方法など間違っているのでしょうか。 -----winAPIを使用したソース--------------------------------------------------------- Private Declare Function LoadCursor Lib "user32" Alias "LoadCursorA" (ByVal hInstance As Long, ByVal lpCursorName As Long) As Long Private Declare Function SetCursor Lib "user32" (ByVal hCursor As Long) As Long Private Const IDC_CROSS = 32515& Sub CursorChangeTest() Dim i As Double Dim waitTime As Variant SetCursor (LoadCursor(0, IDC_CROSS)) 'ループ処理 For i = 1 To 5 waitTime = Now + TimeValue("0:00:01") Debug.Print "きました " & i Application.Wait waitTime Next i End Sub ------------------------------------------------------------------------------------ よろしくお願いします。