Drawing my own title bar

…衆ロ難τιáo~ 提交于 2019-12-02 14:41:06

问题


I'm drawing part of the title bar in my WinForm applications. Is working Ok (placing the name of the company centered and in Orange)

This is the code to do that at the form code:

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

The issue is resizing the window. The text is not cleared and shown several times. Is there a way to "Refresh" the title bar before drawing my text?

Thanks in advance.

EDIT Almost solved. Added two more methods:

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

and modified one:

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

By the way, the whole idea started from Copstone

Thanks Lars, Zach and of course, Jim. Your comments and answers put me on the way.


回答1:


A simple solution is to call gBarra.FillRectangle to fill the title bar with the background color before you draw the string.

Are you sure you need to do this in WM_PAINT? Seems like WM_NCPAINT would be enough.

I strongly recommend that you use try...finally to ensure that the DC gets released. That is:

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


来源:https://stackoverflow.com/questions/8312978/drawing-my-own-title-bar

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!