我在开发 Excel-Visio 应用程序的过程中花了相当多的时间在这个任务上,并面临同样的问题(Visio/Excel 和 VBA 编辑器上方的 Excel 表单被隐藏 - 但用户很容易失去焦点并且只能返回- Alt-Tabbing)。同样的问题!
我解决这个问题的算法是这样的(Userform 类中的所有代码):
Private Sub UserForm_Initialize()
'some init's above
ToggleExcel 'Toggle excel, all windows are hidden now!
ActivateVisio 'Visio fired and on top
SetStandAloneForm 'Let's customize form
End Sub
所以在启动时,我们就有了我们想要的 Visio 和 Form。在Terminate 事件上再次ToggleExcel 并最小化Visio。
ToggleExcel:
Private Function ToggleExcel()
Static IsVBEWasVisible As Boolean
With Application
If .Visible = True Then
IsVBEWasVisible = .VBE.MainWindow.Visible
If IsVBEWasVisible Then _
.VBE.MainWindow.Visible = False
.WindowState = xlMinimized
.Visible = False
Else
If IsVBEWasVisible Then _
.VBE.MainWindow.Visible = True
.WindowState = xlMaximized
.Visible = True
End If
End With
End Function
SetStandAloneForm:
为了 SetStandAloneForm 我声明了这个 API 函数块:
#If VBA7 Then
Private Declare PtrSafe Function GetWindowLong Lib "user32" Alias "GetWindowLongA" (ByVal hWnd As Long, ByVal nIndex As Long) As Long
Private Declare PtrSafe Function ShowWindow Lib "user32" (ByVal hWnd As Long, ByVal nCmdShow As Long) As Long
Private Declare PtrSafe Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Long
Private Declare PtrSafe Function SetWindowLong Lib "user32" Alias "SetWindowLongA" (ByVal hWnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long
Private Declare PtrSafe Function SetFocus Lib "user32" (ByVal hWnd As Long) As Long
#Else
Private Declare Function GetWindowLong Lib "user32" Alias "GetWindowLongA" (ByVal hWnd As Long, ByVal nIndex As Long) As Long
Private Declare Function ShowWindow Lib "user32" (ByVal hWnd As Long, ByVal nCmdShow As Long) As Long
Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Long
Private Declare Function SetWindowLong Lib "user32" Alias "SetWindowLongA" (ByVal hWnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long
Private Declare Function SetFocus Lib "user32" (ByVal hWnd As Long) As Long
#End If
实际SetStandAloneForm:
Private Function SetStandAloneForm()
Const GWL_STYLE As Long = -16
Const GWL_EXSTYLE As Long = -20
Const WS_CAPTION As Long = &HC00000
Const WS_MINIMIZEBOX As Long = &H20000
Const WS_MAXIMIZEBOX As Long = &H10000
Const WS_POPUP As Long = &H80000000
Const WS_VISIBLE As Long = &H10000000
Const WS_EX_DLGMODALFRAME As Long = &H1
Const WS_EX_APPWINDOW As Long = &H40000
Const SW_SHOW As Long = 5
Dim Hwnd As Long
Dim CurrentStyle As Long
Dim NewStyle As Long
If Val(Application.Version) < 9 Then
Hwnd = FindWindow("ThunderXFrame", Me.Caption) 'XL97
Else
Hwnd = FindWindow("ThunderDFrame", Me.Caption) '>XL97
End If
'Let's give to userform minimise and maximise buttons
CurrentStyle = GetWindowLong(Hwnd, GWL_STYLE)
NewStyle = CurrentStyle Or WS_MINIMIZEBOX Or WS_MAXIMIZEBOX
NewStyle = NewStyle And Not WS_VISIBLE And Not WS_POPUP
Call SetWindowLong(Hwnd, GWL_STYLE, NewStyle)
'Let's give to userform a taskbar icon
CurrentStyle = GetWindowLong(Hwnd, GWL_EXSTYLE)
NewStyle = CurrentStyle Or WS_EX_APPWINDOW
Call SetWindowLong(Hwnd, GWL_EXSTYLE, NewStyle)
Call ShowWindow(Hwnd, SW_SHOW)
End Function