我在StackOverflow找到了这个问题。基本上,用户想在标题栏上绘制自定义按钮。
我尝试了代码,并且只有在Aero被禁用时才意识到它在vista / 7中有效。我的问题是,有没有办法在标题栏上绘制自定义按钮启用 aero?
此外,有没有办法从当前主题中读取信息,所以我可以设置我的按钮样式以匹配现有的按钮。
更新
以下是我的计算机的屏幕截图,展示了上述概念。安装DisplayFusion后,我得到了额外的标题栏按钮
我知道DisplayFusion是一个.NET程序,因为它在.NET Reflector中打开。缺点是程序被混淆了。不喜欢我想反编译程序或任何东西;我只想在标题栏上添加一个按钮来执行其他操作(例如,最小化到系统托盘) 下面是截图,证明该程序是一个.NET应用程序
答案 0 :(得分:4)
只要您愿意重新绘制整个标题栏内容,就可以使用DWM API的DwmExtendFrameIntoClientArea方法,该方法包括将窗口设置为没有标题栏,允许DWM将其玻璃绘制到可用区域创建一个看起来像标题栏但实际上在你的客户区域的新空间,这样你就可以在其上绘制按钮。
此方法的缺点是,如果需要,您必须制作标准按钮。最小化,最大化和关闭是没有问题重新创建(虽然你会发现最大化按钮是一个具有基于状态的外观的togglebutton),但你可能会发现重新创建左上角按钮的问题。当然,你还必须重新绘制你的标题,但我无法想象你会遇到任何问题。
至于阅读当前主题的数据,重新将你的按钮作为他们的按钮,我很抱歉,但我对此一无所知。我的建议是在标题栏上构建按钮时使用透明度,并使用半透明的发光效果等。这样你就可以保留玻璃背景,只需通过覆盖半透明的颜色来修改它的外观。此外,如果你这样做,那么玻璃上移动的镜面高光会自然地移动,而如果你只是得到他们的主题颜色,你会发现你没有获得他们的反射或他们重新重新创建按钮的空间。当然,只需要我的两分钱 - 如果你能找到一种方法来做主题颜色等等。
虽然有一点需要注意 - 还有另一个StackOverflow线程(http://stackoverflow.com/questions/2666979/net-framework-4-0-and-drawing-on-aero-glass-issue/4656182#4656182 )这是描述DWM API DwmExtendFrameIntoClientArea方法的一个问题,所以如果我是你,我会在尝试这个解决方案之前仔细阅读。
答案 1 :(得分:4)
我对此进行了一些研究,因为我在自己的多监视器解决方案中实现了这一点。 DisplayFusion和TeamViewer实现此方法的方法是将自定义表单覆盖在包含按钮的所需窗口上。您可以使用Spy ++来确认这一点。
这是一般的想法:
通过GetWindow
和SetWindowPos
API获取并设置Z位置
请注意,DLL必须使用本机语言编写。但是,你使用这样的东西来解决这个问题:
Using Window Messages to Implement Global System Hooks in C#
这是我的结果:
答案 2 :(得分:0)
好的,系统挂钩是获取有关已更改窗口位置信息的直接方法,而Jelle's提案采用透明形式非常好。但您可以使用侵入性较小的方法通过user32.dll
获取桌面窗口上的信息[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool GetWindowRect(HandleRef hWnd, out RECT lpRect);
使用EnumDesktopWindows
可以获得的窗口句柄[DllImport("user32.dll", EntryPoint = "EnumDesktopWindows",
ExactSpelling = false, CharSet = CharSet.Auto, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool EnumDesktopWindows(IntPtr hDesktop, EnumDelegate lpEnumCallbackFunction, IntPtr lParam);
获取此示例