直接作成したコントロールのTABフォーカス移動について – プログラミング – Home

直接作成したコントロールのTABフォー...
 
通知
すべてクリア

[解決済] 直接作成したコントロールのTABフォーカス移動について


ねこ
 ねこ
(@ねこ)
ゲスト
結合: 22年前
投稿: 94
Topic starter  

WindowsXP VC++.NET 2003 で開発しております。

テンプレートを使わずにコントロールを2つ、直接作成したのですが、
2つのコントロール間のTabキーによるフォーカス移動ができません。

親ウインドウで、CreateWindowExにWS_EX_CONTROLPARENTを指定して、
各コントロールにWS_TABSTOPをしてみたのですが、どうもうまくいきません。

各コントロールはそれぞれ、テキストボックス、ボタンです。
このテキストボックスでTABキーを押した場合、インデントされるだけで、
ボタンにフォーカスが移動するようなことはありません。

そもそも、ボタンから、テキストボックスにTABキーでフォーカス移動することもできま
せん。

以下にソースの1部を書きます。

--------WinProc内--------
.
..
...

case WM_CREATE:

/* テキスト入力ボックスを作成 */
hTextbox=CreateWindowEx(0, EDIT,",
WS_CHILD | ES_MULTILINE | WS_VSCROLL
|WS_GROUP|WS_TABSTOP,
0, 0, 0, 0,
hWnd,
(HMENU)2,
(HINSTANCE)GetWindowLong(hWnd, GWL_HINSTANCE), NULL);
ShowWindow(hTextbox,SW_SHOW);

/* 送る ボタンを作成 */
hButton=CreateWindowEx(0, BUTTON,送る,
WS_CHILD|WS_GROUP|WS_TABSTOP ,
0, 0,128, 32,
hWnd,
(HMENU)ID_BTN,
(HINSTANCE)GetWindowLong(hWnd, GWL_HINSTANCE), NULL);
ShowWindow(hButton,SW_SHOW);

break;

.
..
...

case WM_SIZE:
MoveWindow(hButton, LOWORD(lPa)-70,
HIWORD(lPa)-36,64, 32, TRUE);
MoveWindow(hTextbox, 5, HIWORD(lPa)*0.77+10,
LOWORD(lPa)-80, HIWORD(lPa)-HIWORD(lPa)*0.77-
15, TRUE);
break;

.
..
...

--------WinMain内--------
.
..
...

hWnd = CreateWindowEx(
WS_EX_CONTROLPARENT,
szWinName,
szWinTitle,
WS_OVERLAPPEDWINDOW,
0,
0,
SCREEN_WIDTH,
SCREEN_HEIGHT,
NULL,
NULL,
hInst,
NULL
);

アドバイスよろしくお願いいたします。


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

メッセージループで IsDialogMessage() を呼んでいますか?


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

dairygoods様、お早い返事ありがとうございます。
恥ずかしながら、IsDialogMessage()なるものを知りませんでした。
ソースを下記のように書き換えました。

  while (GetMessage(&msg, NULL, 0, 0)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}

       ↑この部分を、↓このように書き換えました。

