none
ラジオボタンが選択されているときの破線が表示されない RRS feed

  • 質問

  • いつもお世話になっております。
    C#2010で開発しております。

    Form上でEnterキーを押下したときにTabキーを押下したときと
    同じような動作をさせたいと考えております。

    そこでFormのKeyDownイベントを利用して
    ProcessTabKeyメソッドを呼び出すようにプログラムしています。

            private void Form1_Load(object sender, EventArgs e)
            {
                this.KeyPreview = true;
                this.KeyDown += new KeyEventHandler(Form1_KeyDown);
            }
    
            private void Form1_KeyDown(object sender, KeyEventArgs e)
            {
                if (e.KeyCode == Keys.Enter)
                {
                    this.ProcessTabKey(!e.Shift);
                    e.Handled = true;
                }
            }
    

    ここまでのプログラムは問題なく動作しております。

    しかし、ラジオボタンにフォーカスがあたったときには、
    ラジオボタンに破線が表示されません。
    一度Tabキーを押下してフォーカス移動していると破線が表示されるのですが、
    それを行っていないと破線が表示されないようです。

    【破線が表示されない】

    【破線が表示される】

    破線がないと、選択されていることが分からないため、
    どうにか表示させたいのですが、何かプログラムで制御できませんでしょうか?

    ActiveControlのプロパティで、
    制御できないだろうかと思い、見てみましたが、
    該当するようなプロパティは見つけられませんでした。

    もしご存知でしたら、ご教示頂けませんか?

    よろしくお願い致します。

    2012年8月13日 3:10

回答

  • .NET 依存でも、Windows 7 からでもなく、Windows Vista からの OS の挙動(仕様か不具合かは不詳)ではないでしょうか。
    こちらの方がまとめておられます が、Windows Vista からコントロールパネルの設定によって挙動が変化します。
    こういった現状を考えると、容認してしまう方向で考えた方がよいとは思います。
    理由は、OS による挙動を無理矢理変えるのは大変ですし、将来の OS では対策が裏目に出る(悪化する)恐れもあるため。 

    なお、この設定が OFF の時に、MFC、.NET のどちらのアプリでも、コードを書かずにクリックで枠線が出ないこと、Tab キーで枠線が出ることの再現を確認しています。逆に ON にすると、期待通りの結果を得ることができます。

    2012年8月13日 5:32
    モデレータ
  • Vistaでコントロールにフォーカスの枠線が出ない » 遥寅
    http://www.harutora.jp/?p=1439

    あまりしっかり理解していないのですが、
    紹介されているプログラムを記載したところ、
    OSの設定を変えなくても意図した動作をするようになりました。

    ここだけ反応しました。リンク先で紹介されているのは SystemParametersInfo 関数ですね。この API はOSの設定を変更するので、使用にはご注意ください。


    ひらぽん http://d.hatena.ne.jp/hilapon/


    2012年8月13日 8:27
    モデレータ
  • 私の手元の Win7 環境でテストして得た事象を列挙します。
    閲覧される方は参考にしてください。

    1. KeyDown で該当のコードを書くと、そもそもフォーカスが遷移しない。(K.Takaoka さんが指摘されている問題)
    2. KeyUp で該当のコードを書くと、フォーカスは遷移する。
      しかし、破線が表示されるかはコントロールパネルの設定や事前に Tab キーを使っていたかに依存する。
      追試される方へ:手元のコントロールパネルの設定をご確認ください。以下のチェックが ON だと破線が必ず表示されるので問題が起きません。
    3. 1 と 2 の挙動に関しては .NET 4 および .NET 3.5 で同じ。
    4. ProcessDialogKey で Enter を Tab に置き換えた場合、フォーカス遷移は発生するが、破線が表示されない問題は 2 と同様の結果となった。

    「Enter キーによるフォーカス制御の実装方法が問題」はこのスレッドの一つの問題ですが、それ以外にも「破線を必ず表示させる方法は特殊なアプローチ(SendKeys.Send("{TAB}"); など)が必要」というのもあると思いますよ。
    (Select メソッドなどの一般的なアプローチでは、設定によって実現できないため)

    上述のことを踏まえ、「KeyDown に書かないことと」ともに「破線を表示させることをあきらめること」がこのスレッドに対する答えになるかと思っています。

    2012年8月14日 12:56
    モデレータ
  • K. Takaoka様
    Azulean様

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

    Azulean様から教えて頂いたようにOSの設定を変更したところ、
    確かにフォーカス枠が表示されるようになりました。

    ただ、既に端末は展開されており、OSの設定を変えてまで、
    対応するのもどうかなと思っております。
    Azulean様からのご意見もその通りだと思いました。

    対応しない方法で検討を進めようかと思っております。




    それとは違い、調べていて分かったこともありましたので、
    今後の情報のため、記載しておきます。

    当初、私なりに検索してみても見付けれらなかったのですが、
    Azulean様から教えて頂いた情報などを参考に、もう少し調べてみたところ、
    次のページが見付かりました。

    Vistaでコントロールにフォーカスの枠線が出ない » 遥寅
    http://www.harutora.jp/?p=1439

    あまりしっかり理解していないのですが、
    紹介されているプログラムを記載したところ、
    OSの設定を変えなくても意図した動作をするようになりました。




    あまり理解しないまま利用してしまうと、
    他への影響もこわいので、どのように対応すべきかは、
    もう少し検討してみようと思いますが、今後誰かの参考になるようでしたら幸いです。
    本件は、クローズとさせて頂きます。


    ご回答ありがとうございました。
    大変参考になりました。

    • 回答としてマーク コンドル 2012年8月13日 7:19
    2012年8月13日 7:18

