如何创建一个命令按钮,告诉我哪个控件有FOCUS?

时间:2012-02-19 02:05:40

标签: forms vb6 focus controls

我在VB6表单上放了一个命令按钮。我想这样做,如果我单击此按钮,它将弹出一条消息,指示哪个控件最近有FOCUS。

我知道如果按下命令按钮,它将导致命令按钮获得焦点。我有兴趣在命令按钮将焦点从焦点上移开之前找出哪个控件具有焦点。我该怎么做?

3 个答案:

答案 0 :(得分:1)

Subclass按钮。
处理WM_SETFOCUS
采取相应行动。

实施例

表单Form1:

Option Explicit

Private Sub cmdCleverButton_Click()
  MsgBox cmdCleverButton.Tag
End Sub

Private Sub Form_Load()
  modCleverButtonSublass.SubclassCleverButton cmdCleverButton, Me
End Sub

Private Sub Form_Unload(Cancel As Integer)
  modCleverButtonSublass.UnsubclassCleverButton
End Sub

模块modCleverButtonSublass

Option Explicit

Private Declare Function SetWindowLong Lib "user32.dll" Alias "SetWindowLongA" (ByVal hwnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long
Private Declare Function CallWindowProc Lib "user32.dll" Alias "CallWindowProcA" (ByVal lpPrevWndFunc As Long, ByVal hwnd As Long, ByVal msg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long

Private Const GWL_WNDPROC As Long = -4&
Private Const WM_SETFOCUS As Long = &H7&


Private m_PrevWndProc As Long
Private m_Button As CommandButton
Private m_Form As Form


Public Sub SubclassCleverButton(ByVal b As CommandButton, ByVal ParentForm As Form)
  If Not m_Button Is Nothing Then Err.Raise 5, , "Already subslassed."

  Set m_Button = b
  Set m_Form = ParentForm
  m_PrevWndProc = SetWindowLong(m_Button.hwnd, GWL_WNDPROC, AddressOf SubclassCallback)
End Sub

Public Sub UnsubclassCleverButton()
  If m_Button Is Nothing Then Err.Raise 5, , "Subclass first."

  SetWindowLong m_Button.hwnd, GWL_WNDPROC, m_PrevWndProc
  Set m_Form = Nothing
  Set m_Button = Nothing
End Sub


Private Function SubclassCallback(ByVal hwnd As Long, ByVal uMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
  If uMsg = WM_SETFOCUS Then
    Dim c As Control

    Set c = FindByHwnd(m_Form, wParam)
    If c Is Nothing Then
      m_Button.Tag = vbNullString
    Else
      m_Button.Tag = c.Name
    End If
  End If

  SubclassCallback = CallWindowProc(m_PrevWndProc, hwnd, uMsg, wParam, lParam)
End Function

Private Function FindByHwnd(ByVal Parent As Form, ByVal hwnd As Long) As Control
  Dim c As Control

  For Each c In Parent.Controls
    If c.hwnd = hwnd Then
      Set FindByHwnd = c
      Exit Function
    End If
  Next
End Function

答案 1 :(得分:0)

Private lastControl As Control
Private lastFocus As Control

Private Sub Timer1_Timer()

Dim curControl As Control
Set curControl = Screen.ActiveControl

If lastControl Is Nothing Then
    Set lastControl = curControl
End If

If curControl.Name <> lastControl.Name Then 
    Set lastFocus = lastControl  'this line memorizes which control most recently just had FOCUS
    Set lastControl = curControl
End If

End Sub

答案 2 :(得分:0)

你需要一个简单的帮助聚焦转发类来做这件事而不需要像这样的子类化(不完整的样本类)

' cFocusFwd    
Option Explicit

Private WithEvents m_oCommand   As VB.CommandButton
Private WithEvents m_oCombo     As VB.ComboBox
Private WithEvents m_oText      As VB.TextBox
Private WithEvents m_oCheck     As VB.CheckBox
Private WithEvents m_oOption    As VB.OptionButton
Private WithEvents m_oExt       As VB.VBControlExtender
Private m_oForm                 As Object

Friend Function frInit(oCtl As Object, oForm As Object) As Boolean
    If TypeOf oCtl Is VB.CommandButton Then
        Set m_oCommand = oCtl
    ElseIf TypeOf oCtl Is VB.ComboBox Then
        Set m_oCombo = oCtl
    ElseIf TypeOf oCtl Is VB.TextBox Then
        Set m_oText = oCtl
    ElseIf TypeOf oCtl Is VB.CheckBox Then
        Set m_oCheck = oCtl
    ElseIf TypeOf oCtl Is VB.OptionButton Then
        Set m_oOption = oCtl
    ElseIf TypeOf oCtl Is VB.VBControlExtender Then
        Set m_oExt = oCtl
    Else
        Exit Function
    End If
    Set m_oForm = oForm
    '--- success
    frInit = True
End Function

Private Sub m_oCommand_GotFocus()
    m_oForm.ControlGotFocus m_oCommand
End Sub

Private Sub m_oCombo_GotFocus()
    m_oForm.ControlGotFocus m_oCombo
End Sub

Private Sub m_oText_GotFocus()
    m_oForm.ControlGotFocus m_oText
End Sub

Private Sub m_oCheck_GotFocus()
    m_oForm.ControlGotFocus m_oCheck
End Sub

Private Sub m_oOption_GotFocus()
    m_oForm.ControlGotFocus m_oOption
End Sub

Private Sub m_oExt_GotFocus()
    m_oForm.ControlGotFocus m_oExt
End Sub

然后在表单中使用它来接收关于子控件获取焦点的通知ControlGotFocus回调

Option Explicit

Private m_oLastFocused      As Object
Private m_cFocusFwds        As Collection

' this is called from cFocusFwd when control gets focus
Public Sub ControlGotFocus(oCtl As Object)
    If Not oCtl Is Command1 Then
        Set m_oLastFocused = oCtl
    End If
End Sub

Private Function pvInitFocusFwd(oCtl As Object, oForm As Object, Optional RetVal As cFocusFwd) As cFocusFwd
    Set RetVal = New cFocusFwd
    If RetVal.frInit(oCtl, oForm) Then
        Set pvInitFocusFwd = RetVal
    End If
End Function

Private Sub Form_Load()
    Dim oCtl        As Object

    Set m_cFocusFwds = New Collection
    For Each oCtl In Controls
        m_cFocusFwds.Add pvInitFocusFwd(oCtl, Me)
    Next
End Sub

Private Sub Command1_Click()
    MsgBox "Last active control is " & m_oLastFocused.Name, vbExclamation
End Sub

其中Command1是处理m_oLastFocused的命令按钮。

不幸的是,这种方法在控制阵列方面存在问题。子类化方法在无窗口控件方面也存在问题,这些控件也可以得到关注。