- PR -

直前のコントロールの取得について

投稿者投稿内容
りんご
ベテラン
会議室デビュー日: 2006/12/21
投稿数: 51
投稿日時: 2007-04-17 15:09
こんにちは。いつもお世話になっております。
開発環境 VB.NET OS=WindowsXP

Buttonを12個並べたカスタムコントロールを作成中です。
動作はF1〜F12キーをClickされた時に、別の入力検証用カスタムコントロールの持つ
オブジェクトプロパティのHandleにSendMessageしてイベントを発生させ、
そのカスタムコントロールにWM_SETFOCUSを送っています。

ところが、Windows標準のTextBoxなどのコントロールにフォーカスを設定したいのですが、直前のコントロールのハンドルが取得できずに困っています・・
FindForm.ActiveControlとすると、当然ですが、このButtonコントロールが
Activeとなっています。
その「直前」のコントロールのハンドルを取得する方法はないでしょうか?

尚、このコントロールはフォーカスを持たない仕様のため、Button_Enterは
使用せずに、Clickイベントのみで行っています。
尚、様々なフォームに実装するため、TabIndexを参照する
GetNextControlは使用できないです・・

どなたかご教授のほど、よろしくお願いします。

コード:
Protected Overrides Sub WndProc(ByRef m As Message)
        Select Case (m.Msg)
            Case WM_SETFOCUS
                Console.WriteLine("WM_SETFOCUS = HWnd == " & m.HWnd.ToString)
                Console.WriteLine("WM_SETFOCUS = LParam == " & m.LParam.ToString)
                Console.WriteLine("WM_SETFOCUS = WParam == " & m.WParam.ToString)            
            Case WM_KILLFOCUS
                Console.WriteLine("WM_KILLFOCUS = HWnd == " & m.HWnd.ToString)
                Console.WriteLine("WM_KILLFOCUS = LParam == " & m.LParam.ToString)
                Console.WriteLine("WM_KILLFOCUS = WParam == " & m.WParam.ToString)
        End Select
        MyBase.WndProc(m)
    End Sub





じゃんぬねっと
ぬし
会議室デビュー日: 2004/12/22
投稿数: 7811
お住まい・勤務地: 愛知県名古屋市
投稿日時: 2007-04-17 16:54
引用:

りんごさんの書き込み (2007-04-17 15:09) より:

その「直前」のコントロールのハンドルを取得する方法はないでしょうか?


たとえば、以下はイベントを起こしてしまっていますが、前のコントロールを保持しなければならないという点で参考になると思います。

_________________
C# と VB.NET の入門サイト
じゃんぬねっと日誌
Ahf
大ベテラン
会議室デビュー日: 2006/08/16
投稿数: 172
投稿日時: 2007-04-17 17:02
ざっと読ませていただくとファンクションメニューなコントロールの様子ですね。

個人的には「直前」をわかるのはフォームなどの親側でなければわからないと思っています。

#または各種コントロールで「必ず」利用されるクラスでもあれば・・・

今回実装しようとしているカスタムコントロールのみでは厳しい気がします。


ふと疑問に思ったのですが、「直前のコントロールにフォーカスを戻す」というのは
どういったケースで利用しようとしているのでしょう?
検証の結果により、というなら直前ではない箇所に戻したくなる
ケースが多い気がしたもので。
ぽぴ王子
ぬし
会議室デビュー日: 2006/03/24
投稿数: 475
お住まい・勤務地: お住まい:城・勤務地:城
投稿日時: 2007-04-17 17:27
引用:

りんごさんの書き込み (2007-04-17 15:09) より:

Buttonを12個並べたカスタムコントロールを作成中です。
動作はF1〜F12キーをClickされた時に、別の入力検証用カスタムコントロールの持つ
オブジェクトプロパティのHandleにSendMessageしてイベントを発生させ、
そのカスタムコントロールにWM_SETFOCUSを送っています。


ごめんなさい。この文章の意味するところがどうもよくわかりません。
  • 「キーを Click 」とはキーボード上のキーを押したときなのか、カスタムコントロールのボタンをクリックしたときなのか
  • 「別の入力検証用カスタムコントロールの持つオブジェクトプロパティ」とは一体なんなのか
  • そのカスタムコントロールとは「別の入力検証用カスタムコントロール」なのか「Buttonを12個並べたカスタムコントロール」なのか
読めば読むほどなにがなにやら…
りんごさん自身は理解されているのだと思いますので、もう少しかみ砕い
て説明していただけませんか。

引用:

尚、このコントロールはフォーカスを持たない仕様のため、Button_Enterは
使用せずに、Clickイベントのみで行っています。


