我尝试使用透明背景复制Windows 10风格的全屏模式对话框。除了标题栏,我的一切都很完美。
我无法摆脱它。我还禁用了窗口透明度的任何其他API子类。 Borderstyle设置为None,我隐藏了所有标题栏控件。表单设置为Popup和Modal
我这样打开它:
DoCmd.OpenForm "Modal_Full_Screen", acNormal, , , , acDialog
这些是我在Form_Load事件中调用的API调用,试图摆脱它:
Dim lStyle As Long
SetWindowLong Me.hwnd, GWL_EXSTYLE, GetWindowLong(Me.hwnd, GWL_EXSTYLE) And Not WS_EX_DLGMODALFRAME
SetWindowPos Me.hwnd, 0, 0, 0, 0, 0, SWP_FRAMECHANGED Or SWP_NOMOVE Or SWP_NOSIZE Or SWP_NOZORDER
lStyle = GetWindowLong(Me.hwnd, GWL_STYLE)
lStyle = lStyle And Not (WS_BORDER Or WS_DLGFRAME Or WS_MAXIMIZEBOX Or WS_MINIMIZEBOX Or WS_THICKFRAME Or WS_CAPTION)
Call SetWindowLong(Me.hwnd, GWL_STYLE, lStyle)
SetWindowPos Me.hwnd, 0, 0, 0, 0, 0, SWP_FRAMECHANGED Or SWP_NOMOVE Or SWP_NOSIZE Or SWP_NOZORDER
我绝对希望它停止处理并等待输入。我知道弹出窗口技巧,你打开一个循环,等待窗口关闭,但我不是DoEvents的粉丝,只是倾向于崩溃堆栈,特别是在更快的机器上。
如果这不可能有办法禁用或捕捉标题栏事件,点击并拖动它会从全屏恢复窗口(但双击它不会最大化它?)。
答案 0 :(得分:2)
这里有很多可能出错的事情。
要检查的第一件事是表单是否在表单load事件中实际具有窗口句柄。它可能不会。 (它不在.net的WinForms中。)在调用SetWindowLong
时设置断点,或者在进行API调用之前检查hwnd
的值是否为0。
要检查的第二件事是这些API调用的返回值实际上是什么。如果函数失败,SetWindowLong
返回0,除非窗口样式为0开始,在这种情况下,您需要在调用之前调用SetLastError(0)
,并使用GetLastError
的结果确定呼叫是否实际失败。在伪代码中,这看起来像:
SetLastError(0)
result = SetWindowLong(...)
if result = 0:
lastError = GetLastError()
if lastError <> 0:
' Handle the error here.
else:
' The window style is actually 0.
另请查看文档以获取SetWindowPos
的返回值。 (请记住,Windows API BOOL
类型实际上是32位整数。)您还应该使用GetWindowLong
来查看是否有任何窗口样式应用于窗口,因为如果窗口仍然是初始化,还没有得到它WM_CREATE
,它可能处于未确定的状态。这很好地引导下一件事要检查。
假设表单的句柄有效,并且API调用都是成功的,那么窗口在初始化期间重置其窗口样式的可能性很大,因为它应用了它的属性。要解决此问题,您可以将样式自定义移动到表单的Activate
事件,该事件最终显示在表单上并呈现给用户。
如果这些都不起作用,您可以继承窗口过程,并处理WM_NCHITTEST
消息。在英语中,窗口消息 - 非客户命中测试&#34;。窗口管理器将消息发送到窗口过程,以确定鼠标在任何给定点处的窗口的哪个部分。要禁用非客户区 1 中的所有内容,请使用HTCLIENT
回复消息,该消息向窗口管理器说明鼠标位于您的责任区域内。 (此消息也是您如何制作可由其背景拖动的表单。)
如果您想完全删除标题栏,并且您无法通过将边框样式设置为None
来管理它,则唯一的其他选项是处理WM_NCPAINT
消息,并手动绘制非客户区域。有关如何回复该消息的示例,请参阅documentation。
最后两个解决方案都需要更多的编程工作,但是StackOverflow和Web上的其他地方有很多示例。处理油漆至少需要4或5个额外的API调用。这实际上取决于从表单中删除标题栏的重要性。
1 为了大大过度简化,非客户区域代表标题栏,系统菜单,最小化和最大化按钮以及窗口边框。客户区域就是其他一切。