扩展另一个应用程序的标题栏

时间:2015-12-27 20:18:24

标签: c# winforms pinvoke titlebar

我正在通过.NET clone(直接从Google云端硬盘下载)开发DeskPins Elias Fotinis的开源enter image description here(GitHub)。它的主要功能是使其他窗户永远在顶部。当它们位于顶部时,标题栏中会添加一个图钉图标,如下所示:

Add Your Control On Top Another Application @ CodeProject

图钉图标在拖放过程中随窗口移动,看起来就像是它的一部分。它甚至会响应click事件,它会始终取消最高状态并从显示中删除图标。

问题。是否可以在C#中实现类似的东西(和p / invoke,我假设)?

研究

  1. 我试图运行这个项目。

  2. 这是一个WPF演示,它应该为标题栏添加一个自定义控件。似乎不适用于Windows 7 x64。不确定是操作系统还是其他操作系统。问题 - z顺序不一致,标题栏也出现在其他窗口的顶部,并且它不随窗口移动,它会尝试,但会出现大量的视觉效果和闪烁。

    1. 试图将此解决方案应用于#1:

    2. 基本上用这种模式替换对SetWindowLong的相关调用:

      SetWindowLong(guestHandle, GWL_STYLE, GetWindowLong(guestHandle, GWL_STYLE) | WS_CHILD);
      SetParent(guestHandle, hostHandle);
      

      此更改打破了所有内容,因此标题栏中未添加任何内容。可能是它不适用于标题栏,仅适用于表单的用户区域。

      无论如何,如果有一个简单的解决方案,请分享你的智慧。如果没有,我将非常感谢任何提示和/或链接,以便我进一步调查该主题。

1 个答案:

答案 0 :(得分:6)

以下是我在DeskPins中的表现。

每个图钉都是一个弹出窗口,其自定义HRGN定义其形状。我确实尝试过使用钩子并在标题上绘制一个DLL进入进程,但那对我来说太麻烦了。

DeskPins使用WS_POPUPWS_EX_TOPMOSTWS_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标志是否已更改并作出适当响应。