ここを読むと「Buttonを12個並べたカスタムコントロール」にフォーカスが
来てはいけないように思えますが、上の文章を読むと自ら
WM_SETFOCUS を送っているとも読めますね。また混乱してきました。

フォーカスを持たない仕様なのであれば、ちょっと乱暴ですが
WM_SETFOCUS を MyBase に渡さずに捨てることでなんとかなりそう
な気がしますが、それではいけないのでしょうか。
_________________
ぽぴ王子@わんくま同盟
ぽぴ王子の人生プログラミング中 / ぽぴンち。
じゃんぬねっと
ぬし
会議室デビュー日: 2004/12/22
投稿数: 7811
お住まい・勤務地: 愛知県名古屋市
投稿日時: 2007-04-17 17:49
引用:

Ahfさんの書き込み (2007-04-17 17:02) より:

ふと疑問に思ったのですが、「直前のコントロールにフォーカスを戻す」というのは
どういったケースで利用しようとしているのでしょう?
検証の結果により、というなら直前ではない箇所に戻したくなる
ケースが多い気がしたもので。


ああっと、質問文を全部読んでいませんでした。

確かに、検証時に必要という意味であれば、Validating イベントで、
現在のコントロールと遷移しようとしているコントロールが取得できますね。
"直前のコントロールにフォーカスを戻す" というのも、Validating イベントで可能ですし。

_________________
C# と VB.NET の入門サイト
じゃんぬねっと日誌
りんご
ベテラン
会議室デビュー日: 2006/12/21
投稿数: 51
投稿日時: 2007-04-18 09:17
じゃんぬねっと様、ぽぴ王子様、Ahf様、ご返答ありがとうございます。

引用:
ActiveControl が変わった時にイベントを発生させるには? (wankuma.com)



URL拝見したのですが、フォーム上で使用するようなので、
カスタムコントロール内部で実現できますでしょうか?
検討してみます。

引用:
直前のコントロールにフォーカスを戻す」というのは
どういったケースで利用しようとしているのでしょう?



ごめんなさい。「直前の」という言い方に誤解があるのかも知れませんが、
ファンクションキーとして使用するのですが、このカスタムコントロール(FuncKeyとします)
には、フォーカスがこないのです。フォームに入力検証するコントロール類(TrueTextとします)を
実装して、FuncKeyを必ず配置するのですが、動作はF1〜F12のキーを押下するか、
もしくはFuncKeyのF1〜F12までのボタンをClickするかのどちらかです。
押されたキーを教えるイベントを発生させます。

TrueTextにフォーカスがある状態で、FuncKeyをClickされようと、ボタンを押されようと
TrueTextにフォーカスがないといけない仕様です。
TrueTextというのは入力検証用に作成してあるカスタムコントロールなので、
検証はこのコントロール内部で行うため、FuncKeyでは必ず「元々フォーカスのあった
コントロール」に戻さないといけません。

引用:
「キーを Click 」とはキーボード上のキーを押したときなのか、カスタムコントロールのボタンをクリックしたときなのか
「別の入力検証用カスタムコントロールの持つオブジェクトプロパティ」とは一体なんなのか
そのカスタムコントロールとは「別の入力検証用カスタムコントロール」なのか「Buttonを12個並べたカスタムコントロール」なのか



・「キーを Click 」とはFuncKeyのボタンをClickです
・「別の入力検証用カスタムコントロールの持つオブジェクトプロパティ」とは
  TrueTextに「Obj」というプロパティを持たせており、そこに自分自身を設定させています。
・そのカスタムコントロールとはTrueTextのことです。
 TrueTextに対して、WM_SETFOCUSを送っているのです。


「検証」はTrueText内部で行っています。エラーがある場合には、次のフォーカスへ移動
できません。

作成する画面数が100を越えるシステム構築のため、なるべくフォームには
コードを増やすな という上司のもと、普通のTextBoxを使用した場合には、
LeaveやValidatingを使用しなければ、フォーム上でも検証しなければいけませんが、
検証なしのTextBoxとしてWindows標準のTextBoxを配置した場合に、
TextBox(直前のコントロール)にフォーカスがないといけないのです・・・
それでどうすればHandleが取得できるのか?と。。

見た目には一瞬でもFuncKeyにフォーカスが移って構わないのですが、
WndProc内でWM_SETFOCUSを使用するとしたら、FuncKey_Enterイベントを使わないと
いけないのでしょうか?それとも、他に何か方法はあるでしょうか?
じゃんぬねっと
ぬし
会議室デビュー日: 2004/12/22
投稿数: 7811
お住まい・勤務地: 愛知県名古屋市
投稿日時: 2007-04-18 09:47
引用:

