绘制我自己的标题栏

时间:2011-11-29 15:03:16

标签: winforms c#-3.0 dllimport

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

enter image description here

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

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;
     }
  }

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

提前致谢。

修改 几乎解决了。添加了两个方法:

  // 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

开始的

感谢Lars,Zach,当然还有Jim。你的意见和答案让我顺利。

1 个答案:

答案 0 :(得分:2)

一个简单的解决方案是在绘制字符串之前调用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);
     }
}