gpt4 book ai didi

Excel异常行为: hiding ribbon also hides TITLE bar if application is invisible

转载 作者:行者123 更新时间:2023-12-02 17:22:55 26 4
gpt4 key购买 nike

我正在创建一个自定义应用程序,它将在其自己单独的 Excel 实例(新应用程序)中启动。

新创建的实例默认不可见,因此需要手动使其可见。我喜欢仅在一切设置完毕后才让我的应用程序可见 - 以避免屏幕闪烁。我认为这是比关闭和打开 ScreenUpdating 更时尚的解决方案:即,如果应用程序无论如何都是不可见的,那么应该不需要切换 ScreenUpdating。在准备好之前,您可以将其保持不可见。

但是,我遇到了一些关于隐藏功能区的异常行为。以下命令:

Application.ExecuteExcel4Macro ("SHOW.TOOLBAR(" & Chr(34) & "Ribbon" & Chr(34) & ",False)")

...用于隐藏功能区。如果将命令简单地粘贴到“立即”窗口中,则可以看到其效果。它隐藏功能区:但应用程序窗口不受影响。但是...如果应用程序在执行此命令时不可见,则看起来不仅功能区被隐藏,而且窗口的整个标题栏也被隐藏!在以下子部分中对此进行测试:

Sub TestVisible()
Dim xl As Excel.Application
Set xl = New Excel.Application
xl.Workbooks.Add ' Required
' xl.Visible = True ' Un-comment out this line to preserve the Title bar
' If the following command is executed while Visible=False, then the TITLE bar will ALSO be hidden alongside the ribbon.
xl.ExecuteExcel4Macro ("SHOW.TOOLBAR(" & Chr(34) & "Ribbon" & Chr(34) & ",False)") ' Hide the ribbon
xl.Visible = True
End Sub

所以我的问题是:有人对这种行为有解释吗?这是一个错误吗?如果有,是否为人所知?如果不是,那么有解决办法吗? (除了在隐藏功能区之前简单地使应用程序可见,然后在需要时设置 ScreenUpdating 的解决方法之外。)

最佳答案

我在这方面花费的时间比我应该花的时间多:)但这里有一些解决方法,也是我认为的完整解决方案,因为它将“标题”栏恢复到新的 Excel 实例。

我可以推测“为什么”ExecuteExcel4Macro 在这里不能正常工作:

ExecuteExcel4Macro 实际上是一个可以追溯到 1995 年之前的 Excel 的遗留问题。它不经常使用,而且我认为其中很多功能不再起作用。使用它来隐藏功能区菜单栏——该菜单栏直到 2007 年才存在,它代表了对完全暴露于 VBA 的遗留 Application.CommandBars 的范式转变(例如:您无法像在 Excel <= 2003 中那样执行 Application.CommandBars("some command bar name").Visible = False) - 似乎可能存在一些 Microsoft 可能永远不会出现的错误地址。

通过使用各种 WinAPI 函数进行进一步调查,我发现一个有趣的事情是,当 Excel 不可见时,FindWindow 函数返回 0。我可能做错了什么,但如果没有,那么我猜测这在某种程度上导致了您观察到的行为。

解决方法(如果您对 WinAPI 不满意)

这是一种类似的方法,但功能区只是最小化,用户仍然可以切换:

Sub TestAlternate()
Dim xl As Excel.Application
Set xl = New Excel.Application
xl.Workbooks.Add ' Required
xl.Application.CommandBars.ExecuteMso ("HideRibbon")
xl.Visible = True
End Sub

调整原始代码的另一个可能的解决方法是强制新实例最小化(并且可见),以避免标题栏出现错误行为:

Sub TestVisible()
Dim xl As Excel.Application
Set xl = New Excel.Application
xl.Workbooks.Add ' Required
xl.Application.WindowState = xlMinimized
xl.Visible = True ' Un-comment out this line to preserve the Title bar
' If the following command is executed while Visible=False, then the TITLE bar will ALSO be hidden alongside the ribbon.
xl.ExecuteExcel4Macro ("SHOW.TOOLBAR(" & Chr(34) & "Ribbon" & Chr(34) & ",False)") ' Hide the ribbon
xl.Visible = False
xl.Application.WindowState = xlNormal

' any additional code required to set up/configure the new instance/application


xl.Visible = True
End Sub

第三种可能的解决方案如OP评论中提到的,我建议重构代码以从模板添加新工作簿。该模板将包含 CustomUI XML 规范和适当的 VBA 回调函数来隐藏功能区上的项目。我不能 100% 确定您可以使用此方法完全复制您的设计意图,对于初学者来说这不是一件小事,但它可能值得探索。

<小时/>

通过 WinAPI 调用隐藏功能区

我找到了this solution这很有希望,但实现比我预期的要复杂,但我认为我有一些适合您的目的的东西,是根据上述内容进行修改的。

