gpt4 book ai didi

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

转载 作者:IT王子 更新时间:2023-10-29 04:02:37 27 4
gpt4 key购买 nike

我见过一些应用程序(可能不是 .NET 应用程序)在表单标题栏上的最小化按钮左侧有一个额外的按钮?如何在 C# 中实现此目的?

最佳答案

更新:添加了一个解决方案,适用于为 Windows Vista 和 Windows 7 启用的 Aero


***非航空解决方案***

窗口交互的非客户区由一系列非客户特定消息管理。例如WM_NCPAINT消息被发送到窗口过程来绘制非客户区。

我从来没有在 .NET 中这样做过,但我怀疑您可以覆盖 WndProc 并处理 WM_NC* 消息来实现您想要的。

更新:因为我从来没有在 .NET 上尝试过这个,所以我有几分钟的时间,我想我会快速尝试一下。

在 Windows 7 上尝试这个,我发现如果我想让操作系统对非客户区进行基本渲染,我需要禁用窗口的主题。所以这是一个简短的测试。我使用 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));
}
ReleaseDC(m.HWnd, hdc);
}
break;
}
}
}
}

顺便说一句。我调用了 DisableProcessWindowsGhosting,如果应用程序响应 Windows 消息的时间过长,这将阻止操作系统绘制非客户区。如果您不这样做,那么在某些情况下会呈现边框但不会显示您的装饰。因此,这取决于您的要求是否适合您。


***航空支持的解决方案***

在@TheCodeKing 的评论的提示下,我想我会再看看这个。事实证明,这可以在支持 Aero 的同时以完整记录的方式完成。但它不适合胆小的人。我不会在这里提供完整的解决方案,锻炼仍然存在一些问题,但它提供了基础知识。

此代码/解决方案基于可在以下位置找到的 Win32 示例 http://msdn.microsoft.com/en-us/library/bb688195(VS.85).aspx

原则上,您需要执行以下操作。

  • 扩展窗口的客户区以覆盖框架。这是通过处理 WM_NCCALCSIZE 消息并返回 0 来完成的。这使非客户区的大小为 0,因此客户区现在覆盖了整个窗口。
  • 使用 DwmExtendFrameIntoClientArea 将框架扩展到客户区.这让操作系统在客户区呈现框架。

以上步骤将为您提供一个带有标准玻璃框架的窗口,不包括系统菜单(窗口图标)和标题。最小化、最大化和关闭按钮仍将被绘制并起作用。你不能做的是拖动或调整窗口大小,这是因为框架并不真正存在,记住客户区覆盖了整个窗口,我们刚刚要求操作系统将框架绘制到客户区。

现在您可以像往常一样在窗口上绘图,甚至可以在框架顶部绘图。您甚至可以将控件放在标题区域。

最后,通过调用 DwmDefWindowProc 允许 DWM 为您处理 HitTest 。从你的 WndProc (在你处理它之前)。它返回一个 bool 值,指示 DWM 是否为您处理了消息。

关于c# - 如何在窗口的标题栏中添加一个额外的按钮?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2841180/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com