我做了一个TForm衍生物,就像组合的下拉部分,提示窗口或者popup式菜单一样,这是一个暂时的事情。 它没有标题 – 它的BorderStyle设置为bsNone。 使用Show非模态地显示窗体,设置其位置。
为了使其脱颖而出,它的边框周围需要阴影。 但是,将其边框设置为bsNone的结果是投影消失。
各种谷歌资源提出了这样的变化:
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集可调整的边界,这看起来很可怕 )。 这是一个popup窗口,而不是一个子窗口,所以我不明白为什么它会失败。
build议请?
注:这是一个类似的问题, 这个问题仍然没有答案。
NB2:有一个叫做TShadowWindow的不起眼的VCL组件,看起来好像做得对,但实际上却写得太粗糙。
更新:下面Andreas的评论,我进一步调查,发现一些细微差别。
在Windows 7中,我发现如果popup窗口位于同一应用程序的另一个窗口之上,则不会出现阴影。
这是一个简单的Delphi应用程序,它在popup窗口上使用CreateParams来请求如上所述的阴影。
看看阴影是如何出现在超出主窗口的地方?
但是我想在主窗口上使用无边框窗口作为popup窗口。 下拉阴影区分popup窗口和下面的窗口。 我上面的所有描述都是指这种情况。 显然有些Windows机制在这里干扰。
我也尝试在Windows XP下的相同的应用程序。 这是它的外观。
这与任何影子无论正确*。 尔加!
所以这似乎是一个Vista / W7的东西,正如Andreas所说的那样。
(*这个文本和screendump的早期版本暗示没有阴影出现,但是,原来这是因为我有Windows XP的显示选项“阴影在菜单下”closures。
找到了! 这是证明:
正如你所看到的那样,阴影现在可以在窗体上正确显示。
问题是Z顺序之一。 事实证明,影子本身就是Windows本身维护的一个单独的窗口。 在Windows 7中,它似乎在主窗口下面显示阴影。 为了正确显示它,需要将其移动。
一位名叫ŁukaszPłomiński的天才在Embarcadero新闻组的一个主题中解释了这一点。 这是他的代码来整理:
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;
你必须知道什么时候调用FixSysShadowOrder()
,因为Z命令改变了,它不会保持正确。 Łukasz建议在空闲的例程中调用它(例如更新一个Action时),以及接收到WM_WINDOWPOSCHANGED
消息。
“它在我的电脑上运行。”
http://privat.rejbrand.se/shdw.png
(高分辨率)
但是这很有趣,因为我有一个和你一样的结论,那就是, CS_DROPSHADOW
在没有厚重的,可调整大小的框架的情况下不起作用。 你还在运行Windows Vista吗?
为了使投影工作,我们必须调用带有SPI_SETDROPSHADOW参数的SystemParametersInfo win32 API来打开整个系统的投影效果,更多信息请参考:
SystemParametersInfo