[リストへもどる]
一括表示

投稿時間:2002/08/16(Fri) 14:33
投稿者名:花ちゃん
Eメール:
URL :
タイトル:
アクティブなテキストボックスを取得する方法
今は、タイマーコントロールを使ってアクティブなテキストボックス(アクティブになった)
を取得しているのですが、サブクラス化して取得出来ないかと思い色々試したのですが
うまく行きません。
(どのフォームのどのコントロールがアクティブになったかを取得したいのですが!)
サブクラス化して取得する方法があれば教えて頂けないでしょうか?

投稿時間:2002/08/17(Sat) 22:34
投稿者名:Say
Eメール:
URL :
タイトル:
Re: アクティブなテキストボックスを取得する方法
WM_SETFOCUSは子Window(コントロール)に直接おくられますから、
もしサブクラス化するとなると、全コントロールをサブクラス化して
WM_SETFOCUSを拾うことになり、GotFocusイベントに直接記述したほうが
まし、ということになります。

WM_SETFOCUSを拾うなら、サブクラス化するより、メッセージフックして
拾ったほうがまだいいでしょう。

一時的にフォーカスが移動してもいいなら、ダミーコントロールに
SetFocusAPIを発行してみる、という手もあります。
戻り値として直前にフォーカースがあったウインドウのハンドルが返ります。

投稿時間:2002/08/18(Sun) 01:30
投稿者名:花ちゃん
Eメール:
URL :
タイトル:
Re^2: アクティブなテキストボックスを取得する方法
回答頂きありがとうございます。

> WM_SETFOCUSを拾うなら、サブクラス化するより、メッセージフックして
> 拾ったほうがまだいいでしょう。

これは、具体的にはどのようにするのでしょうか?

投稿時間:2002/08/18(Sun) 14:59
投稿者名:Say
Eメール:
URL :
タイトル:
Re^3: アクティブなテキストボックスを取得する方法
大雑把に言えば、
SetWindowsHookExでフックをセットし、
フックプロシージャで実処理を行い、
UnhookWindowsHookExでフックを開放します。

C/C++で恐縮ですが、フックについては
http://www.kab-studio.com/Programing/Codian/
の、「DLL・フック」の
・フックの仕組み
・ローカルフック
・システムフック
を参照してください。

また、MSDN LibraryのプラットフォームSDKで
SetWindowsHookEx、UnhookWindowsHookExについて見てみてください。

また、Yahooあたりで「グローバルフック」で検索すれば、
情報が見つかります。

なお、今回服するWM_SETFOCUSはCBTフックで拾えると思いますが、
グローバルフック扱いになりますので、VC++などでDLLにして、
それをVBから呼び出すことになるかと思います。


 

投稿時間:2002/08/18(Sun) 15:05
投稿者名:花ちゃん
Eメール:
URL :
タイトル:
Re^4: アクティブなテキストボックスを取得する方法
回答ありがとうございます。
私のやり方が拙いのか WM_SETFOCUSは 拾えませんでした。
今回は、タイマーコントロールを使った方法でやります。
又、時間ができたら挑戦してみます。
お手数お掛けしました。

投稿時間:2002/08/18(Sun) 15:48
投稿者名:MS
URL :
タイトル:
Re^5: アクティブなテキストボックスを取得する方法
WM_SETFOCUSメッセージを監視する場合、
SetWindowsHookEx()の第1引き数にWH_CALLWNDPROCを指定します。
で、フックプロシージャでWM_SETFOCUSを監視すれば可能と思います。
[追記]
アプリケーションレベルのフックなら、DLLは不要と思います。

投稿時間:2002/08/18(Sun) 20:08
投稿者名:花ちゃん
Eメール:
URL :
タイトル:
Re^6: アクティブなテキストボックスを取得する方法
回答ありがとうございます。
やはり、私の技量ではうまく行きません。
マウスイベントやキーボードイベントは拾えるのですが?
今回は使用を見合わせます。

投稿時間:2002/08/22(Thu) 10:43
投稿者名:ゆう(U)
Eメール:
URL :
タイトル:
Re^7: アクティブなテキストボックス
使用方法が正しいかは自信はありませんが・・・
とりあえず、IDE&EXEで確認は出来ました。

フォームのLoadでSetHookを、UnLoadでUnHookを
必ずCallして下さい。

フォームのキャプションにコントロール名等が
表示されると思います。
※手抜きコードです(On Error Resume Next)

サンプル:標準モジュールへ)
Private Declare Function SetWindowsHookEx Lib "user32" _
                  Alias "SetWindowsHookExA" _
                        (ByVal idHook As Long, _
                         ByVal lpfn As Long, _
                         ByVal hmod As Long, _
                         ByVal dwThreadId As Long) As Long
Private Declare Function UnhookWindowsHookEx Lib "user32" _
                        (ByVal hHook As Long) As Long
Private Declare Function CallNextHookEx Lib "user32" _
                        (ByVal hHook As Long, _
                         ByVal nCode As Long, _
                         ByVal wParam As Long, _
                         ByVal lParam As Long) As Long
Private Declare Function GetWindowLong Lib "user32" _
                  Alias "GetWindowLongA" _
                        (ByVal hWnd As Long, _
                         ByVal nIndex As Long) As Long
Private Declare Function GetCurrentThreadId Lib "kernel32" () As Long

Private myHookForm As Form
Private hHook As Long

Public Sub SetHook(ByRef myForm As Form)
Const GWL_HINSTANCE = (-6&)
Const WH_CBT = 5&
  Dim hInst As Long
  Dim lngThread As Long

  Set myHookForm = myForm

  hInst = GetWindowLong(myHookForm.hWnd, GWL_HINSTANCE)
  lngThread = GetCurrentThreadId()

  hHook = SetWindowsHookEx(WH_CBT, _
                           AddressOf WinProc, _
                           hInst, _
                           lngThread)

