ボタンのハンドル取得から押すまでを詳しく教えてほしいです。

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
おならちゃん。

ボタンのハンドル取得から押すまでを詳しく教えてほしいです。

#1

投稿記事 by おならちゃん。 » 12年前

ボタンのハンドル取得から押すまでを詳しく教えてほしいです。
http://www.ne.jp/asahi/hishidama/home/t ... ckdlg.html
こちらのサイトで、ボタンのHWNDの取得
というところでこのようなサンプルプログラムが書いてありました。

コード:

static BOOL CALLBACK FindSaveButton(
  HWND   hwnd,  // ウィンドウハンドル
  LPARAM lParam // アプリケーション定義の値(今回はボタンのHWNDを返す為のポインター)
)
{
	TCHAR tbuf[1024];
	::GetWindowText(hwnd, tbuf, sizeof(tbuf)); //表示されているテキストを取得
	if (lstrcmp(tbuf, _T("保存(&S)")) == 0) {
		HWND *ret = reinterpret_cast<HWND*>(lParam);
		*ret = hwnd;
		return FALSE; //探索終了
	}

	return TRUE; //探索続行
}
//ダイアログのHWNDから「保存」ボタンのHWNDを取得する
HWND GetSaveButton(HWND hdlg)
{
	HWND hbtn = NULL;
	::EnumChildWindows(hdlg, FindSaveButton, reinterpret_cast<LPARAM>(&hbtn));
	return hbtn;
}
コールバックでstaticに飛んだのはわかるのですが、getwindowtextでボタンも一緒にテキストを探して、
その後の処理がでいまいちわかりません。if文では自分のほしいボタンと比較しているのですか?
その後のreinterpret_castこれは最初にNULLを入れておいたのに何をしているのでしょうか?
*retにHWNDを入れているのもまた意味がわかりません。もともとあったハンドルをそこに入れて、何の意味があるのでしょうか?
後は、SendMessage(ここにボタンのハンドルを入れて,BM_CLICK,0,0)でクリックが可能になるのでしょうか?
色々質問だらけですみません。
順を追いながら説明していただけると、うれしいです。
ご回答よろしくお願いします

アバター
bitter_fox
記事: 607
登録日時: 13年前
住所: 大阪府

Re: ボタンのハンドル取得から押すまでを詳しく教えてほしいです。

#2

投稿記事 by bitter_fox » 12年前

おならちゃん。 さんが書きました: コールバックでstaticに飛んだのはわかるのですが、
飛ぶのはFindSaveButton関数にです、staticにではありません。staticというのはFindSaveButton関数の性質を表している物です。

これはC++の機能(記法)を利用していて分かりにくいと思うのでC言語で書き直してみました。と言っても主にキャスト部分だけですがw

コード:

static BOOL CALLBACK FindSaveButton(
  HWND   hwnd,  // ウィンドウハンドル
  LPARAM lParam // アプリケーション定義の値(今回はボタンのHWNDを返す為のポインター)
)
{
    TCHAR tbuf[1024];
    GetWindowText(hwnd, tbuf, sizeof(tbuf)); //表示されているテキストを取得
    if (lstrcmp(tbuf, _T("保存(&S)")) == 0) {
    	HWND *ret = (HWND*)lParam;
        *ret = hwnd;
        return FALSE; //探索終了
    }
 
    return TRUE; //探索続行
}
//ダイアログのHWNDから「保存」ボタンのHWNDを取得する
HWND GetSaveButton(HWND hdlg)
{
    HWND hbtn = NULL;
    EnumChildWindows(hdlg, FindSaveButton, (LPARAM)&hbtn);
    return hbtn;
}
いかがでしょうか?
おならちゃん。 さんが書きました:getwindowtextでボタンも一緒にテキストを探して、
その後の処理がでいまいちわかりません。if文では自分のほしいボタンと比較しているのですか?
その後のreinterpret_castこれは最初にNULLを入れておいたのに何をしているのでしょうか?
*retにHWNDを入れているのもまた意味がわかりません。もともとあったハンドルをそこに入れて、何の意味があるのでしょうか?
後は、SendMessage(ここにボタンのハンドルを入れて,BM_CLICK,0,0)でクリックが可能になるのでしょうか?
FindSaveButton関数内においてhwndというのは現在注目しているウィンドウ(コントロールなど)のハンドルです。
また、lparamにはGetSaveButton内のhbtnへのアドレスが入っています。
まず、GetWindowText関数でhwndのタイトルを得ます。hwndがボタンの場合、タイトルはボタンに表示されている文字列です。
そのタイトルと「保存(&S)」という文字列とを比較することで保存を行うボタンかどうかを判断しています。
保存を行うボタンならば、retにlparamをHWND*にキャストした物を入れ、
retが指すアドレスの先にhwndを代入して探索を終了します。

おならちゃん。

Re: ボタンのハンドル取得から押すまでを詳しく教えてほしいです。

#3

投稿記事 by おならちゃん。 » 12年前

bitter foxさん
ご回答ありがとう御座いました。
とてもわかりやすかったため、
このプログラムがどんな処理をしているのかが理解できてきた気がします。

ですが、質問が三つほど出来ました。
ご回答よろしくお願いします。
普通に自分で文を書いて、コンパイルしたところ、
_Tという拡張子が見つからないというエラーがでました。
そして、さらに疑問がわいたのですが、
_Tこいつですが、API_Tと検索してもでてきませんでした。
これはどんな役割をしているのでしょうか?
どのような書き方をすればエラーが出ないのでしょうか?