りんごさんの書き込み (2007-04-18 09:17) より:

URL拝見したのですが、フォーム上で使用するようなので、カスタムコントロール内部で実現できますでしょうか?


Form の参照さえ持っていれば、可能でしょうね。

引用:

ごめんなさい。「直前の」という言い方に誤解があるのかも知れませんが、ファンクションキーとして使用するのですが、このカスタムコントロール(FuncKeyとします)には、フォーカスがこないのです。


微妙な言い回しですが、

仮想ファンクション キーから押下された場合はフォーカスは設定されない。
ただし、マウス ポインタでクリックした場合はフォーカスが移るので、これを元に戻したい。

という解釈で宜しいでしょうか?

引用:

作成する画面数が100を越えるシステム構築のため、なるべくフォームには
コードを増やすな という上司のもと、普通のTextBoxを使用した場合には、


"なるべく" どころか、コードで依存していたら無意味なので、書いてはいけません。

確かに、カスタム コントロール側で Form を扱うのは OOP には反しているでしょう。
しかし、今回のような AOP を目指す場合に限っては、トレードオフ関係にあると思います。

引用:

見た目には一瞬でもFuncKeyにフォーカスが移って構わないのですが、WndProc内でWM_SETFOCUSを使用するとしたら、FuncKey_Enterイベントを使わないといけないのでしょうか?それとも、他に何か方法はあるでしょうか?


未だに、WM_SETFOCUS などに拘るのかがわかりません。
FuncKey_Enter イベントは、カスタム コントロールの Enter イベント (OnEnter) であり、
何ら問題ないと思いますが...?

(2 年くらい前に似たようなものを作ったことがあります)

_________________
C# と VB.NET の入門サイト
じゃんぬねっと日誌
りんご
ベテラン
会議室デビュー日: 2006/12/21
投稿数: 51
投稿日時: 2007-04-18 10:54
引用:
仮想ファンクション キーから押下された場合はフォーカスは設定されない。
ただし、マウス ポインタでクリックした場合はフォーカスが移るので、これを元に戻したい。
という解釈で宜しいでしょうか?



その通りです。
実際の動作は、仮想ファンクションキーが押された場合には、
PFKeyPressというイベントを発生させています。

標準のTextBoxの場合には、TextBox1_PFKeyPressとなって欲しいのですが、、、

コード:
Dim mm_Obj As Object = Me.BaseCtrl.CurrentControl
      Dim intp As Integer = CInt(Me.BaseCtrl.currentcontrol.hwnd)
If e.KeyCode = Keys.F4 And Me.m_bEnabled(3) = True Then		'F4キー使用可能の場合
       Me.Button4.BackColor = Color.DeepPink			’色をつける
       RaiseEvent PFKeyPress(Keys.F4, mm_Obj)			’イベント発生
       'Call Me.BaseCtrl.SendMessage(Keys.F4, CInt(intp), 0)	
       e.Handled = True
	'元のコントロールのHandleへフォーカス設定
       SendMessageByVal(intp, WM_SETFOCUS, 0, 0)		
End If



mm_Obj にTextBoxのHandleがとれさえすれば上手くいきそうなのですが・・

引用:
未だに、WM_SETFOCUS などに拘るのかがわかりません。
FuncKey_Enter イベントは、カスタム コントロールの Enter イベント (OnEnter) であり、
何ら問題ないと思いますが...?



以前はVB6でWin32APIを使用したPGがあり、それを流用しています。
もちろんAPIなぞあんまり使いたくないので、それに代わるもので上手くいくのであれば
変更します。

ClickイベントとEnterイベントと両方作成していました・・
Enterイベントのみで行ってみます。
そうすると

コード:
Protected Overrides Sub WndProc(ByRef m As Message)
        Select Case (m.Msg)

            Case WM_SETFOCUS
                Console.WriteLine("WM_SETFOCUS = HWnd == " & m.HWnd.ToString)
                Console.WriteLine("WM_SETFOCUS = LParam == " & m.LParam.ToString)
                Console.WriteLine("WM_SETFOCUS = WParam == " & m.WParam.ToString)

                 '// ハンドルを比較(m.WParamが直前にフォーカスを持っていたコントロールのハンドル)
                'For Each ct As Control In Parent.Controls
                For Each ct As Control In FindForm.Controls
                    If ct.Handle = m.WParam Then
                        m_Con = ct
                    End If
                Next



これでm_Conに入ってくるか実験後、報告します。

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