如何在窗口的标题栏中添加一个额外的按钮?
我已经看到某些应用程序(可能不是.NET应用程序)在表单标题栏上的“最小化”按钮左侧有一个额外的按钮吗?如何在C#中实现呢?
回答:
:添加了一个解决方案,该解决方案将与启用了Windows Vista和Windows 7的Aero一起使用
窗口交互的非客户区域由一系列非客户特定消息管理。例如,将WM_NCPAINT消息发送到窗口过程以绘制非客户区。
我从未从.NET做到这一点,但我怀疑您可以覆盖WndProc并处理WM_NC *消息以实现所需的功能。
更新:因为我从没有尝试过.NET,所以花了几分钟时间,我想我可以快速尝试一下。
在Windows
7上尝试此操作,我发现如果我想让OS进行非工作区的基础渲染,则需要禁用窗口主题。因此,这是一个简短的测试。我使用GetWindowDC而不是GetDCEx来获取整个窗口的DC,这仅仅是因为我可以从内存中互操作,并且没有查找GetDcEx的所有标志常量。当然,该代码可以执行更多错误检查。
using System;using System.Drawing;
using System.Windows.Forms;
using System.Runtime.InteropServices;
namespace WindowsFormsApplication1
{
public partial class CustomBorderForm : Form
{
const int WM_NCPAINT = 0x85;
[DllImport("user32.dll", SetLastError = true)]
public static extern IntPtr GetWindowDC(IntPtr hwnd);
[DllImport("user32.dll", SetLastError = true)]
public static extern int ReleaseDC(IntPtr hwnd, IntPtr hdc);
[DllImport("user32.dll", SetLastError = true)]
public static extern void DisableProcessWindowsGhosting();
[DllImport("UxTheme.dll", SetLastError = true, CharSet = CharSet.Unicode)]
public static extern IntPtr SetWindowTheme(IntPtr hwnd, string pszSubAppName, string pszSubIdList);
public CustomBorderForm()
{
// This could be called from main.
DisableProcessWindowsGhosting();
InitializeComponent();
}
protected override void OnHandleCreated(EventArgs e)
{
SetWindowTheme(this.Handle, "", "");
base.OnHandleCreated(e);
}
protected override void WndProc(ref Message m)
{
base.WndProc(ref m);
switch (m.Msg)
{
case WM_NCPAINT:
{
IntPtr hdc = GetWindowDC(m.HWnd);
using (Graphics g = Graphics.FromHdc(hdc))
{
g.FillEllipse(Brushes.Red, new Rectangle((Width-20)/2, 8, 20, 20));
}
int r = ReleaseDC(m.HWnd, hdc);
}
break;
}
}
}
}
顺便说一句。我叫DisableProcessWindowsGhosting
,如果应用程序响应Windows消息花费的时间太长,这将阻止OS绘制非客户区。如果您不这样做,则在某些情况下将渲染边框,但不会显示您的装饰。因此,这取决于您的要求,它是否适合您。
在@TheCodeKing的评论提示下,我想我会再来看一下。事实证明,可以在支持Aero的同时以完整记录的方式完成此操作。但这不是为了胆小的人。在这里,我将不提供完整的解决方案,但仍有一些锻炼方法,但是它具有基本知识。
此代码/解决方案基于Win32示例,该示例可在以下位置找到: http://msdn.microsoft.com/zh-
cn/library/bb688195(VS.85).aspx
原则上,您需要执行以下操作。
- 扩展窗口的工作区以覆盖框架。这是通过处理WM_NCCALCSIZE消息并返回0来完成的。这使非客户端区域的大小为0,因此客户端区域现在覆盖了整个窗口。
- 使用DwmExtendFrameIntoClientArea将Frame扩展到工作区。这使操作系统可以在客户端区域上渲染框架。
以上步骤将为您提供带有标准玻璃框的窗口,但不包括系统菜单(“窗口”图标)和标题。最小化,最大化和关闭按钮仍将绘制并起作用。您将无法执行的操作是拖动或调整窗口大小,这是因为框架并不真正存在,请记住客户区域覆盖了整个窗口,我们只是要求操作系统将框架绘制到客户区域上。
现在,您可以像平常一样在窗口上绘制,甚至可以在框架顶部绘制。您甚至可以将控件放在字幕区域。
最后,通过从您的DwmDefWindowProc调用DWMWndProc
(在处理它之前),为您处理命中测试。它返回一个布尔值,指示DWM是否为您处理了该消息。
以上是 如何在窗口的标题栏中添加一个额外的按钮? 的全部内容, 来源链接: utcz.com/qa/407623.html