我工作的一个开源的.NET克隆的(GitHub的)DeskPins由埃利亚斯Fotinis(直接下载谷歌关闭驱动器).它的主要功能是使其他窗户永远在顶部.当它们位于顶部时,标题栏中会添加一个图钉图标,如下所示:
在拖放过程中,图钉图标随窗口移动,看起来就像是它的一部分.它甚至响应click事件,它会始终取消最高状态并从显示中删除图标.
题.是否有可能在C#中实现这样的东西(和p/invoke,我假设)?
研究
我试图运行这个项目.
将您的控件添加到另一个应用程序@ CodeProject上
这是一个WPF演示,它应该为标题栏添加一个自定义控件.似乎不适用于Windows 7 x64.不确定是操作系统还是其他操作系统.问题 - z顺序不一致,标题栏也出现在其他窗口的顶部,并且它不随窗口移动,它会尝试,但是很多视觉伪像和闪烁.
试图将此解决方案应用于#1:
将表单窗口附加到C#中的另一个窗口
基本上用这种模式替换对SetWindowLong的相关调用:
SetWindowLong(guestHandle, GWL_STYLE, GetWindowLong(guestHandle, GWL_STYLE) | WS_CHILD); SetParent(guestHandle, hostHandle);
此更改打破了所有内容,因此标题栏中未添加任何内容.可能是它不适用于标题栏,仅适用于表单的用户区域.
无论如何,如果有一个简单的解决方案,请分享你的智慧.如果没有,我将非常感谢任何提示和/或链接,以便我进一步调查该主题.
以下是我在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
标志是否已更改并作出适当响应.