モードレスダイアログ内のコントロールでのキー取得 – プログラミング – Home

モードレスダイアログ内のコントロールで...
 
通知
すべてクリア

[解決済] モードレスダイアログ内のコントロールでのキー取得


qutto
 qutto
(@qutto)
ゲスト
結合: 22年前
投稿: 4
Topic starter  

VC++初心者です。
モードレスダイアログ内のリストボックスでキーが取得できません。
モードレスダイアログボックスでWM_KEYDOWNやWM_LBUTTONDOWNメッセージに対する処理が
コントロール以外の領域でしかできません。リストボックス内でVK_DOWNと
WM_LBUTTONDOWNを取りたいのです。
WEBで調べてWinMainのGetMessage()でIsDialogMessage()を呼び出し、

LRESULT CALLBACK WndDialog(){
switch(msg){ case WM_GETDLGCODE : return DLGC_ALLKEYS;
case WM_KEYDOWN :   ‥‥

としましたが、WM_KEYDOWNメッセージが来ません。どうすればよいのでしょうか?
WINDOWS XP , VisualStudio 6.0sp5


引用未解決
トピックタグ
***
 ***
(@***)
ゲスト
結合: 22年前
投稿: 18
 

>WEBで調べてWinMainのGetMessage()でIsDialogMessage()を呼び出し、
という方法は知りませんが、リストボックスをサブクラス化したクラス
でPreTransrateMessageをオーバーライドをする方法を私はしています。

参考になりますでしょうか。


返信引用
qutto
 qutto
(@qutto)
ゲスト
結合: 22年前
投稿: 4
Topic starter  

レスありがとうございます。
私はSDKでつくっています。記入するべきでした、すいません。
SDKでもPreTransrateMessage()は使えるのでしょうか?


返信引用
tnd
 tnd
(@tnd)
ゲスト
結合: 22年前
投稿: 6
 

SetWindowLong( hListBox, GWL_WNDPROC, (LONG)MyListBoxWinProc )
でサブクラス化して、MyListBoxWinProcの中でハンドルできませんか?


返信引用
qutto
 qutto
(@qutto)
ゲスト
結合: 22年前
投稿: 2
 

レスありがとうございます。
SetWindowLong()ですか、知りませんでした。WM_INITDIALOGでこれを呼んでプロシージャ
を作ったのですが、デバッグではプロシージャが呼び出されませんでした。
使い方がおかしいのでしょうか・・。

LRESULT CALLBACK DlgBinary(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp)
{
switch (msg) {
case WM_INITDIALOG:
SetWindowLong(GetDlgItem(hDlgBinary, IDC_LIST1),
                GWL_WNDPROC, (LONG)MyListBoxWinProc );
return TRUE;


返信引用
qutto
 qutto
(@qutto)
ゲスト
結合: 22年前
投稿: 2
 

よく考えたらWM_INIDIGALOGではGetDlgItem(hDlgBinary,・・)はつかえません。
修正したらプロシージャに飛んでくれましたが、どこか別のところで無限ループになって
しまって、リストボックスが表示されなくなりました。
これは自分で解決できると思います。
tndさん、***さんありがとうございました。


返信引用
tnd
 tnd
(@tnd)
ゲスト
結合: 22年前
投稿: 6
 

自分の作ったプログラムではWM_INIDIGALOGで HWND GetDlgItem(hDlg,nIDDlgItem)
使えています。なにか別のところに問題があったのではありませんか?
サブクラス化してWM_KEYDOWNをハンドルする部分はざっくりとこんなものです。

WNDPROC g_pOldListCtrlWndProc; // デフォルトのリストボックスのプロシージャ
LRESULT CALLBACK ListCtrlWndProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM
lParam )
{
switch ( msg )
{
case WM_KEYDOWN:
return 0;
}
return ::CallWindowProc( g_pOldListCtrlWndProc, hWnd, message, wParam, lParam );
}

LRESULT CALLBACK ModelessDlg( HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam )
{
switch( msg )
{
case WM_INITDIALOG:
{
HWND hList = GetDlgItem( hDlg, IDC_LIST1 );
g_pOldListCtrlWndProc = (WNDPROC)GetWindowLong( hList, GWL_WNDPROC );
SetWindowLong( hList, GWL_WNDPROC, (LONG)ListCtrlWndProc );
return TRUE;
}
:


返信引用
qutto
 qutto
(@qutto)
ゲスト
結合: 22年前
投稿: 4
Topic starter  

上のように作ってみたのですが、ハンドルが無効だといわれます。たぶんWM_INITDIALOG
ではまだリストボックスが作られてないからハンドルを取得できないと思ったのです
が・・。
いちおうWinMain()のループ前の初期化時に入れるとエラーはでませんが、ダイアログが
無限ループに入ってしまってリストボックスすら表示できません。
VCははじめて間もないため初歩的なミスをしていると思います。ソースをアップしまし
たので時間がありましたらご指摘いただけるとうれしいです。

http://qutto.netfirms.com/MatrixViewer.zip

ps. デフォルトのリストボックスのプロシージャとありますが、なぜかGetWindowsLong()
で作れなかったのでreturn ::CallWindowProc( g_pOldListCtrlWndProc, .. )はよんでい
ません。


返信引用
tnd
 tnd
(@tnd)
ゲスト
結合: 22年前
投稿: 6
 

LRESULT CALLBACK DlgBinary(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp)
{
HWND hList;
switch (msg) {
case WM_INITDIALOG:
hList = GetDlgItem( hDlgBinary, IDC_LIST1 );

となっていますが、ここのGetDlgItemに渡すウインドウハンドルはhWndでないと駄目です。

これは、
BOOL InitInstance( HINSTANCE hInstance, int nCmdShow )のなかで呼んでいる
hDlgBinary = CreateDialog(hInstance, MAKEINTRESOURCE(IDD_DIALOG), hWnd,
(DLGPROC)DlgBinary);
よりも前にDlgBinaryのWM_INITDIALOGメッセージが届くため、hDlgBinaryは無効なハンド
ルとなっているためです。

DlgBinaryのWM_INITDIALOGハンドラで使っているGetDlgItemに渡すウインドウハンドルを
DlgBinaryの仮引数であるhWndに変更すればGetDlgItemは成功します。

また、MyListBoxWinProcの最後で
return CallWindowProc( g_pOldListCtrlWndProc, hWnd, msg, wp, lp);
とやらなければ、リストボックスのデフォルト動作を全て隠してしまうことになるので当
然何も表示されないでしょう。

この2箇所を変更したらちゃんと動きました。
では、がんばってください。


返信引用
qutto
 qutto
(@qutto)
ゲスト
結合: 22年前
投稿: 4
Topic starter  

試してみたところ動きました。ずっと悩んでいたのでうれいしいです。
tndさん、実行までしていただきありがとうございました。


返信引用

返信する

投稿者名

投稿者メールアドレス

タイトル *

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