すべての返信

  • .NET4 を利用されていますかね? たぶん、.NET4 でだけ発生する問題と思います。

    KeyDown イベントではなく、KeyUp イベントを利用すれば、.NET 2.0~4 全てで問題なく動くと思います。

    上記の問題とは別に、

    • KeyDown で Keys.Enter を拾ってというアプローチは、ボタン等で問題になる可能性が高いです。
    • ProcessTabKey も、ラジオボタン等のグループ化されたものをどのように移動したいかによっては、Enter で次の入力項目に移動するには問題になる可能性が高いので、SelectNextControl なんかを利用されたほうがよいのでは?

    と思います。

    2012年8月13日 4:03
  • K. Takaoka様

    ご回答ありがとうございます。
    確認してみました。

    > .NET4 を利用されていますかね? たぶん、.NET4 でだけ発生する問題と思います。
    .NET4を利用しています。

    > KeyDown イベントではなく、KeyUp イベントを利用すれば、.NET 2.0~4 全てで問題なく動くと思います。
    KeyUpイベントを利用してみましたが、
    問題は解決されませんでした。

    あまりこの回答とは関係ないかもしれませんが、
    K. Takaoka様からの回答を見てOSの違いなのかなと思い、
    WinXP、Win7で動作確認してみました。

    私の環境はWin7で問題が依然として発生しているのですが、
    WinXPであればKeyDownイベントを利用したとしても、
    枠線が表示されておりました。

    .NET Frameworkの問題ではなく、OSの違いによる動作の違いが
    原因のようです。

    > 上記の問題とは別に、
    > KeyDown で Keys.Enter を拾ってというアプローチは、ボタン等で問題になる可能性が高いです。
    > ProcessTabKey も、ラジオボタン等のグループ化されたものをどのように移動したいかによっては、Enter で次の入力項目に移動するには問題になる可能性が高いので、SelectNextControl なんかを利用されたほうがよいのでは?
    > と思います。
    とても参考になりました。
    KeyUpやSelectNextControlを利用する方向で検討致します。



    ------
    改めてですが、Win7の場合に限り、
    依然として問題が解消されておりません。
    改善されそうな案などございましたら、検証してみたいと思いますので、
    ご教示頂けますと幸いでございます。

    よろしくお願い致します。

    2012年8月13日 4:22
  • うーん、こちらでは念のため WinXP+.NET3.5, Win7+.NET4 で問題の再現有無を確認していました。

    なので、Win7+.NET4 であれば、KeyDown では発生し KeyUp で発生しないようになっています。

    2012年8月13日 4:24
  • .NET 依存でも、Windows 7 からでもなく、Windows Vista からの OS の挙動(仕様か不具合かは不詳)ではないでしょうか。
    こちらの方がまとめておられます が、Windows Vista からコントロールパネルの設定によって挙動が変化します。
    こういった現状を考えると、容認してしまう方向で考えた方がよいとは思います。
    理由は、OS による挙動を無理矢理変えるのは大変ですし、将来の OS では対策が裏目に出る(悪化する)恐れもあるため。 

    なお、この設定が OFF の時に、MFC、.NET のどちらのアプリでも、コードを書かずにクリックで枠線が出ないこと、Tab キーで枠線が出ることの再現を確認しています。逆に ON にすると、期待通りの結果を得ることができます。

    2012年8月13日 5:32
    モデレータ
  • K. Takaoka様
    Azulean様

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

    Azulean様から教えて頂いたようにOSの設定を変更したところ、
    確かにフォーカス枠が表示されるようになりました。

    ただ、既に端末は展開されており、OSの設定を変えてまで、
    対応するのもどうかなと思っております。
    Azulean様からのご意見もその通りだと思いました。

    対応しない方法で検討を進めようかと思っております。




    それとは違い、調べていて分かったこともありましたので、
    今後の情報のため、記載しておきます。

    当初、私なりに検索してみても見付けれらなかったのですが、
    Azulean様から教えて頂いた情報などを参考に、もう少し調べてみたところ、
    次のページが見付かりました。

    Vistaでコントロールにフォーカスの枠線が出ない » 遥寅
    http://www.harutora.jp/?p=1439

    あまりしっかり理解していないのですが、
    紹介されているプログラムを記載したところ、
    OSの設定を変えなくても意図した動作をするようになりました。




    あまり理解しないまま利用してしまうと、
    他への影響もこわいので、どのように対応すべきかは、
    もう少し検討してみようと思いますが、今後誰かの参考になるようでしたら幸いです。
    本件は、クローズとさせて頂きます。


    ご回答ありがとうございました。
    大変参考になりました。

    • 回答としてマーク コンドル 2012年8月13日 7:19
    2012年8月13日 7:18
  • Vistaでコントロールにフォーカスの枠線が出ない » 遥寅
    http://www.harutora.jp/?p=1439

    あまりしっかり理解していないのですが、
    紹介されているプログラムを記載したところ、
    OSの設定を変えなくても意図した動作をするようになりました。

    ここだけ反応しました。リンク先で紹介されているのは SystemParametersInfo 関数ですね。この API はOSの設定を変更するので、使用にはご注意ください。


    ひらぽん http://d.hatena.ne.jp/hilapon/


    2012年8月13日 8:27
    モデレータ
  • ひらぽん様

    ありがとうございます。
    詳しく理解しておらず、間違って理解しておりました。

    使用しない方向で進めておりますが、
    誤った理解のまま検討を進めるところでした。

    ありがとうございます。
    2012年8月13日 9:48
  • > こういった現状を考えると、容認してしまう方向で考えた方がよいとは思います。

    放置でもいいかな?とは思いますが、期待するポイントは

    • OS からみてポインタ操作なのかキー操作なのかを判断する基準がどこか?

    ではないでしょうか。該当の機能は

    • ポインティングデバイスによるフォーカス切替時には、フォーカス枠を表示しない
      (チェックが ON の場合、ポインティングデバイスによる移動でも常にフォーカス枠を表示する)

    という機能であって、キーボードデバイス等でフォーカス切替時には補助機能の有無にかかわらず常にフォーカス枠を表示する機能になっています。問題は、

    • Enterキーによってフォーカスを移動した場合、キーボードによるフォーカス移動とみなされない

    ことであって、この結果として表面化した問題がフォーカス枠が表示されないということです。この問題の解決策として

    • フォーカス移動がキー操作によって発生していることを OS に認識させる

    というのが解決方法で、その具体的な実装について

    • KeyDown イベントで Handled を true にしないで、KeyUp イベントまで発生させる

    です。(OS の判定基準は KeyPress イベント相当なんでしょうけど) KeyDown でイベントをハンドリング済みにしてしまうと、OS としてはキー操作が中断されたことになり、キー操作によるフォーカス移動とみなされなくなるため枠線が消失します。

    上記のような理由で、本件はコントロールパネルの設定に関係ないプログラミングミスによる問題ではないか?と考えています。


    2012年8月14日 0:23
  • 上記のような理由で、本件はコントロールパネルの設定に関係ないプログラミングミスによる問題ではないか?と考えています。

    手元において、KeyUp で ProcessTabKey を実行するようなサンプルを作りましたが、該当の設定がオフの状態では破線が表示されることはありませんでしたので、「KeyDown に書いていることだけが問題である」ではなさそうです。
    Tab キーと同じ操作をさせるのであれば、ProcessTabKey を使わず、SendKeys.Send などの方法が妥当な気はしますね。
    2012年8月14日 2:06
    モデレータ
  • 一番穏当なエミュレートは、ProcessDialogKeyをオーバーライドして、Enterが入力されたときにKeys.Tabをbase.ProcessDialogKeyに渡すことじゃないかなー?

    // 融通は利かせにくいですけど。

    2012年8月14日 3:13
  • > KeyUp で ProcessTabKey を実行するようなサンプルを作りましたが、該当の設定がオフの状態では破線が表示されることはありませんでしたので

    他にも原因がある可能性があるってことですね。こちらでは、Win7 環境で KeyUp イベントならフォーカス枠がきちんと表示されました。

    まあ、どちらにしろ、コントロールパネルの設定とは関係ない Enter キーによるフォーカス制御の実装方法による問題だってことです。(Enter キーで次の項目に移動する仕様を排除するのが一番楽なんですけどね)

    2012年8月14日 4:00
  • 私の手元の Win7 環境でテストして得た事象を列挙します。
    閲覧される方は参考にしてください。

    1. KeyDown で該当のコードを書くと、そもそもフォーカスが遷移しない。(K.Takaoka さんが指摘されている問題)
    2. KeyUp で該当のコードを書くと、フォーカスは遷移する。
      しかし、破線が表示されるかはコントロールパネルの設定や事前に Tab キーを使っていたかに依存する。
      追試される方へ:手元のコントロールパネルの設定をご確認ください。以下のチェックが ON だと破線が必ず表示されるので問題が起きません。
    3. 1 と 2 の挙動に関しては .NET 4 および .NET 3.5 で同じ。
    4. ProcessDialogKey で Enter を Tab に置き換えた場合、フォーカス遷移は発生するが、破線が表示されない問題は 2 と同様の結果となった。

    「Enter キーによるフォーカス制御の実装方法が問題」はこのスレッドの一つの問題ですが、それ以外にも「破線を必ず表示させる方法は特殊なアプローチ(SendKeys.Send("{TAB}"); など)が必要」というのもあると思いますよ。
    (Select メソッドなどの一般的なアプローチでは、設定によって実現できないため)

    上述のことを踏まえ、「KeyDown に書かないことと」ともに「破線を表示させることをあきらめること」がこのスレッドに対する答えになるかと思っています。

    2012年8月14日 12:56
    モデレータ
  • 皆さま、ご回答ありがとうございました。
    大変参考になりました。

    大変参考になりました。
    最終的にどのように対応するかは、
    私なりに吟味して顧客と相談して決めようと思います。

    とても勉強になりました。
    ありがとうございました。
    2012年8月16日 2:39