如何在窗口的标题栏中添加一个额外的按钮?

我已经看到某些应用程序(可能不是.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

回到顶部