Borderless TForm with drop shadow
我制作了一个TForm派生类,它的作用类似于组合的下拉部分,提示窗口或弹出菜单-这是暂时的。它没有标题-它的BorderStyle设置为bsNone。设置位置后,使用"显示"以无模式显示该表单。
要使其脱颖而出,需要在其边框周围添加阴影。但是,将其边框设置为bsNone的结果是,阴影消失了。
各种各样的Google资料来源都建议这样做:
1 2 3 4 5 6 7 8 9 10 11 12 | procedure TdlgEditServiceTask.CreateParams(var Params: TCreateParams); const CS_DROPSHADOW = $00020000; begin inherited; { Enable drop shadow effect on Windows XP and later } if (Win32Platform = VER_PLATFORM_WIN32_NT) and ((Win32MajorVersion > 5) or ((Win32MajorVersion = 5) and (Win32MinorVersion >= 1))) then Params.WindowClass.Style := Params.WindowClass.Style or CS_DROPSHADOW; end; |
但是它不起作用-阴影不会显示(除非我也用WS_THICKFRAME设置了可调整大小的边框,看起来很糟糕)。这是一个弹出窗口,而不是子窗口,因此我看不出它为什么会失败。
请提出建议?
注意:这是与此问题类似的问题,但仍未得到解答。
NB2:有一个晦涩的VCL组件,称为TShadowWindow,看起来像做对的事情,但事实证明它太粗糙了,不实用。
更新:根据Andreas的以下评论,我对此进行了进一步调查,并发现了一些好处。
在Windows 7下,我发现如果弹出窗口位于同一应用程序的另一个窗口上方,则该阴影不会出现。
这是一个简单的Delphi应用程序,如上所述,它在弹出窗口上使用CreateParams来请求阴影。
看看投影在超出主窗口的地方如何显示?
但是我想使用无边界窗口作为主窗口的弹出窗口。阴影将弹出窗口与下面的窗口区分开。我上面的所有描述都是针对这种情况。显然,某些Windows机制会干扰这里。
我也在Windows XP下尝试了相同的应用程序。这是它的外观。
这可以在阴影无处不在的情况下正常工作*。加!
因此,就像Andreas建议的那样,这似乎是Vista / W7。
(*此文本和screendump的较早版本建议没有阴影出现。但是,事实证明是因为我关闭了Windows XP显示选项"菜单下的阴影"。是的。)
找到了!这是证明:
如您所见,阴影现在可以在表单上正确显示。
问题是Z阶之一。事实证明,阴影本身是Windows自己维护的单独窗口。在Windows 7中,似乎在主窗口下方显示阴影。为了使其正确显示,需要向上移动。
一个名叫" ukasz P?omi" ski的天才在Embarcadero新闻组的一个帖子中对此进行了解释。这是他的代码来解决:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 | procedure TForm1.FixSysShadowOrder; function FindSysShadowOrderProc(WindowHandle: HWND; // handle to window Form: TForm1 // application-defined value, 32-bit ): BOOL; stdcall; var Buffer: array [0 .. 255] of char; Rect: TRect; begin Result := True; if IsWindowVisible(WindowHandle) then begin // this code search for SysShadow window created for this window. GetClassName(WindowHandle, Buffer, 255); if 0 <> AnsiStrComp(Buffer, PChar('SysShadow')) then Exit; GetWindowRect(WindowHandle, Rect); if (Rect.Left <> Form.Left) or (Rect.Top <> Form.Top) then Exit; Form.FSysShadowHandle := WindowHandle; // stop enumeration Result := False; end; end; begin if not(csDesigning in ComponentState) and ((GetClassLong(Handle, GCL_STYLE) and CS_DROPSHADOW) = CS_DROPSHADOW) and IsWindowVisible(Handle) then begin // for speed, proper SysShadow handle is cached if FSysShadowHandle = 0 then EnumThreadWindows(GetCurrentThreadID(), @FindSysShadowOrderProc, lParam(Self)); // if SysShadow exists, change its z-order, and place it directly below this window if FSysShadowHandle <> 0 then SetWindowPos(FSysShadowHandle, Handle, 0, 0, 0, 0, SWP_NOACTIVATE or SWP_NOMOVE or SWP_NOOWNERZORDER or SWP_NOSIZE); end; end; |
您必须确定何时调用
要使阴影正常工作,我们必须使用SPI_SETDROPSHADOW参数调用SystemParametersInfo win32 API,以打开整个系统的阴影效果,有关更多信息,请参考:
SystemParametersInfo
"它可以在我的计算机上使用。"
(高分辨率)
但是这很有趣,因为我对做出与您相同的结论有微弱的记忆,即