- PR -

C# ToolStripContainer上のコントロールで、[Enter]キーでのフォーカス移動がしたいのですが

投稿者投稿内容
kuwappi
会議室デビュー日: 2004/10/14
投稿数: 10
お住まい・勤務地: Yokohama
投稿日時: 2006-06-29 14:09
C#のWindowsフォームでのDBシステムを開発しはじめたのですが、
1週間前にC#を始めたばかりで、つまづいてしまいました。

Visual Studio 2005 Tools for Officeで開発を行っているのですが、

[Enter]キーでのフォーカス移動を、
http://www.atmarkit.co.jp/fdotnet/dotnettips/231winentermove/winentermove.html
で紹介している記事のとおりコーディングして、
無事に動くようになったのですが、

http://www.atmarkit.co.jp/fdotnet/special/win20review02/win20review02_01.html
の記事を参考に、
ToolStripContainerコントロール上に全てのコントロールを移動したところ、
[Enter]キーでの移動ができなくなってしまいました。

調べたところ、
http://msdn2.microsoft.com/ja-jp/library/system.windows.forms.toolstripcontainer_methods.aspx
ToolStripContainerコントロールには、SelectNextControlメソッドがあるので、

ToolStripContainerコントロールのKeyDownイベントにも
[Enter]キーでのフォーカス移動のコードをコピーしたのですが、
[Enter]キーを押下しても、まったくの無反応です。

ToolStripContainerコントロール上にある、TextBox等のコントロール間を
[Enter]キーでフォーカス移動させるというのは、無理なのでしょうか?

MS Access でしたら、[Enter]キーや方向キーでのフォーカス移動が当たり前のように
できていたので、[Enter]キーで移動できないこと自体に違和感があります。
テンキーにある[Enter]が使えないとなると、[Tab]キーを使うことになると思うのですが、
実務では使い物にならないシステムとなってしまいます。

「あー、なんで[Tab]キーって変なところにあるのでしょう、
[Tab]キーと[Enter]キーの位置が、逆のキーボードがあればそれを使ってみたい…」


以下が問題のコードです。
どうか、よろしくお願いいたします。


  public partial class FrmWorkShopM : Form
  {
    public FrmWorkShopM()
    {
      InitializeComponent();
    }
 
    private void acd_WorkShopMBindingNavigatorSaveItem_Click(object sender, EventArgs e)
    {
      this.Validate();
      this.acd_WorkShopMBindingSource.EndEdit();
      this.acd_WorkShopMTableAdapter.Update(this.accidentDataSet.Acd_WorkShopM);
    }
 
    private void FrmWorkShopM_Load(object sender, EventArgs e)
    {
      this.acd_WorkShopMTableAdapter.Fill(this.accidentDataSet.Acd_WorkShopM);
      // フォーム上でのキーボードからのキー入力をイベントで受け取れるようにする
      this.KeyPreview = true;
    }
 
    private void FrmWorkShopM_KeyDown(object sender, KeyEventArgs e)
    {
      if (e.KeyCode == Keys.Enter)
      {
        bool bThrough = false;
        if (this.ActiveControl is TextBox)
        {
          // マルチラインのテキストボックスは
          // テキストボックス内で改行があるため対象外とする
          if (((TextBox)this.ActiveControl).Multiline == true)
          {
            bThrough = true;
          }
        }
 
        if (bThrough == false)
        {
          bool forward = e.Modifiers != Keys.Shift;
          // [Enter]キーでのコントロール移動
          this.SelectNextControl(this.ActiveControl, forward, true, true, true);
        }
      }
    }
 
    private void toolStripContainer1_KeyDown(object sender, KeyEventArgs e)
    {
      if (e.KeyCode == Keys.Enter)
      {
        bool bThrough = false;
        if (this.toolStripContainer1.ActiveControl is TextBox)
        {
          if (((TextBox)this.toolStripContainer1.ActiveControl).Multiline == true)
          {
            bThrough = true;
          }
        }
 
        if (bThrough == false)
        {
          bool forward = e.Modifiers != Keys.Shift;
          //this.ProcessTabKey(forward);
          this.toolStripContainer1.SelectNextControl(this.toolStripContainer1.ActiveControl, forward, true, true, true);
        }
      }
 
    }
  }
}
じゃんぬねっと
ぬし
会議室デビュー日: 2004/12/22
投稿数: 7811
お住まい・勤務地: 愛知県名古屋市
投稿日時: 2006-06-29 14:25
引用:

kuwappiさんの書き込み (2006-06-29 14:09) より:

ToolStripContainerコントロールのKeyDownイベントにも[Enter]キーでのフォーカス移動のコードをコピーしたのですが、[Enter]キーを押下しても、まったくの無反応です。
ToolStripContainerコントロール上にある、TextBox等のコントロール間を[Enter]キーでフォーカス移動させるというのは、無理なのでしょうか?


Form 内全体に適用するならば、面倒ですから一括でやりたいですね。
Form の ProcessCmdKey メソッドでキーの補足することはできますか?

_________________
C# と VB.NET の入門サイト
じゃんぬねっと日誌
kuwappi
会議室デビュー日: 2004/10/14
投稿数: 10
お住まい・勤務地: Yokohama
投稿日時: 2006-06-29 17:12
じゃんぬねっと さん、回答ありがとうございます。

早速、
ProcessCmdKeyメソッドの使い方を調べたのですが、
いまひとつ使い方がわかりませんでした。

これは後日、勉強してから確かめたいと思います。


それと、つぎのような実験をしてみました。

「フォーム上に2個のTextBox」と「toolStripContainer上に2個のTextBox」を
配置してみて、動きを見てみました。

すると、フォーム上では[Enter]キーでフォーカスが移動するのですが、
toolStripContainer上では、最初のTextBoxにフォーカスがあたり、

もう一度[Enter]キーを押下すると、
フォーム上の最初のTextBoxにフォーカスが移動します。

このことから、toolStripContainer自体がコントロールなので、
それにぶら下がっているコントロールに対しては、
制御というか、キー入力に対するイベントが発生していないと
思われます。

toolStripContainerのイベントのほうに、
ブレークポイントを設定して、コードを走らせてもブレークしませんでした。

メソッドは用意されていても、toolStripContainer上ではイベントが発生しないと
いうことは、とても不思議です。

他に原因があるかもしれないので、もうすこし、考えてみたいと思います。
じゃんぬねっと
ぬし
会議室デビュー日: 2004/12/22
投稿数: 7811
お住まい・勤務地: 愛知県名古屋市
投稿日時: 2006-06-29 17:50
引用:

kuwappiさんの書き込み (2006-06-29 17:12) より:

早速、ProcessCmdKeyメソッドの使い方を調べたのですが、いまひとつ使い方がわかりませんでした。
これは後日、勉強してから確かめたいと思います。


いえ、とても容易いことですので是非お試しください。

コード:

    protected override bool ProcessCmdKey(ref Message msg, Keys keyData) {
        return base.ProcessCmdKey(ref msg, keyData);
    }


ブレークポイントを張って、keyData の値を確認するだけですから。

_________________
C# と VB.NET の入門サイト
じゃんぬねっと日誌
Jitta
ぬし
会議室デビュー日: 2002/07/05
投稿数: 6267
お住まい・勤務地: 兵庫県・海手
投稿日時: 2006-06-29 21:43
お気に召さないと思いますが、一応。
ユーザ インターフェスを考える link to my blog
kuwappi
会議室デビュー日: 2004/10/14
投稿数: 10
お住まい・勤務地: Yokohama
投稿日時: 2006-06-30 10:15
じゃんぬねっとさん回答ありがとうございます。