End Sub

Public Sub UnHook()
  Call UnhookWindowsHookEx(hHook)
  Set myHookForm = Nothing
End Sub

Private Function WinProc(ByVal nCode As Long, _
                         ByVal wParam As Long, _
                         ByVal lParam As Long) As Long
Const HCBT_SETFOCUS = 9&
  Dim myControl As Control
  On Error Resume Next

  If nCode = HCBT_SETFOCUS Then
    For Each myControl In myHookForm.Controls
      If myControl.hWnd = wParam Then
        myHookForm.Caption = myControl.Name
        myHookForm.Caption = myHookForm.Caption _
                           & "(" & myControl.Index & ")"
      End If
    Next
  End If

  Err.Clear
  On Error GoTo 0

  '次の処理へ
  WinProc = CallNextHookEx(hHook, nCode, wParam, lParam)
End Function

投稿時間:2002/08/22(Thu) 10:51
投稿者名:花ちゃん
Eメール:
URL :
タイトル:
(お礼)アクティブなテキスト
回答ありがとうございます。

現在はNo.52のとろさんの方法で実現しています。
この方法も勉強させて頂きます。

※ パスワードを保存されていれば 修正モード で 図表モード にチェックを入れて
  修正して頂ければタブ位置が保持されます。

投稿時間:2002/08/19(Mon) 12:35
投稿者名:とろ
Eメール:
URL :
タイトル:
Re: アクティブなテキストボックスを取得する方法
> (どのフォームのどのコントロールがアクティブになったかを取得したいのですが!)
> サブクラス化して取得する方法があれば教えて頂けないでしょうか?

これじゃダメかしら?
フォームモジュールとクラスモジュールを1つずつ用意して、下記のコードをコピペして、
フォーム上にテキストボックスを適当な数だけ配置して、実行してみて下さい。
注意:コントロール配列が設定されている( Index プロパティに値が入っている)
      場合はエラーになります。

'-- フォームモジュール
Option Explicit
Private cTextBox() As clsTextBox
Private Sub Form_Load()
  Dim ctrl  As Control
  Dim iCnt  As Integer
  iCnt = -1
  For Each ctrl In Me.Controls            '* 当フォーム上のコントロールすべてを処理
    If TypeName(ctrl) = "TextBox" Then    '* コントロールが TextBox ならば
      iCnt = iCnt + 1                     '* カウンタをインクリメント
      ReDim Preserve cTextBox(iCnt)       '* 配列を拡大
      Set cTextBox(iCnt) = New clsTextBox '* そこに新しいクラスを作成
      cTextBox(iCnt).TextBox = ctrl       '* それに TextBox をセット
    End If
  Next
End Sub
Private Sub Form_Unload(Cancel As Integer)
  Dim i As Integer
  For i = 0 To UBound(cTextBox())
    Set cTextBox(i) = Nothing
  Next i
End Sub

'-- clsTextBox.cls モジュール
Option Explicit
Private WithEvents m_TextBox As TextBox
Private Sub m_TextBox_GotFocus()
    Debug.Print m_TextBox.Name, "GotFocus"
End Sub
Public Property Let TextBox(oTextBox As TextBox)
  Set m_TextBox = oTextBox
End Property

後は、複数のフォームが存在する場合は、ここのフォームがロードされた時に、
同じような処理を行うだけです。
( cTextBox は配列より Collection の方が良いかもしれませんね。)

投稿時間:2002/08/19(Mon) 15:02
投稿者名:花ちゃん
Eメール:
URL :
タイトル:
(お礼)アクティブなテキストボックスを取得する方法
コードまで作って頂きありがとうございます。
これでいけそうなので、使わせて頂きます。

投稿時間:2002/08/23(Fri) 15:21
投稿者名:花ちゃん
Eメール:
URL :
タイトル:
(再質問)アクティブなテキストボックスを取得する方法
Re7:のサンプルを試させてもらったらなぜか Labelコントロールを貼り付けると
Labelコントロールだけしか表示しません。
Labelは hWnd プロパティを持っていないからでしょうか?
何か回避策があれば教えて下さい。

投稿時間:2002/08/23(Fri) 16:59
投稿者名:MS
URL :
タイトル:
Re: (再質問)アクティブなテキストボックスを取得する方法
> Re7:のサンプルを試させてもらったらなぜか Labelコントロールを貼り付けると
> Labelコントロールだけしか表示しません。
> Labelは hWnd プロパティを持っていないからでしょうか?

だと思います。
なので If myControl.hWnd = wParam Then でエラーになりますが、
On Error Resume Next なので If...Then の次も実行し、追加した
LabelがControlsコレクションの最終Itemなら、最後にそれを拾って
表示されるのだと思われます。
回避策は、例えば以下の様にする方法もあります。

Dim hWnd As Long
If nCode = HCBT_SETFOCUS Then
    For Each myControl In myHookForm.Controls
        Err.Clear
        hWnd = myControl.hWnd
        If (Err = 0) And (hWnd = wParam) Then
            myHookForm.Caption = myControl.Name
            myHookForm.Caption = myHookForm.Caption _
                                 & "(" & myControl.Index & ")"
        End If
    Next
End If

投稿時間:2002/08/23(Fri) 18:12
投稿者名:花ちゃん
Eメール:
URL :
タイトル:
(お礼)(再質問)アクティブなテキストボックスを取得する方法
MSさん、ありがとうございました
これでうまく動作しました。