gpt4 book ai didi

windows - 带投影的无边框 TForm

转载 作者:可可西里 更新时间:2023-11-01 12:27:42 31 4
gpt4 key购买 nike

我制作了一个 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:有一个不起眼的 VCL 组件叫做 TShadowWindow看起来它会做正确的事情,但事实证明它写得太粗糙而不实用。

更新:根据下面 Andreas 的评论,我对此进行了进一步调查,并发现了一些细节。

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

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

Windows 7 with shadow only over desktop

看到投影超出主窗口的地方是如何出现的吗?

但我想将无边框窗口用作主窗口上方的弹出窗口。投影将弹出窗口与下面的窗口区分开来。我上面的所有描述都指的是这种情况。显然,某些 Windows 机制在此处进行干扰。

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

Same application under XP

这对无处不在的阴影都能正常工作*。啊!

所以这似乎是 Vista/W7 的事情,正如 Andreas 所建议的那样。

(*此文本和屏幕转储的早期版本表明没有出现阴影。但是,结果证明这是因为我关闭了 Windows XP 显示选项“菜单下的阴影”。呃。)

最佳答案

找到了!证明如下:

alt text

如您所见,阴影现在可以正确地显示在表单上。

问题是 Z 顺序之一。原来,影子本身就是Windows自己维护的一个独立窗口。在 Windows 7 中,它似乎在主窗口下方显示阴影。为了使其正常显示,需要将其上移。

一位名叫 Łukasz Pł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 消息时调用它。

关于windows - 带投影的无边框 TForm,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3530051/

31 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com