显示用户表单后将焦点设置回应用程序 window

Set focus back to the application window after showing userform

当显示用户表单时(运行 它的 Show 方法),它不仅会显示在屏幕上,还会获得焦点(例如击键的目的地)。

比如说,用户窗体是一个定制的工具栏。它的 ShowWorkbook_Open() 中触发,但表单本身很少使用,因此我们希望焦点在它出现后立即返回到主应用程序 window。

不幸的是,SetFocus方法似乎对应用程序对象无效。

那么这是怎么做到的?

我想我的示例的解决方案出现在

之后
Private Sub Workbook_Open()
    [...]
    UserForm1.Show

对我来说

AppActivate ThisWorkbook.Application

Show 语句之后似乎工作正常。

其他情况

AppActivate "Microsoft Excel"

也可以吧

这有点棘手,但这是可以做到的。

在子程序“Private Sub UserForm_Initialize()”中,在最后一行添加:

Private Sub UserForm_Initialize()
    . . . . . . . . . . 
    Application.OnTime Now(), "MoveFocusToWorksheet"
End Sub

在任何通用代码模块中(如果有 none,请添加一个),声明一个 API 函数:

Public Declare Function SetForegroundWindow Lib "user32" (ByVal hwnd As Long) As Long

在任何通用代码模块(当然可以是带有 API 声明的模块)中,添加此子例程:

Public Sub MoveFocusToWorksheet()
    Dim Dummy As Long

    ThisWorkbook.Worksheets("Sheet1").Activate
    ' "Sheet1" here is the tab name of the sheet you want to move focus to. _
        Or simply use then: With shtABC.Activate _
        where "shtABC" being the worksheet's CodeName, _
        same as ThisWorkbook.Worksheets("Sheet1").CodeName, _
        same as the sheets module name showing in the Project Explorer panel.
    Dummy = SetForegroundWindow(Application.hwnd)
End Sub

我用这个:

AppActivate Application.caption

这会将焦点从用户表单重置为您的 Excel Sheet。

作为这个优秀讨论的脚注,在某些情况下,您可以通过跳过对 .Show 的调用来避免焦点问题,因此焦点从一开始就不会移动。例如对于 Word,如果您正在更新无模式窗体或对话框,只需更新所需区域并省略对 .Show 的调用,例如:

Sub ShowProblems(ByVal ProbLoc)
    EditBox2.TextBox.Text = "Here is the problem location: " & ProbLoc
    ' not needed: EditBox2.Show vbModeless
End Sub

我为应用程序创建了一个对象,例如Outlook,然后将 WindowSate 更改为最大化 (OlMaximized),然后当我想移除焦点时我最小化 (olMinimized)

Set OutlookObj = GetObject(, "Outlook.Application")
OutlookObj.ActiveExplorer.WindowState = olMinimized
OutlookObj.ActiveExplorer.WindowState = olMaximized

或者您从应用程序内部更改状态,您还可以更改其位置和大小等以获取更多信息,请参阅:https://msdn.microsoft.com/en-us/library/office/ff838577.aspx

Application.WindowState = xlMaximized
Private Sub UserForm_Activate()
    RefRangeIn.SetFocus
End Sub

它对我有用,在 excel 2013 VBA

添加一个虚拟表单并添加如下代码:

Private Sub SomeButton_Click()

    frm_Dummy.Show vbModeless
    Unload frm_Dummy

End Sub

Sub SomeSub()

    frm_Some.Show vbModeless
    frm_Dummy.Show vbModeless
    Unload frm_Dummy

End Sub

另一种形式是:

AppActivate ThisWorkbook.Name

我创建了一个带有用户表单的浮动菜单,并使用此代码使我的光标离开用户表单并 jump/focus 返回到我的工作表。它适用于每个命令按钮代码的末尾,也适用于用户表单的启动代码。

AppActivate ThisWorkbook.Application

只需将以上代码行放在任何命令按钮代码和初始显示用户窗体代码的 "End Sub" 行之前。

我用 应用激活 ActiveWindow.Caption 因为 应用激活 Application.Caption 如果为同一个工作簿打开多个 windows,可能会聚焦错误 window。

其他答案中提到的 AppActivate Application.Caption 和(更好的)AppActivate ActiveWindow.Caption 都在重新关注应用程序 window 本身……但他们 NOT 关注人们通常希望关注的实际 cell/range。为此,请使用:

ActiveCell.Activate

这样的好处是不需要在 sheet 的单元格区域上额外单击您想要 return 聚焦的位置 - 额外单击可能会更改之前的选择。