绘制我自己的标题栏

2023-12-31

我正在我的 WinForm 应用程序中绘制标题栏的一部分。工作正常(将公司名称置于居中并以橙色显示)

这是在表单代码中执行此操作的代码:

using System.Runtime.InteropServices;


  [DllImport("user32.dll")]
  private static extern IntPtr GetWindowDC(IntPtr hWnd);

  [DllImport("user32.dll")]
  private static extern int ReleaseDC(IntPtr hWnd, IntPtr hDC);



  private Rectangle PosicionTexto()
  {
     string sTexto = String.Format("{0} : {1}", this.Text, "Trevo I.T.");
     sTexto = "Trevo I.T.";

     Graphics oG = this.CreateGraphics();

     SizeF oS = oG.MeasureString(sTexto, new Font("Tahoma", 8f, FontStyle.Bold));

     Rectangle rect = new Rectangle();
     rect.X = (this.Width/2) - (int)(oS.Width/2);
     rect.Y = SystemInformation.FrameBorderSize.Height + 4;
     rect.Width = (int)oS.Width;
     rect.Height = SystemInformation.CaptionButtonSize.Height;

     return rect;
  }

  private void DrawTitleBar(IntPtr hwnd)
  {
     // Obtenemos el Canvas a partir del DC de la ventana
     IntPtr hdc = GetWindowDC(hwnd);
     Graphics gBarra = Graphics.FromHdc(hdc);

     Rectangle rect = PosicionTexto();
     string sTexto = String.Format("{0} : {1}", this.Text, "Trevo I.T.");
     sTexto = "Trevo I.T.";
     gBarra.DrawString(sTexto, new Font("Tahoma", 8f, FontStyle.Bold), Brushes.Orange, new PointF(rect.X, rect.Y));

     // Liberamos la memoria*/
     gBarra.Flush();
     ReleaseDC(hwnd, hdc);
  }

  protected override void WndProc(ref Message m)
  {
     switch (m.Msg)
     {
        case 0x000F: // WM_PAINT
        case 0x0085: // WM_NCPAINT:
           base.WndProc(ref m);
           DrawTitleBar(m.HWnd);
           break;

        default:
           // Invocamos a la funcion original
           base.WndProc(ref m);
           break;
     }
  }

问题是调整窗口大小。文本未清除并显示多次。有没有办法在绘制文本之前“刷新”标题栏?

提前致谢。

EDIT差不多解决了。添加了另外两个方法:

  // Rectangle of the title bar
  private Rectangle TitleBarRectangle()
      {
         Rectangle rect = new Rectangle();
         rect.X = 1 + SystemInformation.CaptionButtonSize.Width;  // Avoid to draw over the icon
         rect.Y = 1;
         rect.Width = Width - (SystemInformation.CaptionButtonSize.Width * 4); // Avoid to draw over the buttons
         rect.Height = SystemInformation.CaptionButtonSize.Height;
         return rect;
      }

  // Draw a filled rectangle
  private void ClearTitleBar(IntPtr hwnd)
  {
     // Obtenemos el Canvas a partir del DC de la ventana
     IntPtr hdc = GetWindowDC(hwnd);

     try
     {
        using (Graphics gBarra = Graphics.FromHdc(hdc))
        {
           Rectangle rect = TitleBarRectangle();
           gBarra.FillRectangle(new SolidBrush(SystemColors.ActiveCaption), rect);
           gBarra.Flush();
        }
     }
     finally
     {
        ReleaseDC(hwnd, hdc);
     }
  }

并修改了一项:

  protected override void WndProc(ref Message m)
  {
     switch (m.Msg)
     {
        case 0x0085: // WM_NCPAINT:
        case 0x0005: // WM_SIZE
           base.WndProc(ref m);
           DrawTitleBar(m.HWnd);
           break;

        case 0x214:  //   WM_SIZING 
           base.WndProc(ref m);
           ClearTitleBar(m.HWnd);
           break;

        default:
           // Invocamos a la funcion original
           base.WndProc(ref m);
           break;
     }
  }

顺便说一下,整个想法是从Copstone http://copstone.com/2010/02/agregando-botones-a-la-barra-de-titulo-de-una-ventana/

谢谢拉尔斯、扎克,当然还有吉姆。您的评论和回答让我上路了。


一个简单的解决方案是调用gBarra.FillRectangle在绘制字符串之前用背景颜色填充标题栏。

您确定需要在 WM_PAINT 中执行此操作吗?似乎 WM_NCPAINT 就足够了。

我强烈建议您使用try...finally以确保 DC 被释放。那是:

