- PR -

モードレスダイアログアクティブ時のショートカットキー

投稿者投稿内容
KI
大ベテラン
会議室デビュー日: 2007/01/10
投稿数: 239
投稿日時: 2007-06-15 12:18
VS2005 C# で Windows フォーム での質問です。

アプリケーション内にモードレスダイアログを作成しているのですが、
このダイアログがアクティブになっているとき、
メインフォームに配置してあるメニューの
ショートカットキーが効かなくなってしまいます。
このモードレスダイアログはツールボックスのようなイメージですので、
アクティブなときも、メインフォームのメニューの
ショートカットキーを有効にしたいです。

その方法として、私が考えた方法(まだ試してはないのですが)は、以下のようなものです。

(1) メインフォーム側でメニュー処理を行うメソッドを公開する。
  (例えば「保存」メニューに対応する SaveFile メソッド)

(2) モードレスダイアログ側で OnKeyDown メソッドをオーバーライドして、
  押されたキーを判定して、メインフォームの対応するメソッドを呼び出す。
  (例えば Ctrl + S が押されたら、SaveFile メソッドを呼び出す)

ただし、この方法で出来たとしても、
全てのショートカットキーのパターンに対して書く必要が出てきますから
相当面倒に思います。
こういうインタフェースを持つアプリケーションは多いような気がしますし、
ショートカットキーもちゃんと効いているような気がしますが、
もう少し簡単な方法はないのでしょうか?

ご存知の方いらっしゃいましたらお願いします。
まどか
ぬし
会議室デビュー日: 2005/09/06
投稿数: 372
お住まい・勤務地: ますのすし管区
投稿日時: 2007-06-15 13:09
引用:

全てのショートカットキーのパターンに対して書く必要が出てきますから
相当面倒に思います。
もう少し簡単な方法はないのでしょうか?


キーを受け取り、その意味(列挙型:NotShortcut、Open、Save、・・・)を返す関数なりを作るとか。
その際、呼び出し側はNotShortcutの判断だけすればよいですね。
さらに、意味ごとのメソッドではなく、その列挙型を渡せば要求メソッドを一本化できたりとか。

[ メッセージ編集済み 編集者: まどか 編集日時 2007-06-15 13:12 ]
KI
大ベテラン
会議室デビュー日: 2007/01/10
投稿数: 239
投稿日時: 2007-06-15 13:25
お返事ありがとうございます。
確かに私が出した例はもう少し工夫して
コードの重複を避けるようなことはできるかと思いますが。

すみません、質問の仕方が悪かったかも知れませんが、
もっと根本的な解決策がないのかが知りたかったのです。

例えばMDIフォームの子ウィンドウの場合、
アクティブになっていても普通にショートカットキーを使うことができます。
あれがどういう仕組みになっているのかよくわかりませんが、
同じようなことは簡単にできないのかなと。

モーダルダイアログのプロパティとか、protected メソッドのオーバーライド等で、
ダイアログの上で押されたキーを、親にそのまま渡すような方法がないかと思ったのです。
unibon
ぬし
会議室デビュー日: 2002/08/22
投稿数: 1532
お住まい・勤務地: 美人谷        良回答(20pt)
投稿日時: 2007-06-15 13:36
引用:

KIさんの書き込み (2007-06-15 12:18) より:
こういうインタフェースを持つアプリケーションは多いような気がしますし、
ショートカットキーもちゃんと効いているような気がしますが、
もう少し簡単な方法はないのでしょうか?


Microsoft Office のあのウザいカイル君のウィンドウもこんな感じですよね。キーのイベントを伝播させるよりも、そもそもそのモードレスダイアログをアクティブにしないようにするのが簡単なのではないでしょうか。

--
unibon {B73D0144-CD2A-11DA-8E06-0050DA15BC86}
KI
大ベテラン
会議室デビュー日: 2007/01/10
投稿数: 239
投稿日時: 2007-06-15 14:05
お返事ありがとうございます。

引用:

unibonさんの書き込み (2007-06-15 13:36) より:

キーのイベントを伝播させるよりも、そもそもそのモードレスダイアログをアクティブにしないようにするのが簡単なのではないでしょうか。


