显示用户窗体后,将焦点设置回应用程序窗口



当显示用户表单(运行其Show方法)时,它不仅显示在屏幕上,而且还占据焦点(例如击键的目标)。

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

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

那么这是怎么做到的呢?

我想我的例子的解决方案是在之后

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

我使用这个:

AppActivate Application.caption

这会将焦点从用户窗体重置为 Excel 工作表。

对我来说

AppActivate ThisWorkbook.Application

Show声明之后似乎工作正常。

在其他情况下

AppActivate "Microsoft Excel"

也可能没问题。

其他答案中提到的AppActivate Application.Caption和(更好的)AppActivate ActiveWindow.Caption都专注于应用程序窗口本身......但他们关注人们通常希望焦点的实际单元格/范围。为此,请使用:

ActiveCell.Activate

这样做的好处是不需要额外单击要返回焦点的工作表单元格区域 - 额外的单击可能会更改以前的选择。

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

在子例程"私有子UserForm_Initialize()"中,将其添加为最后一行:

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

在任何通用代码模块中(如果没有,请添加一个),声明一个 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

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

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

另一种形式是:

AppActivate ThisWorkbook.Name

我使用 AppActivate ActiveWindow.Caption因为 AppActivate Application.Caption如果为同一工作簿打开多个窗口,则可以聚焦错误的窗口。

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

Sub ShowProblems(ByVal ProbLoc)
    EditBox2.TextBox.Text = "Here is the problem location: " & ProbLoc
    ' not needed: EditBox2.Show vbModeless
End Sub
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

我创建了一个带有用户窗体的浮动菜单,并使用此代码使光标离开用户窗体并跳转/聚焦回工作表。它在每个命令按钮代码的末尾工作,也适用于用户窗体的启动代码。

应用程序

激活此工作簿.应用程序

只需将上面的代码行放在任何命令按钮代码的"结束子"行和初始显示用户表单代码之前即可。

最新更新