首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >无边界阴影的TForm

无边界阴影的TForm
EN

Stack Overflow用户
提问于 2010-08-20 10:33:14
回答 3查看 8.4K关注 0票数 14

我制作了一个TForm导数,它的作用就像组合体的下拉部分、提示窗口或弹出菜单--这是暂时的事情。它没有标题-它的BorderStyle被设置为bsNone。在设置了窗体的位置后,将非模式地使用Show显示窗体。

为了使它脱颖而出,它需要在其边界周围投下一个阴影。但是,将其边框设置为bsNone的结果是drop阴影消失。

谷歌的各种消息来源提出了各种不同的建议:

代码语言:javascript
复制
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:有一个名为TShadowWindow的晦涩的VCL组件,它看起来会做正确的事情,但它的编写过于粗糙,不太实用。

更新:在安德烈亚斯下面的评论之后,我对此做了进一步的调查,并发现了一些细节。

在Windows 7下,我发现当弹出窗口在同一应用程序的另一个窗口上时,阴影不会出现。

下面是一个简单的Delphi应用程序,它使用弹出窗口上的CreateParams请求阴影,如前所述。

看到放置阴影是如何出现在主窗口之外的地方的吗?

但是我想用无边界窗口作为主窗口的弹出窗口。下拉阴影将弹出窗口与下面的窗口区分开来。我上面所有的描述都提到了这种情况。显然,某些Windows机制正在干扰这里。

我也在Windows下尝试过相同的应用程序。下面是它的样子。

这对任何地方的阴影都是正确的。啊!

因此,正如安德烈亚斯所建议的那样,这似乎是Vista/W7的一件事。

(*较早版本的文本和屏幕显示没有影子出现。然而,这是因为我关闭了Windows显示选项“菜单下的阴影”。)

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2010-08-21 13:10:08

找到了!这是证据:

正如您所看到的,下拉阴影现在正确地显示在窗体上。

问题出在Z秩序上。事实证明,阴影本身就是Windows自己维护的一个单独的窗口。在Windows 7中,它似乎显示了主窗口下面的阴影。为了使它正确地显示,需要将它向上移动。

一个名为Łukasz Płomiński的天才在Embarcadero新闻组的一个线程中解释了这一点。下面是他整理的代码:

代码语言:javascript
复制
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命令会发生变化,而且不会保持正确。WM_WINDOWPOSCHANGED ukasz建议在空闲例程中调用它(例如,在更新操作时),并在收到Ł消息时调用它。

票数 8
EN

Stack Overflow用户

发布于 2010-08-20 14:09:55

“它在我的电脑上工作。”

(高分辨率)

但这是相当有趣的,因为我有一个微弱的记忆,作出了与您相同的结论,即,没有厚的,可调整的框架,CS_DROPSHADOW是无法工作的。您可能还在运行Windows吗?

票数 3
EN

Stack Overflow用户

发布于 2010-10-01 10:26:24

要使drop阴影工作,我们必须调用带有SystemParametersInfo win32参数的SPI_SETDROPSHADOW API,以打开整个系统的下降阴影效果,有关更多信息,请参见:

SystemParametersInfo

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/3530051

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档