うーん…すみません。知識不足で、具体的に何をしたらよいのかがわかりません。
試しにモードレスダイアログのフォームの Activated イベントで、
メインフォームにフォーカスを移すように書いてみたら、
モードレスダイアログの上のコントロールが全く使えなくなってしまいました…
じゃんぬねっと
ぬし
会議室デビュー日: 2004/12/22
投稿数: 7811
お住まい・勤務地: 愛知県名古屋市
投稿日時: 2007-06-15 14:47
引用:

KIさんの書き込み (2007-06-15 13:25) より:

モーダルダイアログのプロパティとか、protected メソッドのオーバーライド等で、ダイアログの上で押されたキーを、親にそのまま渡すような方法がないかと思ったのです。


気持ちがわかるような気がします。ショートカットを仲介するメソッドを通せば実現できるものの変更がある度にメンテナンスする場所が 2 倍になるのは、確かにイヤですよね。

どんな技を使っても良いというのであれば、方法はいくつか思いつきます。ただ今の構成でキーを伝播させてしまって本当に良いのでしょうか。

引用:

KIさんの書き込み (2007-06-15 12:18) より:

このモードレスダイアログはツールボックスのようなイメージですので、


ツール ボックスのようなイメージであれば、モードレス ダイアログとしてメイン フォームの外に出すのではなく、メイン フォームの中にそのダイアログを Controls.Add してしまうというのはどうでしょうか。要するに Form の中に Form を追加するということです。Form は System.Windows.Forms.Control からの継承クラスなので TopLevel にさえ気をつければ追加することができます。

この状態であれば、ツール ボックスとなるダイアログ自体はアクティブにはならず、親たるメイン フォームのショートカットは影響を受けることがありません。アクティブにはなりませんが、ダイアログの中に含まれるコントロールたちはクライアント領域での入力を受け付けます。

_________________
C# と VB.NET の入門サイト
じゃんぬねっと日誌
KI
大ベテラン
会議室デビュー日: 2007/01/10
投稿数: 239
投稿日時: 2007-06-15 15:11
引用:

じゃんぬねっとさんの書き込み (2007-06-15 14:47) より:

ツール ボックスのようなイメージであれば、モードレス ダイアログとしてメイン フォームの外に出すのではなく、メイン フォームの中にそのダイアログを Controls.Add してしまうというのはどうでしょうか。要するに Form の中に Form を追加するということです。Form は System.Windows.Forms.Control からの継承クラスなので TopLevel にさえ気をつければ追加することができます。



なるほど。こんな手があるとは知りませんでした。
ありがとうございます。

やってみたところ、ショートカットキーは確かに有効でした。
ただし、別の問題が出てきてしまいました。
ダイアログにテキストボックスが配置されているのですが、
入力されているテキストの右端よりも右の部分をクリックしたとき、
通常ですとテキストボックス内のカーソルは
テキストの一番右に移動するのですが、全く移動しません。
モードレスダイアログとして表示していたときは、この現象はなかったです。
ウィンドウがアクティブになっていないからでしょうか。
あとは表示の問題ですが、ウィンドウのタイトルバーが
非アクティブウィンドウの色になるのも気になります。

非アクティブである限り、この2点が解消されないのであれば、
やはりアクティブにする方向で考えた方がいいのかなぁ…と。
まどか
ぬし
会議室デビュー日: 2005/09/06
投稿数: 372
お住まい・勤務地: ますのすし管区
投稿日時: 2007-06-15 15:44
引用:

ダイアログにテキストボックスが配置されているのですが、
入力されているテキストの右端よりも右の部分をクリックしたとき、
通常ですとテキストボックス内のカーソルは
テキストの一番右に移動するのですが、全く移動しません。


クリックそのものがだめですね。※ダブルクリックで選択はできるみたい。
なんだろう、裏のウィンドウのメニューをクリックしたらまずウィンドウがアクティブになるという動きのせいかな?
メッセージは届いているはずだけど、常に非アクティブなもんだからその動きを繰り返しているだけのような。
キー入力は直接キューに行っているみたいですね。

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