绘制我自己的标题栏

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(使用前将#替换为@)

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

  • 如何从一个窗口窗体中访问其他窗体中的控件

    先生 我有两个窗口窗体 每个窗体都有一些控件 我想从一种表单访问另一种表单的控制权 我尝试过两种方法 1 公开控件并访问它们 2 根据需要进行公共属性的获取和设置控制 但在这两种情况下 我都必须创建第一种形式的对象才能访问属性或公共控件 我
  • SaveFileDialog 在 Windows XP 上静默崩溃 WinForms 应用程序

    我正在使用 C NET 4 0 和 DevExpress 组件开发 WinForms 应用程序 在 Windows 7 上一切正常 在 Windows XP SP3 上 SaveFileDialog 显示并关闭几秒钟后 应用程序将默默退出
  • 暴露底层控制的事件

    我在自定义控件中有一个组合框 如何向实现自定义控件的任何人 事物公开其中的特定事件 例如 SelectedIndexChanged 或 KeyPress 等 您可以像这样转发事件 public event EventHandler Sele
  • 在列标题上绘制矩形

    I m painting rectangle on the column headers in datagridview but on scrolling to right it disappears as in the picture s
  • Fortran DLL 导入

    Fortran 中有一段代码罗伯特 L 帕克和菲利普 B 斯塔克 http www stat berkeley edu 7Estark Code sbvq f FORTRAN subroutine bv key m n a b bl bu
  • System.Drawing.dll / NumericUpDown 的 .NET 访问冲突异常

    我遇到了一个非常愚蠢的问题 我已经尝试完全重新安装 NET 但它没有解决问题 我什至无法通过谷歌搜索找到其他有同样问题的人 就在我的计算机上 如果我将 NumericUpDown 控件添加到 NET 项目中的窗体并运行该应用程序 则在运行该
  • 有没有一种方法可以在 TreeView.Nodes 集合中搜索 TreeNode.Text 字段?

    像这样 TreeNode treeNodes treeView Nodes Find searchString true 但我希望它在text字段而不是name field 我不知道有任何内置方法 但你可以使用 LINQ TreeNode
  • 单击按钮时运行表单上的所有验证事件

    我有一个带有一些文本框和组合框的小表单 每个都有自己的验证事件 当用户移动到下一个框而不输入任何内容时 它只会填充默认值 1 或 0 具体取决于该框 但是我也想要当用户直接单击提交按钮时运行所有验证 private void Validat
  • 从任务并行库更新 ProgressBar UI 对象

    基本上我想更新 FormMain WindowsForm 上的 ProgressBar UI 对象 我正在使用 NET 4 0 以下是 Form1 Designer cs 中的代码 namespace ProgressBarApp publ
  • 基本 WinForm KeyDown 事件处理

    我正在使用 WinForms 我已经为KeyDown主窗体的事件 从而调用按钮的Click事件处理程序 The Click调用的事件处理程序取决于按下的特定键 如果用户单击该按钮而不是使用该键 然后随后尝试使用该键 则该键 例如向下箭头 将
  • 让设计者为 UserControl 的简单 List 属性生成 AddRange

    我创建了一个新的用户控件 如下所示 public partial class MyControl UserControl List
  • 滚动时在面板中平滑地绘制或绘制子控件

    在使用 Tab 控件的 TabPage 中的 Panel 控件时 我有很多子控件 如 RichTextBox 按钮 标签等 问题是当我在面板中滚动时 内部会闪烁 子控件没有像它们已经存在一样顺利地显示 淹没 绘制 寻找可以使滚动平滑并消除闪
  • 当 AxWindowsMediaPlayer 关闭时,出现 AccessViolation 异常

    我有一个AxWMPLib AxWindowsMediaPlayer在表格上 当我关闭表单时 我收到 尝试读取或写入受保护的内存 这通常表明其他内存已损坏 例外 隐藏表单可以 但关闭则不行 当组件从表单中删除时 一切都很好 这是Winform
  • 设置 Form.KeyPreview = true 的缺点?

    我想知道 Form KeyPreview 属性实际上有什么用处 它为什么存在以及将其设置为 true 会带来什么 风险 我想它一定有some负面影响 否则它根本不应该存在 或者至少默认情况下是正确的 EDIT 我很清楚what确实如此 我问
  • 当我使用 Image.FromFile() 时 FileNotFound

    我在这种情况下使用 Image FromFile string 方法 using System using System Collections Generic using System ComponentModel using Syste
  • 维护 app.config 中的字符串列表

    我想在 app config 中维护一个字符串列表 例如
  • 如何在文本框中插入图像

    有没有办法在文本框中插入图像 我正在开发一个聊天应用程序 我想用图标图像更改值 等 但我找不到如何在文本框中插入图像 Thanks 如果您使用 RichTextBox 进行聊天 请查看Paste http msdn microsoft co
  • 在 VB2010 Windows 窗体开始时播放 .wav/.mp3 文件?

    制作 VB2010 已经大约一年了 最近开始突破我可以将哪种媒体合并到我的表单中的界限 但我无法播放 wav 或 mp3 文件 我尝试按照微软和其他编码网站上的教程进行操作 但没有成功 任何帮助 将不胜感激 要播放波形文件 您可以简单地使用
  • F10键没被抓住

    I have a Windows Form and there overriden ProcessCmdKey However this works with all of the F Keys except for F10 I am tr
  • 如何强制执行特定的 UserControl 设计

    我正在编写一个基本用户控件 它将由一堆其他用户控件继承 我需要对所有这些后代控件强制执行某种设计 例如 顶部必须有几个按钮以及一个或两个标签 后代用户控件区域的其余部分可以自由放置任何内容 最初 我认为我可以将一个面板放到 Base Use

随机推荐