お世話になります。
ダイアログにタブコントロールを貼り付け、そこに
各タブ毎にダイアログを貼り付けてます。
タブコントロール上(タブ部分)でTabキーの押下により、
内部のダイアログの最初のコントロールにフォーカスが
移るようにはなっているのですが、Enterキーの押下でも
同様の処理をしたいと考えてます。
内部にあるダイアログでは、PreTranslateMessage()でEnterキー
のメッセージを拾って、wparamにVK_TABを入れてしまう事により
希望の動作を実現している為、同様にメインのダイアログ(タブ
コントロールがあるダイアログ)のPreTranslate~にも同様の処理を
入れてみたのですが希望の動作になってくれません。
私が無知なだけかも知れませんが、ダイアログの親子関係等が問題
なのでしょうか?
環境はVC6.0/MFC/ダイアログベースです。
宜しくお願い致します。
すいません。自己解決です。
NextDlgCtrl()を使うことで一発解決でした。
しかし、やはり疑問です。
修正前の親ダイアログのPreTranslateMessage()の一部抜粋です。
-----------------------------------
case WM_KEYDOWN:
switch(pMsg->wParam){
case VK_RETURN:
pMsg->wParam = VK_TAB;※
return FALSE;
}
-----------------------------------
※の部分をNextDlgCtrl()に変更する事により希望の処理が出来ましたが、
上記のソースではダメな理由がわかりません。
上のソースでは結果として、「TABキーが押された事と同義」だと
思っているのですが違うのでしょうか?
ちょっと疑問が残ってしまったので、もう暫く皆さんの
回答待ちにさせてください。宜しくお願い致します。
動作の流れが
イベント発生->イベントの種類判定->種類ごとの動作
であるのに、動作の位置で無理にイベントの種類を変えても
次のイベント発生まで指定種類での判定は行いません。
かといって次のイベントを起こした段階では
起こしたイベントの内容に置き換わっています。
つまり変更後の値で判定することがないのです
toshiさん回答有難うございます。
しかし子ダイアログでは上記のソースで
フォーカス移動出来ているのですが、
何が違うんでしょうか?
よくわかっていない部分でもあるのですが、
PreTranslate~を抜けた後に「実際の動作」が
起こりうるのではないのでしょうか?
まさに「Pre」と付くだけあって、事前に処理したい事を
行う関数だと思ってるのですが・・・。
※印の部分で、VK_TABに置き換えることにより、
PreTranslate~を抜けた後に、VK_TABの場合の処理が
されると認識しているのですが間違っているのでしょうか?
今回のものはPreTranslateMessage()の使用法の違いでは
ないでしょうか。つまり実際に処理を呼び出すために使用した
場合と、ご想像通りの事前設定に用いた場合の違いだと思います。
親のほうの処理ですが、抜粋部位は実際は
-----------------------------------
case WM_KEYDOWN:
switch(pMsg->wParam){
case VK_TAB:
//処理
ほにゃらら // <=ここが処理
return TRUE;
case VK_RETURN:
pMsg->wParam = VK_TAB;※
return FALSE;
}
-----------------------------------
このような感じと思いますがいかがでしょうか?
(違うようでしたら私の記入全てが的外れということで
流して下さい。)
//まさに「Pre」と付くだけあって、事前に処理したい事を
//行う関数だと思ってるのですが・・・。
他にも用途はありまして、キー入力を判定するためにも
使うことがあります。
http://www.alpha-net.ne.jp/users2/uk413/vc/VCT_KEY.html
http://hp.vector.co.jp/authors/VA000092/win32/input.html
このような動作のための直接の判定時(判定終了時)に
判定対象を変えても、求める動作へと至る経路はないでしょう。
(名前の違いは記入ミス)
おはようございます。遅くなりました。
>このような感じと思いますがいかがでしょうか?
>(違うようでしたら私の記入全てが的外れということで
>流して下さい。)
すいません。ソースは全部乗せるべきでしたね。
残念ながらcase文にVK_TABは記述していないんですよ。
未だに原因と言うか理由がわからずじまいです。
とっても単純な事だと思うのですが・・・。
メインダイアログであると言うのが引っかかっているのではないかと
思いますけれど、どうでしょう。
WinAppクラス辺りの影響があるような来もしますけれど。
デバッガで追ってみたら何か判るかもしれませんね。
ぎゃーっ、誤字
誤)
WinAppクラス辺りの影響があるような来もしますけれど。
正)
WinAppクラス辺りの影響があるような気もしますけれど。
PATIOさん有難うございます。
色々見ていたのですが、ソースをコメントアウトしたら動きました・・・。
子ダイアログでは、return FALSEできちんと動作するのに・・・。
----------------------
pMsg->wParam = VK_TAB;
//return FALSE;←ココ。
----------------------
このTRUE/FALSEっていったい何なんでしょう?また何も指定しなければ、
継承元(CDialog)のPreTranslate~()が呼ばれますよね?
MSDNのPreTranlste~()のヘルプにはこうあります。
-----------------------------------------------
メッセージが変換されディスパッチすべきでない場合は、
0 以外を返します。メッセージが変換されずディスパッチ
すべき場合は、0 を返します。
-----------------------------------------------
この「変換」と言うのが良く分かりません。
私は自分でメッセージをVK_RETURNからVK_TABに変換している(?)
ので、上記説明の後者にのっとって、FALSE(0)を返しています。
んじゃTRUEを指定した場合は、何をされるのか?また
何も指定しない場合にCDialog::Pre~()では何がされるのかを
知る事が理解の鍵じゃないかと思っているのですが、
お恥ずかしい話、MSDNだけでは今の私の頭では理解しきれません。
そのあたりご存知でしたらご説明頂けませんか?
宜しくお願いします。
>-----------------------------------------------
>メッセージが変換されディスパッチすべきでない場合は、
>0 以外を返します。メッセージが変換されずディスパッチ
>すべき場合は、0 を返します。
>-----------------------------------------------
>この「変換」と言うのが良く分かりません。
>私は自分でメッセージをVK_RETURNからVK_TABに変換している(?)
>ので、上記説明の後者にのっとって、FALSE(0)を返しています。
変換しているなら前者では?
>変換しているなら前者では?
「何か」で変換されるものではないのでしょうか?
私は自分で「変換」したので、他所での変換は不要と
思い「変換されずディスパッチすべき」を選択したのですが。
CDialog::Pre~()で「何か」の変換がされると
思うのは間違いでしょうか?
勝手に変換はされたくないけど、ディスパッチ(実行?)させたい
と思ってFALSEにしたのですが・・・。
コメントアウトしたら動いたと言うだけの情報では
どういうコードのがその後走ったのか判らないような気がしますが。
return行がコメントアウトされたわけなので
それ以降の処理が動いたのだろうなと判る程度です。
HELPの表記の解釈ですが、
関数から抜けた後、変換されているから元の値でディスパッチされると困る場合はTRUEで
関数から抜けた後、変換されていないから元の値でディスパッチされるべき場合はFALSE
なのかな?
MFCのソースを確認した方が良いかも。
ああっ、文章がおかしい。
中で変換しているから元の値でディスパッチされると困る場合は、0以外。
内部での扱いはチャラにして元の値でディスパッチしてほしい時は0かな。
そうです。PreTranslateMessage() の戻り値は、そのメッセージをハンドルする場合は
TRUE, ハンドルしない場合は FALSE を返します。
ここで「ハンドルする」の意味は、そのメッセージをフックしてデフォルトの処理は
行なわない事を意味します。
FALSE を返した場合は、デフォルトの処理を行うことを意味します。
MFC自動生成のメッセージハンドラ
LRESULT func(WORD wNotifyCode, WORD wID, HWND hWndCtrl, BOOL& bHandled)
の bHandled も同じ意味です。
あ、なんか文章ヘンですね。
> この「変換」と言うのが良く分かりません。
これが私の投稿内容の「ハンドルされる」状態です。
「ハンドルされる」とそれ以降のディスパッチは行なわれません。
> case VK_RETURN:
> pMsg->wParam = VK_TAB;※
> return FALSE;
ではなく、自前で処理(=NextDlgCtrl())するか、
PostMessage(WM_KEYDOWN, (WPARAM)VK_TAB, (LPARAM)0);
return TRUE; // handled
のようにする方が良いと思われます。
MSDN> PreTranslateMessage
MSDN> 戻り値
MSDN> メッセージが PreTranslateMessage で完全に処理され、
MSDN> それ以上処理される必要がない場合は、0 以外を返します。
MSDN> メッセージを通常の方法で処理する必要がある場合は、0 を返します。
VC++6なら、MSDNで「PreTranslateMessage 関数の使い方」を参照してみると
いいかもしれません。
