- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
Mike Lischke 的 TThemeServices
子类 Application.Handle
,以便在主题更改时可以接收来自 Windows 的广播通知(即 WM_THEMECHANGED
)。
它是 Application
对象窗口的子类:
FWindowHandle := Application.Handle;
if FWindowHandle <> 0 then
begin
// If a window handle is given then subclass the window to get notified about theme changes.
{$ifdef COMPILER_6_UP}
FObjectInstance := Classes.MakeObjectInstance(WindowProc);
{$else}
FObjectInstance := MakeObjectInstance(WindowProc);
{$endif COMPILER_6_UP}
FDefWindowProc := Pointer(GetWindowLong(FWindowHandle, GWL_WNDPROC));
SetWindowLong(FWindowHandle, GWL_WNDPROC, Integer(FObjectInstance));
end;
子类化的窗口过程然后按照预期执行 WM_DESTROY
消息,删除其子类,然后将 WM_DESTROY
消息传递给:
procedure TThemeServices.WindowProc(var Message: TMessage);
begin
case Message.Msg of
WM_THEMECHANGED:
begin
[...snip...]
end;
WM_DESTROY:
begin
// If we are connected to a window then we have to listen to its destruction.
SetWindowLong(FWindowHandle, GWL_WNDPROC, Integer(FDefWindowProc));
{$ifdef COMPILER_6_UP}
Classes.FreeObjectInstance(FObjectInstance);
{$else}
FreeObjectInstance(FObjectInstance);
{$endif COMPILER_6_UP}
FObjectInstance := nil;
end;
end;
with Message do
Result := CallWindowProc(FDefWindowProc, FWindowHandle, Msg, WParam, LParam);
end;
TThemeServices
对象是一个单例,在单元终结期间被销毁:
initialization
finalization
InternalThemeServices.Free;
end.
一切都运行良好 - 只要 TThemeServices 是唯一对应用程序句柄进行子类化的人。
我有一个类似的单例库,它也想 Hook Application.Handle
这样我就可以接收广播:
procedure TDesktopWindowManager.WindowProc(var Message: TMessage);
begin
case Message.Msg of
WM_DWMCOLORIZATIONCOLORCHANGED: ...
WM_DWMCOMPOSITIONCHANGED: ...
WM_DWMNCRENDERINGCHANGED: ...
WM_DESTROY:
begin
// If we are connected to a window then we have to listen to its destruction.
SetWindowLong(FWindowHandle, GWL_WNDPROC, Integer(FDefWindowProc));
{$ifdef COMPILER_6_UP}
Classes.FreeObjectInstance(FObjectInstance);
{$else}
FreeObjectInstance(FObjectInstance);
{$endif COMPILER_6_UP}
FObjectInstance := nil;
end;
end;
with Message do
Result := CallWindowProc(FDefWindowProc, FWindowHandle, Msg, WParam, LParam);
当单元完成时,我的单例也会被类似地删除:
initialization
...
finalization
InternalDwmServices.Free;
end.
<小时/>
现在我们来解决问题了。我无法保证某人可能选择访问 ThemeServices
或 DWM
的顺序,每个都应用其子类。我也不知道 Delphi 最终确定单元的顺序。
子类被以错误的顺序删除,并且应用程序关闭时发生崩溃。
如何解决?我怎样才能ensure that i keep my subclassing method around long enough until the other guy is done我完成后? (毕竟我不想泄漏内存)
更新:我看到 Delphi 7 通过重写 TApplication
解决了该错误。 ><
procedure TApplication.WndProc(var Message: TMessage);
...
begin
...
with Message do
case Msg of
...
WM_THEMECHANGED:
if ThemeServices.ThemesEnabled then
ThemeServices.ApplyThemeChange;
...
end;
...
end;
咕噜咕噜
换句话说:尝试子类化 TApplication 是一个错误,Borland 在采用 Mike 的 TThemeManager
时修复了该错误。
这很可能意味着无法以相反的顺序删除 TApplication
上的子类。有人以答案的形式提出了这个问题,我会接受。
最佳答案
更改您的代码以调用 SetWindowSubclass
,正如您链接到的文章所建议的那样。但这只有在每个人都使用相同的 API 时才有效,因此请修补主题管理器以使用相同的技术。该 API 是在 Windows XP 中引入的,因此不存在在需要它的系统上不可用的危险。
给主题管理器打补丁应该没有问题。它旨在支持 Windows XP(Microsoft 不再支持),以及支持 Delphi 4 到 6(Borland 不再支持)。由于所有相关产品的开发都已停止,因此您可以安全地 fork 主题管理器项目,而不会因 future 的更新而面临落后的风险。
您并没有真正引入依赖项。相反,您正在修复仅在同时使用两个窗口外观库时才会出现的错误。您的库的用户不需要主题管理器即可工作,但如果他们希望同时使用两者,则需要在应用了您的补丁后使用主题管理器。对此应该没有什么异议,因为他们已经有了基本版本,所以他们不会安装一个全新的库。他们只是应用补丁并重新编译。
关于Delphi:如何以相反的顺序删除子类?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4616535/
这个问题不太可能帮助任何 future 的访问者;它只与一个小的地理区域、一个特定的时间点或一个非常狭窄的情况有关,这些情况并不普遍适用于互联网的全局受众。为了帮助使这个问题更广泛地适用,visit
我想从输入对象内部开始找到下一个表单元素。Find() 是查找子对象的绝佳函数。但是在父级中寻找相反的方法呢?
是否可以执行$(this)的相反操作? 因此,它不是获取 this 元素,而是获取与 .sb-popular-thumb a 匹配但不包括 $(this) 的所有内容? 请参阅下面的示例代码。我已用
这是一个关于术语的问题。 考虑到有一个方法使用词法this: var foo = { method: function () { console.log(this, ' is the co
我想问你是否存在一个与 WHERE IN 相反的命令,我想选择数组中具有不同参数的所有行。 1 && id <> 2 && id <> 3"; // how can i do the same q
是否有语法来获取不在给定切片内的列表元素?给定切片 [1:4] 很容易得到这些元素: >>> l = [1,2,3,4,5] >>> l[1:4] [2, 3, 4] 如果我想要列表的其余部分,我可以
这个问题在这里已经有了答案: How can I remove a specific item from an array? (138 个回答) 关闭8年前。 JavaScript push(); 方
在此先感谢您的帮助。这是一个很棒的社区,我在这里找到了许多编程答案。 我有一个包含多个列的表,其中5个包含日期或null。 我想编写一个本质上将5列合并为1列的sql查询,条件是如果5列中的1包含“N
我使用 hasClass() 在 if 语句中验证元素是否具有给定的类。 如果元素没有给定的类,如何检查 if 语句?预先感谢您的回复。 最佳答案 为什么不简单地: if (!el.hasClass(
我有一个 std::vector v我想防止进一步写入它。 C++ 编译器不接受这个 const std::vector& w = v; 但它接受这个 const std::vector& w = r
这个问题已经有答案了: How to reshape data from long to wide format (14 个回答) 已关闭 7 年前。 我有像这样的巨大数据框: SN = c(1:10
如何将可调用(匿名函数)转换为字符串进行评估? 我正在尝试在 phpunit 中编写使用 runkit 的单元测试覆盖方法。特别是,runkit_method_redefine() 需要一个字符串参数
我想实现一个堆栈(队列),许多用户可以以 FILO 方式将其推送(),并且许多用户可以从中弹出()。 是否有与 pop() 等效的方法来检索/删除列表的最后一项? 例如: var popRef = f
我想知道“无状态协议(protocol)”的反面是什么。例如,鉴于 HTTP 是无状态的,那么像 FTP 这样的协议(protocol)是相反的/维护状态的协议(protocol),我的假设是否正确?
我对array_filter很熟悉,想往功能上想,但我想知道有没有办法保留被丢弃的值?例如,如果我有一个像这样的数组: 2; }); 结果将是:array( 3, 4 )。 有没有办法保留丢弃的值
我已将色轮的图像加载到 Canvas 上,并且在数组中有一个色相值列表。我遍历 Canvas 上的每个像素,并删除匹配相同色相值的像素。 该代码是: var element = document.ge
这个问题在这里已经有了答案: Repeat each row of data.frame the number of times specified in a column (10 个答案) 关闭
如何将可调用(匿名函数)转换为字符串以进行评估? 我正在尝试在使用 runkit 的 phpunit 中编写单元测试覆盖方法。特别是,runkit_method_redefine() 需要一个字符串参
我对array_filter很熟悉,想往功能上想,但我想知道有没有办法保留被丢弃的值?例如,如果我有一个像这样的数组: 2; }); 结果将是:array( 3, 4 )。 有没有办法保留丢弃的值
很难说出这里问的是什么。这个问题是含糊的、模糊的、不完整的、过于宽泛的或修辞性的,无法以目前的形式得到合理的回答。如需帮助澄清此问题以便重新打开它,visit the help center 。 已关
我是一名优秀的程序员,十分优秀!