条件
・コントロールのメンバ変数を使えない
・VC++(MFC)
まず、
ラジオボタンを3つと普通のボタンを用意します。
ラジオボタンの3つのボタンのそれぞれにフォーカスが行くように設定します。
ボタンを押した時、ラジオボタンが未選択状態になるように
すべてのラジオボタンに、
SetCheck(0);
をします。
そして、実行して
ラジオボタンすべてにフォーカスが行くか確認します。
ラジオボタンのどれかにチェックを入れて、
ボタンを押します。
次に
ボタンにフォーカスを移し、タブでフォーカス移動しようとしても
ラジオボタンには、フォーカスが移動しません。
この理由についてご存知な方は、教えてください。
確信は持てないのですが、何となくそれがラジオボタンの仕様のような気がします。
そもそもラジオボタンは、グループ内でどれかひとつが選択されているものです。
フォーカスは、選択されているラジオボタンに当たるようですので、
どれも選択されてないのなら、結果としてどこにもフォーカスが行かない、と。
sugarさん、ありがとうございます。
何としてもフォーカスが行くようにしたいのですが・・・
そういう仕様であれば、一番最初にフォーカスが行くのは
なぜなのでしょうか。何としても解決したいのですが・・・
> そういう仕様であれば、一番最初にフォーカスが行くのは
> なぜなのでしょうか。
自分の環境で試してみましたが、どのラジオボタンにもチェックが付いていないと、
そこにはフォーカスが当たりません。
一番最初というのは、ラジオボタンが置かれたダイアログが表示された時って事ですよね?
その時、ラジオボタンにはチェックがないんですよね?
で、チェックのついていないラジオボタンにフォーカスが当たっている、と?
(フォーカスが当たっている=キャプションが点線矩形で囲まれる状態を指します。)
もしかして、OnInitDialog()の中でSetFocus()やGotoDlgCtrl()なんかを実行してます?
(これらの関数を使うと、強引にフォーカスを当てることができるようです。)
> 何としてもフォーカスが行くようにしたいのですが・・・
チェックはされていないが、フォーカスは当てたい、と。
Tabキー押下の一連のフォーカス移動で当たるようにしたいとなると、
キーボードイベントを監視して、特定のコントロール上でTabキーが押されたら
ラジオボタンにフォーカスを当てて...と、かなり面倒な話になりますよ。
(PreTranslateMessage()でできるかな...??)
強引にフォーカスをもっていく事は、SetFocus()でできました。
ただ、そのあと、また、フォーカスが行かなくなります。
PreTranslateMessageを調べたのですが、よくわかりませんでした。
何か、ヒントになることを教えてください。
> PreTranslateMessageを調べたのですが、よくわかりませんでした。
>
そうですか...メッセージの流れというか、仕組みは、Windowsプログラミングの重要部分ですから、
このあたりはキッチリおさえておいた方がいいですよ。
簡単に言うと、PreTranslateMessage()を準備しておくと、
発生したメッセージが標準のウィンドウプロシジャに渡る前に、この関数に渡ってくるんです。
まさにPreTransrateの通りですね。
以下に例を示します。
ここではまず、飛んできたメッセージの種類がWM_KEYDOWNかどうかを調べます(①)。
次に、そのメッセージがどのウィンドウ(コントロール)に対して発生したか(②)、
押されたキーは何だったか(③)、を調べます。
IDC_BUTTON1は、任意のボタンのIDです。
IDC_RADIO1は、フォーカスを当てたいラジオボタンのIDです。
こうすることで、IDC_RADIO1がチェックされているか否かに関わらず、
IDC_BUTTON1にフォーカスがある時にTABキーを押すと、IDC_RADIO1にフォーカスが移ります(④)。
④の後、return で処理を終わらせないと、デフォルトのウィンドウプロシジャに処理が渡ってしまい、
折角の処理も無意味になってしまいますから、気をつけてください。
BOOL CTest22Dlg::PreTranslateMessage(MSG* pMsg)
{
// TODO: この位置に固有の処理を追加するか、または基本クラスを呼び出してください
if(pMsg->message == WM_KEYDOWN) // ①
{
CWnd *pWnd = CWnd::FromHandle(pMsg->hwnd); // ②
int nVirtKey = (int)pMsg->wParam; // ③
if(pWnd->GetDlgCtrlID() == IDC_BUTTON1 && nVirtKey == VK_TAB)
{
GotoDlgCtrl(GetDlgItem(IDC_RADIO1)); // ④
return TRUE;
}
}
return CDialog::PreTranslateMessage(pMsg);
}
!!
きちんと対応するためには、上記だけでは不十分です。
少なくとも、以下の点は対応する必要があるのではないでしょうか?
・Shift+Tabで逆順タブオーダーをサポートする必要がある。
・IDC_RADIO1以外のラジオボタンにチェックがあったら、IDC_RADIO1ではなく、
チェックのあるラジオボタンにフォーカスを移す必要がある。
では、頑張ってください。