while(GetMessage(&msg,NULL,0,0))
{
if(!IsDialogMessage(hWnd,&msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}

しかし、残念ながらTABキーでのフォーカス移動はできませんでした。

改善されたことは1つあります。
テキストボックス内でTABキーを入力した場合、
インデントされなくなりました。


返信引用
dairygoods
 dairygoods
(@dairygoods)
ゲスト
結合: 23年前
投稿: 1421
 

> hWnd = CreateWindowEx(
> WS_EX_CONTROLPARENT,

このスタイルは、作ったダイアログを親ダイアログの中に埋め込み、
ダイアログとしての処理は親に任せる時に使うものなので、
不要のような気がします。

あと、今回の問題とは関係ないですが、
コントロールを作ってからいちいちShowWindowしなくても、
WS_VISIBLE スタイルというものがあります。


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

dairygoods様

おっしゃるとおり、ShowWindowしなくても、WS_VISIBLEで表示できました。

ただ、相変わらずTABでフォーカス移動ができません・・・。
指摘されたとおり、親ウインドウのWS_EX_CONTROLPARENTの記述を削除しましたが、
どうしてもフォーカス移動できません。

何かいい方法はないでしょうか。。。


返信引用
dairygoods
 dairygoods
(@dairygoods)
ゲスト
結合: 23年前
投稿: 1421
 

DefDlgProc
http://www.microsoft.com/japan/msdn/library/ja/jpwinui/html/_win32_defdlgproc.asp

ここの「解説」にある、カスタムダイアログボックスに関する要件は
満たしていますでしょうか?


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

dairygoods様

すみません。私が初心者なもので、
dairygoods様がおっしゃっている意味がわかりません。
私は、DefWindowProcをウインドウプロシージャの最後に記述しています。
ここを、DefDlgProcに書き換えたところ、ウインドウが表示されなくなりました。
もうちょっと詳しいソースを記述します。

//-----WinMain----------
INT APIENTRY WinMain( HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR pCmdLine, INT
nCmdShow )
{
.
...
....
WNDCLASSEX wc;

wc.cbSize = sizeof(WNDCLASSEX);
wc.style = NULL;
wc.lpfnWndProc = WinProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInst;
wc.hIcon = NULL;
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
wc.lpszMenuName = NULL;
wc.lpszClassName = szWinName;
wc.hIconSm = NULL;

if (!RegisterClassEx(&wc)) return (FALSE);

hWnd = CreateWindowEx(0,
szWinName,
szWinTitle,
WS_OVERLAPPEDWINDOW|WS_SYSMENU,
0,
0,
SCREEN_WIDTH,
SCREEN_HEIGHT,
NULL,
NULL,
hInst,
NULL
);

ShowWindow(hWnd, nWinMode);
UpdateWindow(hWnd);
.
...
....

while(GetMessage(&msg,NULL,0,0))
{
if(!IsDialogMessage(hWnd,&msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
.
...
....

//-----ウインドウプロシージャ-------

LRESULT CALLBACK WinProc(HWND hWnd, UINT msg, WPARAM wPa, LPARAM lPa)
{

.
...
....

case WM_CREATE:

/* テキスト入力ボックスを作成 */
hTextbox=CreateWindowEx(0, EDIT,",
WS_CHILD | ES_MULTILINE | WS_VSCROLL
|WS_GROUP|WS_TABSTOP|WS_VISIBLE,
0, 0, 0, 0,
hWnd,
(HMENU)2,
(HINSTANCE)GetWindowLong(hWnd, GWL_HINSTANCE), NULL);

/* 送る ボタンを作成 */
hButton=CreateWindowEx(0, BUTTON,送る,
WS_CHILD|WS_GROUP|WS_TABSTOP|WS_VISIBLE,
0, 0,128, 32,
hWnd,
(HMENU)ID_BTN,
(HINSTANCE)GetWindowLong(hWnd, GWL_HINSTANCE), NULL);

break;

.
..
...

case WM_SIZE:
MoveWindow(hButton, LOWORD(lPa)-70,
HIWORD(lPa)-36,64, 32, TRUE);
MoveWindow(hTextbox, 5, HIWORD(lPa)*0.77+10,
LOWORD(lPa)-80, HIWORD(lPa)-HIWORD(lPa)*0.77-
15, TRUE);
break;

.
..
...

default:
return DefWindowProc(hWnd, msg, wPa, lPa);

.
..
...
---------------

以上です。


返信引用
dairygoods
 dairygoods
(@dairygoods)
ゲスト
結合: 23年前
投稿: 1421
 

もうひとつ、
> どのような場合でも、カスタムダイアログボックスクラスでは、
> WNDCLASS の cbWndExtra メンバは少なくとも DLGWINDOWEXTRA
> の値に設定しなければなりません。
という記載がありますね。

ところで、ダイアログリソースを使って CreateDialog した方が
わざわざダイアログとしての基本動作の部分について思い悩む
必要もないと思うのですが、なにか動的にコントロールを生成
しなければならない理由がおありでしょうか。


返信引用
aetos
(@aetos)
Noble Member
結合: 5年前
投稿: 1480
 

なんか食い違ってんね。

>> dairygoods さん

作ってるのは、ダイアログボックスじゃないようですよ。


返信引用
R2
 R2
(@R2)
ゲスト
結合: 19年前
投稿: 3
 

ん。

標準のダイアログクラスを使わないで、独自ウィンドウクラスを使うなら
「カスタムダイアログ」にしなきゃだめ、てことじゃないかと。

http://msdn.microsoft.com/library/default.asp?url=/library/en-
us/winui/winui/windowsuserinterface/windowing/windows/windowreference/windowfun
ctions/createwindowex.asp

の最後のほうに記述がありますね。
DefWindowProc のかわりに DefDlgProc を呼び出すようにウィンドウプロシージャを
変更する必要があるみたい。

でも、dairygoods さんが言われているようにダイアログを使うのが一般的なのかも。
メインウィンドウに子ダイアログを貼り付けて、その中にコントロールを配置する。
MFC のフォームビューなんかはそのパターンですよね。
(背景色なんかは簡単に変えられると思います)


返信引用
dairygoods
 dairygoods
(@dairygoods)
ゲスト
結合: 23年前
投稿: 1421
 

> 作ってるのは、ダイアログボックスじゃないようですよ。

WS_TABSTOP スタイルのコントロールをTABで移動する機能は、
DefDlgProc や IsDialogMessage の組合せで実現されており、
これらを利用するウィンドウは、本人にそのつもりが無くても
(モードレス)ダイアログボックスです。

Windows のダイアログボックス機能に頼らず、
WndProcに自力でTAB遷移を組み込むという方法もありますが。


返信引用
R2
 R2
(@R2)
ゲスト
結合: 19年前
投稿: 3
 

リンク先訂正です。(^^;

> http://msdn.microsoft.com/library/default.asp?url=/library/en-
>us/winui/winui/windowsuserinterface/windowing/windows/windowreference/windowfu
n
>ctions/createwindowex.asp

http://msdn.microsoft.com/library/en-
us/winui/winui/windowsuserinterface/windowing/dialogboxes/usingdialogboxes.asp?
frame=true
(改行はつなげてください)


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

dairygoods様 R2様 シャノン様

おっしゃるとおりに、DLGWINDOWEXTRAを記述したところ、
フォーカス移動ができるようになりました!
カスタムダイアログ、ウインドウ、ダイアログなどの違いがいまいちわからず、
すこし混乱していますが、とりあえずは解決できてうれいしです。
リソースを使わず、あえて直接書いたのは、
単にリソースの使い方がよくわからないというだけです。

フォーカス移動はできたのですが、今度は作成したウインドウの背景色が
ダイアログボックス特有のグレーになってしまいました。
ですが、ウインドウプロシージャ(の、つもりだったんですが、もうダイアログプロシー
ジャなのかな・・・。)の中を、下記のように書き換えたところ、もとのブラック色にもど
すことができました。

case WM_CTLCOLORDLG:
return (long)GetStockObject(BLACK_BRUSH);

みなさま、どうもありがとうございました。


返信引用
aetos
(@aetos)
Noble Member
結合: 5年前
投稿: 1480
 

> dairygoods さん、R2 さん

ぬう、そんな秘密があったとは。
役立たずで申し訳ありませんでした。


返信引用

返信する

投稿者名

投稿者メールアドレス

タイトル *

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