Win32のサブクラス化について – プログラミング – Home

Win32のサブクラス化について
 
通知
すべてクリア

[解決済] Win32のサブクラス化について


saitama
 saitama
(@saitama)
ゲスト
結合: 21年前
投稿: 12
Topic starter  

Win32のサブクラス化でつまってしまいました。
お知恵をお貸しください。

ボタンを作成、ボタンをサブクラス化し
ボタンが押された時の処理を置き換えたコールバック内で行う

というものです。
ボタンはメインウィンドウに配置します。

具体的な例だと置き換えたコールバック内でヘルプダイアログを呼び出します

以下 メインウィンドウコールバック
これは単純にすべてをメインウィンドウコールバック内に記述したものです

#define IDB_TEST_PUSH
(2000)

LRESULT CALLBACK MainWindowProcedure(HWND hWindow, UINT Message, UINT wParam,
LONG lParam)
{
switch ( Message ) {
case WM_CREATE:
// ボタン作成
CreateWindow(
TEXT(BUTTON),
TEXT(test button),
WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON,
10, 90, 50, 20,
hWindow,
(HMENU) IDB_TEST_PUSH,
((LPCREATESTRUCT) (lParam))->hInstance,
NULL);
break;
case WM_COMMAND:
switch ( LOWORD(wParam) ) {
case IDB_TEST_PUSH:
// ボタンが押されるとヘルプダイアロ
グを表示
DialogBox(lvar_hInstance,
(LPCTSTR) IDD_ABOUTBOX, hWindow, (DLGPROC) HelpProcedure);
}
break;
default:
break;
}

return ( DefWindowProc(hWindow, Message, wParam, lParam) );
}

上記のものを以下のようにサブクラス化して
コールバック内でボタンがおされたかどうかのメッセージを拾おうとしています

#define IDB_TEST_PUSH
(2000)

LRESULT CALLBACK MainWindowProcedure(HWND hWindow, UINT Message, UINT wParam,
LONG lParam)
{
switch ( Message ) {
case WM_CREATE:
// ボタン作成
CreateWindow(
TEXT(BUTTON),
TEXT(test button),
WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON,
10, 90, 50, 20,
hWindow,
(HMENU) IDB_TEST_PUSH,
((LPCREATESTRUCT) (lParam))->hInstance,
NULL);
break;
g_DefProcedure = (WNDPROC) GetWindowLong(hWindow,
GWL_WNDPROC);
SetWindowLong(hWindow, GWL_WNDPROC, (LONG)
TestButton_CallBackProcedure);
default:
break;
}

return ( DefWindowProc(hWindow, Message, wParam, lParam) );
}

LRESULT CALLBACK TestButton_CallBackProcedure(HWND hWindow, UINT uMessage,
LPARAM lParam, LPARAM lpData)
{
switch ( uMessage ) {
case WM_COMMAND:
switch ( LOWORD(wParam) ) {
case IDB_TEST_PUSH:
// ボタンが押されるとヘルプダイアロ
グを表示
DialogBox(g_hInstance, (LPCTSTR)
IDD_ABOUTBOX, hWindow, (DLGPROC) HelpProcedure);
}
break;
default:
return ( CallWindowProc(g_DefProcedure, hWindow,
uMessage, lParam, lpData) );
break;
}

return ( 0 );
}

しかし、これだとまったくメッセージが回ってきませんでした。(WM_COMMANDすら来ませんでし
た)
ユーザーのボタンに対するアクションはオーナーウィンドウにしか通知されないのでしょうか?
また、これらをコールバック内で解決する場合はどのようにすれば解決できるでしょうか?

以上よろしくお願いします


引用未解決
トピックタグ
暇人
 暇人
(@暇人)
ゲスト
結合: 23年前
投稿: 19
 

GetWindowLongとかが実行されてないですね。
break;がどういう働きをするかヘルプで調べて下さい。
あとウィンドウプロシージャの取得や設定を行っているところですが、どのウインドウの
ウィンドウプロシージャを取ろうとしているのでしょうか?


返信引用
saitama
 saitama
(@saitama)
ゲスト
結合: 21年前
投稿: 12
Topic starter  

あちゃ、失礼しました。
ここに乗せるためにいろい消したときに混じってしまったのでしょう・・
紛らわしくてすみません。

こちらで使っている方にbreakが変な位置にきてGetWindowLongが実行されてない、
ということはありませんので、実行されていることを前提にお願いいたします


返信引用
saitama
 saitama
(@saitama)
ゲスト
結合: 21年前
投稿: 12
Topic starter  

