我正在通过.NET clone(直接从Google云端硬盘下载)开发DeskPins Elias Fotinis的开源(GitHub)。它的主要功能是使其他窗户永远在顶部。当它们位于顶部时,标题栏中会添加一个图钉图标,如下所示:
Add Your Control On Top Another Application @ CodeProject
图钉图标在拖放过程中随窗口移动,看起来就像是它的一部分。它甚至会响应click事件,它会始终取消最高状态并从显示中删除图标。
问题。是否可以在C#中实现类似的东西(和p / invoke,我假设)?
研究
我试图运行这个项目。
这是一个WPF演示,它应该为标题栏添加一个自定义控件。似乎不适用于Windows 7 x64。不确定是操作系统还是其他操作系统。问题 - z顺序不一致,标题栏也出现在其他窗口的顶部,并且它不随窗口移动,它会尝试,但会出现大量的视觉效果和闪烁。
试图将此解决方案应用于#1:
基本上用这种模式替换对SetWindowLong的相关调用:
SetWindowLong(guestHandle, GWL_STYLE, GetWindowLong(guestHandle, GWL_STYLE) | WS_CHILD);
SetParent(guestHandle, hostHandle);
此更改打破了所有内容,因此标题栏中未添加任何内容。可能是它不适用于标题栏,仅适用于表单的用户区域。
无论如何,如果有一个简单的解决方案,请分享你的智慧。如果没有,我将非常感谢任何提示和/或链接,以便我进一步调查该主题。
答案 0 :(得分:6)
以下是我在DeskPins中的表现。
每个图钉都是一个弹出窗口,其自定义HRGN
定义其形状。我确实尝试过使用钩子并在标题上绘制一个DLL进入进程,但那对我来说太麻烦了。
DeskPins使用WS_POPUP
,WS_EX_TOPMOST
和WS_EX_TOOLWINDOW
创建图钉,其中0为父窗口。然后它立即向它发送一条消息(WM_PIN_ASSIGNWND
),传递要固定的目标窗口和以毫秒为单位的轮询速率。之后,引脚独立于DeskPins运行,它们只向对方发送信息消息。
引脚通过将目标窗口设置为其父窗口来处理WM_PIN_ASSIGNWND
,使其成为最顶层并启动轮询计时器。设置它使用的父级:
SetWindowLong(hPin, GWL_HWNDPARENT, (LONG)hPinned);
请注意,Microsoft警告不要像这样设置父级,而是建议使用SetParent()
。但是,SetParent()
会执行一些内部处理,以防止它跨进程工作。使用SetWindowLong(GWL_HWNDPARENT)
基本上欺骗窗口管理器接受这个。这有点像黑客,但是,嘿......它有效。
轮询计时器连续运行并测试目标窗口是否被破坏,隐藏,移动或其WS_EX_TOPMOST
标志是否已更改并作出适当响应。