我正在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;
}
}
问题在于调整窗口大小。文本未清除并多次显示。有没有办法在绘制文本之前“刷新”标题栏?
提前致谢。
修改 几乎解决了。添加了两个方法:
// 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。你的意见和答案让我顺利。
答案 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);
}
}