ProcessCmdKeyメソッドについては、正直なところ、
サトシさんの「独学C#」というホームページを
3日ぐらいかけて勉強した私には、チョット敷居が高く、
MSDNのオンラインヘルプを見ても使い方が理解できませんでした。
経験値が少なすぎといったところでしょうか。
もう一度「独学C#」を読み直してみたいと思います。

提示していただいたコードを見て、「へ〜っ」という気持ちです。

ただ、疑問なのは、提示してくださったコードに、
ブレークポイントを設定したのですが、
どこからもこのメソッドを呼び出すコードは追加していないのに、
きちんとブレイクするという点です。

「どうなってるんだ、これ!?」といった気持ちです。

本題からそれるので、
それは、おいおい理解を深めることとして、



「Key Dataの値」は、「LButton | MButton | Back」でした。

「フォーム上」、「toolStripContainer上」、
どちらでも[Enter]キーを押下した場合はこの値でした。

toolStripContainer自体がTextBoxなどのコントロールと同じように、
1つのコントロール扱いとなっているようです。
例えば、toolStripContainer自体にTextBox等が何個含まれているかということは、
親コンテナであるフォーム側からみれば「関係ないよ」といったことになっていると
推測されます。

フォーム側にKeyPreviewプロパティがあるように、
ToolStripContainerにもなにかプロパティというかスイッチのようなものが
あるような気もしますので、チョット調べてみたいと思います。
kuwappi
会議室デビュー日: 2004/10/14
投稿数: 10
お住まい・勤務地: Yokohama
投稿日時: 2006-06-30 10:35
JiTTAさん回答ありがとうございます。

ホームページ拝見させていただきました。

たしかに、「Tab」キーでフォーカス移動というのが、正統派と思います。

ワープロ系とかですと[Enter]で改行というのが自然ですし、
エクセルでも[Enter]で下に、[Tab]で右にとなっていますし、
Webページなんかもそうですね。

ただし、例外が…
MS Accessは[Enter]で普通にフォーカスが移動します。
あと、業務系で「○○奉行」とかもそうです。

ユーザーからすると、数字入力が主な場合、
「テンキーで数字を入れる」→「テンキーの[Enter]で次のフィールドにフォーカス」
が、自然みたいです。

観察してみると、左手は例えば伝票入力であれば、
「書類に指を置いたり、めくったり」しているようです。

標準操作に「慣れてください」とは言いづらいです。

左手を[Tab]キーを押すために、
付近に待機させるか、乗せておくといったことが要求されると思いますので。

キーボードにモード切替スイッチがあればベストだと思うのは、
私だけでしょうか…?
じゃんぬねっと
ぬし
会議室デビュー日: 2004/12/22
投稿数: 7811
お住まい・勤務地: 愛知県名古屋市
投稿日時: 2006-06-30 11:43
引用:

kuwappiさんの書き込み (2006-06-30 10:15) より:

ただ、疑問なのは、提示してくださったコードに、ブレークポイントを設定したのですが、どこからもこのメソッドを呼び出すコードは追加していないのに、きちんとブレイクするという点です。
「どうなってるんだ、これ!?」といった気持ちです。


これについては、「オーバーライド」 と 「Process~」 関連のメソッドの役割を調べると理解できると思います。

引用:

本題からそれるので、それは、おいおい理解を深めることとして、


本題から反れてはいないと思いますよ。
ここで keyData という引数から Enter が押されたかどうか、コンテナの都合に関係なく判断できます。

引用:

「Key Dataの値」は、「LButton | MButton | Back」でした。


妙ですね。
Keys.Enter のハズですが...

コード:

    protected override bool ProcessCmdKey(ref Message msg, Keys keyData) {
        const int KEY_DOWN = 0x0100;

        if (msg.Msg == KEY_DOWN) {
            if ((keyData & Keys.Enter) == Keys.Enter) {
                MessageBox.Show("Enter が押された");
            }
        }

        return base.ProcessCmdKey(ref msg, keyData);
    }


_________________
C# と VB.NET の入門サイト
じゃんぬねっと日誌

スキルアップ/キャリアアップ(JOB@IT)