窗口 – 无边界TForm与阴影

前端之家收集整理的这篇文章主要介绍了窗口 – 无边界TForm与阴影前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我已经制作了一个TForm衍生物,它像组合,提示窗口或弹出菜单的下拉部分 – 一个暂时的东西.它没有标题 – 其BorderStyle设置为bsNone.表单以非模态方式显示,使用Show设置其位置.

为了使其脱颖而出,它需要在其边框周围的阴影.然而,将边界设置为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消息.

猜你在找的Delphi相关文章