いちおう修正したものを張っておきます。

LRESULT CALLBACK MainWindowProcedure(HWND hWindow, UINT Message, UINT wParam,
LONG lParam)
{
switch ( Message ) {
case WM_CREATE:
// ボタン作成
CreateWindow(
TEXT(BUTTON),
TEXT(test button),
WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON,
10, 90, 50, 20,
hWindow,
(HMENU) IDB_TEST_PUSH,
((LPCREATESTRUCT) (lParam))->hInstance,
NULL);
g_DefProcedure = (WNDPROC) GetWindowLong(hWindow,
GWL_WNDPROC);
SetWindowLong(hWindow, GWL_WNDPROC, (LONG)
TestButton_CallBackProcedure);
break;
default:
break;
}

return ( DefWindowProc(hWindow, Message, wParam, lParam) );
}


返信引用
PATIO
(@patio)
Famed Member
結合: 4年前
投稿: 2660
 

GetWindowLongとSetWindowLongに引き渡しているウインドウハンドルは
ボタンコントロールの物ではないように思えますが、
これではボタンをサブクラス化したことにはならないと思います。

このコードだとボタンの親ウインドウをサブクラス化しているように見えます。

あと疑問に思ったんですが、
ボタンをサブクラス化したいとして、ボタンにWM_COMMANDが来るもんでしょうか?
WM_COMMANDってボタンコントロールが親にBN_CLICKEDを通知した結果、
親ウインドウ側で送出するものではないかと思うんですが。
親がわざわざ通知元にWM_COMMANDを通知するとは思えないんですが、
詳しく調べてみたわけではないので単なる疑問なんですけれど。


返信引用
saitama
 saitama
(@saitama)
ゲスト
結合: 21年前
投稿: 12
Topic starter  

>あとウィンドウプロシージャの取得や設定を行っているところですが、どのウインドウの
ウィンドウプロシージャを取ろうとしているのでしょうか?

すみません、乗せるときにコピペミスしまくりですね;;

えっと、CreateWindowで作成したボタンのプロシージャです
なので

hButton = CreateWindow(
TEXT(BUTTON),
TEXT(test button),
WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON,
10, 90, 50, 20,
hWindow,
(HMENU) IDB_TEST_PUSH,
((LPCREATESTRUCT) (lParam))->hInstance,
NULL);
g_DefProcedure = (WNDPROC) GetWindowLong(hButton,
GWL_WNDPROC);
SetWindowLong(hButton, GWL_WNDPROC, (LONG)
TestButton_CallBackProcedure);

実際はこっちですね;;


返信引用
saitama
 saitama
(@saitama)
ゲスト
結合: 21年前
投稿: 12
Topic starter  

>ボタンをサブクラス化したいとして、ボタンにWM_COMMANDが来るもんでしょうか?
>WM_COMMANDってボタンコントロールが親にBN_CLICKEDを通知した結果、
>親ウインドウ側で送出するものではないかと思うんですが。
登録したコールバック内でブレークポイントをしかけてチェックしてたときに
他のメッセージはいろいろ送られてくるけど、WM_COMMANDとかはさっぱり
送られてこないので、まさか、とはおもっていましたが・・・;;

あと同じような状況として
親の関係が
親ウィンドウ>プッシュボタン
という状況ならWM_COMMANDでボタンIDを拾えますが

親ウィンドウ>グループボックス(BS_GROUPBOX)>プッシュボタン
の場合などは 当然WM_COMMANDで拾えなくなってしまいます。
この場合はどこで拾えばよいのでしょうか?
グループボックスのプロシージャを置き換えてひろうのでしょうか?


返信引用
PATIO
(@patio)
Famed Member
結合: 4年前
投稿: 2660
 

こういう場合は、ボタンの親は親ウインドウにしませんか?
グループボックスとの関係はZオーダーで設定すればいい話ですし、
グループボックスがアクティブになるようなことが無ければ、
Zオーダーが変わることは無いと思うので特に問題は無いと思いますが。


返信引用
saitama
 saitama
(@saitama)
ゲスト
結合: 21年前
投稿: 12
Topic starter  

どうやらそうした方がよさそうですね
結局ボタンの件はボタンクラスをつくってみました。
内部でボタン用の親ウィンドウを生成して、そこでさらにボタン生成。
サブクラス化はボタン用の親ウィンドウプロシージャを置換して
WM_COMMANDの件は解決しました。

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


返信引用

返信する

投稿者名

投稿者メールアドレス

タイトル *

プレビュー 0リビジョン 保存しました
共有:
タイトルとURLをコピーしました