在我所做的调试中,功能区和标题栏似乎紧密地联系在一起,您会注意到我根本不使用 ExecuteExcel4Macro,因为此函数调用需要还要照顾丝带。我怀疑这个链接可能会导致您原来的问题!

以下是 API Hook :

Option Explicit

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 GetWindowLong Lib "user32" Alias "GetWindowLongA" _
(ByVal hwnd As Long, ByVal nIndex As Long) As Long

Private Const GWL_STYLE = (-16)
Private Const WS_CAPTION = &HC00000
Private Const WS_MAXIMIZEBOX = &H10000
Private Const WS_MINIMIZEBOX = &H20000
Private Const WS_SYSMENU = &H80000

Private Declare Function SetWindowPos Lib "user32" _
(ByVal hwnd As Long, ByVal hWndInsertAfter As Long, _
ByVal x As Long, ByVal y As Long, ByVal cx As Long, _
ByVal cy As Long, ByVal wFlags As Long) As Long

Private Enum ESetWindowPosStyles
SWP_SHOWWINDOW = &H40
SWP_HIDEWINDOW = &H80
SWP_FRAMECHANGED = &H20
SWP_NOACTIVATE = &H10
SWP_NOCOPYBITS = &H100
SWP_NOMOVE = &H2
SWP_NOOWNERZORDER = &H200
SWP_NOREDRAW = &H8
SWP_NOREPOSITION = SWP_NOOWNERZORDER
SWP_NOSIZE = &H1
SWP_NOZORDER = &H4
SWP_DRAWFRAME = SWP_FRAMECHANGED
HWND_NOTOPMOST = -2
End Enum

Private Declare Function GetWindowRect Lib "user32" _
(ByVal hwnd As Long, lpRect As RECT) As Long

Private Type RECT
Left As Long
Top As Long
Right As Long
Bottom As Long
End Type

Sub ShowTitleBar(xlApp As Excel.Application, bShow As Boolean, Optional bCaptionOverride As Boolean = True)
Dim lStyle As Long
Dim tRect As RECT
'Dim sWndTitle As String
Dim xlhnd

'## I modified this function to receive an Application instance and
'## to use it's .Hwnd property rather than the FindWindow API call
xlhnd = xlApp.hwnd

'// Get the window's position:
GetWindowRect xlhnd, tRect

If Not bShow Then
lStyle = GetWindowLong(xlhnd, GWL_STYLE)
lStyle = lStyle And Not WS_SYSMENU
lStyle = lStyle And Not WS_MAXIMIZEBOX
lStyle = lStyle And Not WS_MINIMIZEBOX
'## I added this logic to ensure the CAPTION may always displayed if bCaptionOverride
If Not bCaptionOverride Then
lStyle = lStyle And Not WS_CAPTION
Else
lStyle = lStyle Or WS_CAPTION
End If
Else
lStyle = GetWindowLong(xlhnd, GWL_STYLE)
lStyle = lStyle Or WS_SYSMENU
lStyle = lStyle Or WS_MAXIMIZEBOX
lStyle = lStyle Or WS_MINIMIZEBOX
lStyle = lStyle Or WS_CAPTION
End If

SetWindowLong xlhnd, GWL_STYLE, lStyle

xlApp.DisplayFullScreen = Not bShow

'// Ensure the style is set and makes the xlwindow the
'// same size, regardless of the title bar.
SetWindowPos xlhnd, 0, tRect.Left, tRect.Top, tRect.Right - tRect.Left, _
tRect.Bottom - tRect.Top, SWP_NOREPOSITION Or SWP_NOZORDER Or SWP_FRAMECHANGED

End Sub

这是我们用于隐藏功能区的新子项,已在 Excel 2016 中进行了测试:

Sub Test()
Dim xl As New Excel.Application

xl.Workbooks.Add
ShowTitleBar xl, False

' configure the application

xl.Visible = True

' Re-enable the ribbon, or the user can double-click the title bar or Restore menu.
ShowTitleBar xl, True
End Sub

我在 Visible = True 语句后中断并确认功能区未显示:

enter image description here

最后,在过程结束时我们可以恢复功能区(如果需要)

enter image description here

<小时/>

注意:我注意到菜单中的“恢复”选项(右键单击标题栏中的 Excel 图标)不会恢复功能区,如果您使用 ExecuteExcel4Macro,但如果您使用 WinAPI 调用,它确实会恢复功能区。

enter image description here

如果您只是设置一个环境,那么这应该不重要,但我实现的方法并不能完全复制该功能。可以通过 WinAPI 进一步配置(例如,我知道您可以使用 lStyle = lStyle And Not WS_SYSMENU

从标题栏中删除该菜单

关于Excel异常行为: hiding ribbon also hides TITLE bar if application is invisible,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51672541/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com