private void DrawTitleBar(IntPtr hwnd)
{
     // Obtenemos el Canvas a partir del DC de la ventana
     IntPtr hdc = GetWindowDC(hwnd);
     try
     {
         using (Graphics gBarra = Graphics.FromHdc(hdc))
         {
             Rectangle rect = PosicionTexto();
             string sTexto = String.Format("{0} : {1}", this.Text, "Trevo I.T.");
             sTexto = "Trevo I.T.";
             gBarra.DrawString(sTexto, new Font("Tahoma", 8f, FontStyle.Bold), Brushes.Orange, new PointF(rect.X, rect.Y));

             // Liberamos la memoria*/
             gBarra.Flush();
         }   
     }
     finally
     {
         ReleaseDC(hwnd, hdc);
     }
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

绘制我自己的标题栏 的相关文章

  • 为什么 Application.Exit 无法工作?

    我有一个应用程序在取消对话框时出现奇怪的错误 如果该框被取消 应用程序将无法继续 因此它会退出 但由于某种原因它无法工作 因此它会继续运行并崩溃 我调试了这个问题 并且不知何故应用程序在 Application Exit 调用之后运行 我正
  • 如何禁用 Alt + F4 关闭表单?

    What is the best way to disable Alt F4 in a c win form to prevent the user from closing the form 我使用表单作为弹出对话框来显示进度条 但我不希
  • C# WinForms:使用一个或多个附加线程进行绘图。如何?

    如果我有一张包含各种几何形式 直线 矩形 圆形等 的大图 线程需要花费大量时间来绘制所有内容 但在现实生活中 一栋建筑是由不止一名工人建造的 因此 如果绘图是建筑物而线程是构建者 则绘制速度会快得多 但我想知道怎么做 你能告诉我怎么做吗 有
  • 如何使用 DateTime 计算已经过去了多少时间?

    我有一个启动操作的按钮单击事件 private void Diagnose Click object sender EventArgs e processfinish false timer2 Enabled true timerCount
  • 我应该如何缓冲绘制的矩形以提高性能(C#/.NET/WinForms/GDI+)

    我在做什么 我正在开发一个 C NET 4 7 2 WinForms 应用程序 它使用以下命令在表单上绘制大量填充矩形Graphics FillRectangle https learn microsoft com en us dotnet
  • 尝试用 C# 创建数学输入面板

    如何在 C 中创建数学输入面板 我尝试将其放入 dll 中并调用它 但它立即关闭 include
  • C# 中的空“if”语句是否会导致错误或警告?

    让我从一个现实生活中的例子开始 顾客 Alex 刚刚注意到 RemovalProcessor 第 138 行有一些奇怪的东西 if Session Handler ExecutePrefetchTasks null Session Exec
  • 匹配所有有效格式 IPv6 地址的正则表达式

    乍一看 我承认这个问题看起来像是这个问题以及与之相关的任何其他问题的重复 匹配有效 IPv6 地址的正则表达式 https stackoverflow com questions 53497 regular expression that
  • ComboBox DataBinding 导致 ArgumentException

    我的几个类对象 class Person public string Name get set public string Sex get set public int Age get set public override string
  • 如何填充 ToolStripComboBox?

    我发现它很难将数据绑定到ToolStripComboBox 好像没有这个ValueMember and DisplayMember特性 怎么绑定呢 访问toolstripcombobox中包装的组合框并访问其ValueMember Disp
  • 具有白色背景的组合框 DropDownList 样式

    我想要一个不可编辑的组合框 但仍然显示白色背景颜色 因此它的样式有效地类似于默认的组合框样式 DropDown ComboBoxStyle DropDownList 仅提供标准的 禁用 灰色背景色 简单地设置 BackColor Color
  • 使用按钮在表单之间传递变量[重复]

    这个问题在这里已经有答案了 我想知道如何将一个整数从 form1 传递到 form2 我尝试通过打开 form2 的按钮来执行此操作 但事件按钮单击无法识别整数 我该怎么办 在form1中 我有整数x 我希望当我单击button1时 for
  • 如何使对象在以表单呈现时“可缩放”

    我正在 Winform 中渲染我的游戏 方式与本示例中的方式相同 WinForms系列1 图形设备 http xbox create msdn com en US education catalog sample winforms seri
  • MaskedTextBox 的多行掩码

    我有一个MaskedTextBox在我的 Winforms 应用程序中 我需要一个多线掩码 例如 999999 r n 999999 r n 999999 r n 00 00 0000 我读了msdn文档 http msdn microso
  • 在运行时向父控件添加控件

    我需要将运行时添加的控件添加到父控件 面板 我可以设置对象的属性 PictureEdit 但如何显示它 将其添加到父控件 谢谢 protected override void OnPaint PaintEventArgs pe Pictur
  • 如何避免用户帐户控制或在Win7中始终以管理员模式运行Windows应用程序

    在 WinForms 应用程序中 当我的应用程序启动时 将出现 用户帐户控制 对话框 仅在 Windows 7 中 任何人都可以建议我如何以编程方式避免这种情况 也就是说我的应用程序应该始终以管理模式启动 或者是否有任何选项可以阻止此对话框
  • 如何避免选择项目时 winforms 树视图图标发生变化

    我正在一个小型 C Winforms 应用程序中尝试树视图 我已经以编程方式将 ImageList 分配给树视图 并且所有节点都很好地显示了它们的图标 but当我单击一个节点时 它的图标会发生变化 变为 ImageList 中的第一个图像
  • TabControl 和边框视觉故障

    我在每台电脑上都有这些视觉故障tabControls当我改变它的时候tabPages BackColor和BackColor的形式 如下图所示 在顶部tabPage 有一个内部单像素白色边框 在左侧tabPage 有一个内部三像素白色边框
  • 从所有动态生成的控件中获取文本总和

    我有一个 Windows 窗体 其中有下面列出的控件面板1 按钮1 添加新手机 按钮2 确定单击button1 时会添加一个用户控件 您可以根据需要添加任意数量的用户控件 userControl 定义由五个控件组成 组合框1 组合框2 文本
  • winform c# 中的弹出窗口

    我正在开发一个需要弹出窗口的项目 但问题是我还希望能够通过表单设计器在此弹出窗口中添加文本框等 所以基本上我有一个按钮 当您单击它时 它将打开我在表单设计器中设计的另一个窗口 我一直在谷歌搜索 但还没有找到我需要的东西 所以我希望你们能帮助

随机推荐