为了使其脱颖而出,它需要在其边框周围的阴影.然而,将边界设置为bsNone的结果是,阴影消失.
各种Google来源提供了以下变体:
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集,这看起来很可怕).这是一个弹出窗口,而不是子窗口,所以我不明白为什么它应该失败.
有建议吗
注意:这是一个类似于this问题的问题,仍然没有答案.
NB2:有一个晦涩的VCI组件,称为TShadowWindow,看起来它会做正确的事情,但事实证明是太粗略地写实际.
更新:遵循Andreas在下面的评论,我进一步调查了这一点,并发现了一些好处.
在Windows 7下,我发现当弹出窗口在同一个应用程序的另一个窗口上时,阴影不会出现.
这是一个简单的Delphi应用程序,它在弹出窗口中使用CreateParams来请求如上所述的阴影.
看看阴影出现在主窗口以外的位置?
但是我想使用无边界窗口作为主窗口的弹出窗口.弹出的阴影将弹出窗口与下面的窗口区分开来.以上所有的描述都是指这种情况.显然有些Windows机制在这里干扰.
我也在Windows XP下尝试了相同的应用程序.这是它的外观.
这样可以随着影子无处不在.尔加!
所以这似乎是一个Vista / W7的事情,正如Andreas所说.
(*这个文本的早期版本和screendump建议没有阴影出现,但原来是因为我的Windows XP显示选项“菜单下的阴影”关闭了.
解决方法
你可以看到,现在的阴影在表单上正确显示.
问题是Z-order之一.事实证明,这个影子本身就是由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,SWP_NOACTIVATE or SWP_NOMOVE or SWP_NOOWNERZORDER or SWP_NOSIZE); end; end;
你必须找出什么时候调用FixSysShadowOrder(),因为Z命令改变了,它不会保持正确. Łukasz建议在空闲的程序中调用它(例如更新Action时),并且收到WM_WINDOWPOSCHANGED消息.