二つ目は、

コード:

EnumChildWindows(hwndTarget,FindSaveButton,(LPARAM)&hbtn);
この部分ですが初め僕は、

コード:

hwnd=EnumChildWindows(hwndTarget,FindSaveButton,(LPARAM)&hbtn);
という様に書いていました。しかしこれではエラーがでました。なのでhbtnをSendMessageで使ってみたのですが、この使い方であっているのでしょうか?

コード:

SendMessage(hbtn,BM_CLICK,0,0);
そして三つ目ですが、
こんな感じの書き方で大きな間違いは無いでしょうか?

コード:

#include <Windows.h>
static BOOL CALLBACK FindSaveButton(
									HWND hwnd,
									LPARAM lParam
									)
{
	TCHAR tbuf[1024];
	GetWindowText(hwnd, tbuf, sizeof(tbuf));
	if(lstrcmp(tbuf,_T("開始(&S)"))==0){
		HWND *ret = (HWND*)lParam;
		*ret = hwnd;
		return FALSE;
	}
	return TRUE;
}

int main()
{   
	HWND hwndTarget,hwnd,hbtn=NULL;

    hwndTarget=FindWindow(TEXT(""),NULL);
	EnumChildWindows(hwndTarget,FindSaveButton,(LPARAM)&hbtn);
    hwndTarget = FindWindowEx(hwndTarget, 0, "Edit", 0);
	SendMessage(hwndTarget, WM_SETTEXT, 0, (LPARAM)("処理終了です!"));
	SendMessage(hbtn, BM_CLICK, 0,0);
}
エラーがでたのは_Tの部分だけでした。

ご回答よろしくお願いします。

アバター
bitter_fox
記事: 607
登録日時: 13年前
住所: 大阪府

Re: ボタンのハンドル取得から押すまでを詳しく教えてほしいです。

#4

投稿記事 by bitter_fox » 12年前

おならちゃん。 さんが書きました: 普通に自分で文を書いて、コンパイルしたところ、
_Tという拡張子が見つからないというエラーがでました。
そして、さらに疑問がわいたのですが、
_Tこいつですが、API_Tと検索してもでてきませんでした。
これはどんな役割をしているのでしょうか?
どのような書き方をすればエラーが出ないのでしょうか?
_Tというのは、VSでマルチバイト文字を使用するかユニコードを使用するかの設定によって一意に定まるようにしてくれるマクロです。
http://victreal.com/Junk/_T/index.html

VS以外の環境でもって定義されてない場合は_T("hogehoge")を"hogehoge"にしてください。
おならちゃん。 さんが書きました: 二つ目は、

コード:

EnumChildWindows(hwndTarget,FindSaveButton,(LPARAM)&hbtn);
この部分ですが初め僕は、

コード:

hwnd=EnumChildWindows(hwndTarget,FindSaveButton,(LPARAM)&hbtn);
という様に書いていました。しかしこれではエラーがでました。なのでhbtnをSendMessageで使ってみたのですが、この使い方であっているのでしょうか?

コード:

SendMessage(hbtn,BM_CLICK,0,0);
EnumChildWindowsの戻り値はBOOLなのでHWNDの変数に代入してはいけません。
http://msdn.microsoft.com/ja-jp/library/cc410802.aspx

今回の場合はEnumChildWindowsの呼び出しの結果見つかった場合のウィンドウハンドルはhbtnに代入されています。
ですので、その使い方であっています。

また、見つからなかった場合はEnumChildWindowsは0を返すのでifで成功時と失敗時を分岐させておけばより良いと思います。

おならちゃん。 さんが書きました: そして三つ目ですが、
こんな感じの書き方で大きな間違いは無いでしょうか?

コード:

#include <Windows.h>
static BOOL CALLBACK FindSaveButton(
									HWND hwnd,
									LPARAM lParam
									)
{
	TCHAR tbuf[1024];
	GetWindowText(hwnd, tbuf, sizeof(tbuf));
	if(lstrcmp(tbuf,_T("開始(&S)"))==0){
		HWND *ret = (HWND*)lParam;
		*ret = hwnd;
		return FALSE;
	}
	return TRUE;
}

int main()
{   
	HWND hwndTarget,hwnd,hbtn=NULL;

    hwndTarget=FindWindow(TEXT(""),NULL);
	EnumChildWindows(hwndTarget,FindSaveButton,(LPARAM)&hbtn);
    hwndTarget = FindWindowEx(hwndTarget, 0, "Edit", 0);
	SendMessage(hwndTarget, WM_SETTEXT, 0, (LPARAM)("処理終了です!"));
	SendMessage(hbtn, BM_CLICK, 0,0);
}
エラーがでたのは_Tの部分だけでした。
いいんじゃないでしょうか。

おならちゃん。

Re: ボタンのハンドル取得から押すまでを詳しく教えてほしいです。

#5

投稿記事 by おならちゃん。 » 12年前

bitter foxさん ご回答ありがとう御座いました!!!
マルチバイト文字とunicode文字の違いがやっとはっきりしました。!
なんの違いなんだろうなぁーこれと思って今までやってきました。

色々とああ!なるほど!っと納得させて頂き
ありがとう御座いました。
拡張子じゃなくて識別子でした。すみません。
無事includeしたら出来ました。

本当に丁寧にご回答いただきありがとう御座いました。

閉鎖

“C言語何でも質問掲示板” へ戻る