给ProgressBar添加文字,但不会重载OnPaint方法,就用了Graphics.DrawString()。
private void button2_Click(object sender, EventArgs e)
{
progressBar1.Value = Math.Min(progressBar1.Value+10, 100);
Graphics dc = progressBar1.CreateGraphics();
Font font = new Font("宋体", 10);
Brush br = Brushes.Black;
Rectangle rec = progressBar1.ClientRectangle;
StringFormat drawFormat = new StringFormat();
drawFormat.Alignment = StringAlignment.Center;
drawFormat.LineAlignment = StringAlignment.Center;
dc.DrawString(string.Format("{0}%", progressBar1.Value), font, br, rec, drawFormat);
}
但文字会一闪而逝。我猜是:ProgressBar.Value改变后,进度条没有立即重绘;Value的改变仅仅相当于是PostMessage到消息队列。之后Graphics.DrawString()绘制出文字。再之后进度条重绘,原文字被刷没了。
我想到的解决办法是,控件在重绘完成后是不是会产生一个事件,关联此事件到一个委托方法,在委托方法中Graphics.DrawString()就行了。
求大神提供方法,先行谢过了!
另外,ProgressBar.Value改变,进度条的变化怎么是连续且有延迟的?比如从0直接变成100,能明显看到进度条从空白慢悠悠地涨满,用时0.5秒左右。我想让这个改变一蹴而就,何解?
实在不行,有大神提供个现成的派生控件?再行谢过!
8 个解决方案
#2
#3
谢谢版主的回复,问题解决!
我在原文的基础上做了一些修改,可以显示任意字符,只要对Text属性赋值即可。如下:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Text;
using System.Windows.Forms;
namespace SimpleWindowsFormsControlLibrary
{
[ToolboxItem(true)]
public partial class TextProgressBar : System.Windows.Forms.ProgressBar
{
[System.Runtime.InteropServices.DllImport("user32.dll ")]
static extern IntPtr GetWindowDC(IntPtr hWnd);
[System.Runtime.InteropServices.DllImport("user32.dll ")]
static extern int ReleaseDC(IntPtr hWnd, IntPtr hDC);
// 添加文字相关的私有字段
private string text = "";
private Color textColor = Color.Black;
private Font font = new System.Drawing.Font("SimSun ", 9);
// 重写Text属性
[BrowsableAttribute(true)]
[BindableAttribute(true)]
public override string Text
{
get { return text; }
set { text = value; this.Invalidate(); }
}
// 文字颜色
public System.Drawing.Color TextColor
{
get { return textColor; }
set { textColor = value; this.Invalidate(); }
}
// 重写Font属性
[BrowsableAttribute(false)]
public override Font Font
{
get { return font; }
set { font = value; this.Invalidate(); }
}
protected override void WndProc(ref Message m)
{
base.WndProc(ref m);
if (m.Msg == 0xf || m.Msg == 0x133)
{
//拦截系统消息,获得当前控件进程以便重绘。
//一些控件(如TextBox、Button等)是由系统进程绘制,重载OnPaint方法将不起作用.
//所有这里并没有使用重载OnPaint方法绘制TextBox边框。
//MSDN:重写 OnPaint 将禁止修改所有控件的外观。
//那些由 Windows 完成其所有绘图的控件(例如 Textbox)从不调用它们的 OnPaint 方法,
//因此将永远不会使用自定义代码。请参见您要修改的特定控件的文档,
//查看 OnPaint 方法是否可用。如果某个控件未将 OnPaint 作为成员方法列出,
//则您无法通过重写此方法改变其外观。
//MSDN:要了解可用的 Message.Msg、Message.LParam 和 Message.WParam 值,
//请参考位于 MSDN Library 中的 Platform SDK 文档参考。可在 Platform SDK(“Core SDK”一节)
//下载中包含的 windows.h 头文件中找到实际常数值,该文件也可在 MSDN 上找到。
IntPtr hDC = GetWindowDC(m.HWnd);
if (hDC.ToInt32() == 0)
{
return;
}
//base.OnPaint(e);
System.Drawing.Graphics g = Graphics.FromHdc(hDC);
SolidBrush brush = new SolidBrush(textColor);
SizeF size = g.MeasureString(text, font);
float x = (this.Width - size.Width) / 2;
float y = (this.Height - size.Height) / 2;
g.DrawString(Text, font, brush, x, y);
// 下面的显示方法与上面的方法有相同的效果
//StringFormat format = new StringFormat();
//format.Alignment = StringAlignment.Center;
//format.LineAlignment = StringAlignment.Center;
//g.DrawString(text, font, brush, this.ClientRectangle, format);
//返回结果
m.Result = IntPtr.Zero;
//释放
ReleaseDC(m.HWnd, hDC);
}
}
}
}
#4
这可真是编程悲剧。你打算每次加一个功能,都破坏一次 WndProc ?
#5
重新修改了一下,让Font属性可见:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Text;
using System.Windows.Forms;
namespace SimpleWindowsFormsControlLibrary
{
[ToolboxItem(true)]
public partial class TextProgressBar : System.Windows.Forms.ProgressBar
{
[System.Runtime.InteropServices.DllImport("user32.dll ")]
static extern IntPtr GetWindowDC(IntPtr hWnd);
[System.Runtime.InteropServices.DllImport("user32.dll ")]
static extern int ReleaseDC(IntPtr hWnd, IntPtr hDC);
// 添加文字相关的私有字段
private string text = "";
private Color textColor = Color.Black;
private Font font = new Font("SimSun", 9F);
// 重写Text属性
[BrowsableAttribute(true)]
[BindableAttribute(true)]
public override string Text
{
get { return text; }
set { text = value; this.Invalidate(); }
}
// 文字颜色
public Color TextColor
{
get { return textColor; }
set { textColor = value; this.Invalidate(); }
}
// 重写Font属性
[BrowsableAttribute(true)]
public override Font Font
{
get { return font; }
set { font = value; this.Invalidate(); }
}
protected override void WndProc(ref Message m)
{
base.WndProc(ref m);
if (m.Msg == 0xf || m.Msg == 0x133)
{
//拦截系统消息,获得当前控件进程以便重绘。
//一些控件(如TextBox、Button等)是由系统进程绘制,重载OnPaint方法将不起作用.
//所有这里并没有使用重载OnPaint方法绘制TextBox边框。
//MSDN:重写 OnPaint 将禁止修改所有控件的外观。
//那些由 Windows 完成其所有绘图的控件(例如 Textbox)从不调用它们的 OnPaint 方法,
//因此将永远不会使用自定义代码。请参见您要修改的特定控件的文档,
//查看 OnPaint 方法是否可用。如果某个控件未将 OnPaint 作为成员方法列出,
//则您无法通过重写此方法改变其外观。
//MSDN:要了解可用的 Message.Msg、Message.LParam 和 Message.WParam 值,
//请参考位于 MSDN Library 中的 Platform SDK 文档参考。可在 Platform SDK(“Core SDK”一节)
//下载中包含的 windows.h 头文件中找到实际常数值,该文件也可在 MSDN 上找到。
IntPtr hDC = GetWindowDC(m.HWnd);
if (hDC.ToInt32() == 0)
{
return;
}
//base.OnPaint(e);
System.Drawing.Graphics g = Graphics.FromHdc(hDC);
SolidBrush brush = new SolidBrush(textColor);
SizeF size = g.MeasureString(text, font);
float x = (this.Width - size.Width) / 2;
float y = (this.Height - size.Height) / 2;
g.DrawString(Text, font, brush, x, y);
// 下面的显示方法与上面的方法有相同的效果
//StringFormat format = new StringFormat();
//format.Alignment = StringAlignment.Center;
//format.LineAlignment = StringAlignment.Center;
//g.DrawString(text, font, brush, this.ClientRectangle, format);
//返回结果
m.Result = IntPtr.Zero;
//释放
ReleaseDC(m.HWnd, hDC);
}
}
}
}
#6
对于着重于实际业务系统开发的人,我建议学点高级的 WPF 下的 XAML 酷设计,拒绝“玩儿” GDI 等东西。
#7
请问应该怎么改比较好?我刚学.net没几天。
#8
我是业余的,不是程序员。上学时学的C语言,后自学MFC和VB用来做些小工具。真要高级点的,我自学了Qt的一点皮毛。
想请教您一下,在WinForm里,这个问题如何解决比较合理?
#1
#2
#3
谢谢版主的回复,问题解决!
我在原文的基础上做了一些修改,可以显示任意字符,只要对Text属性赋值即可。如下:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Text;
using System.Windows.Forms;
namespace SimpleWindowsFormsControlLibrary
{
[ToolboxItem(true)]
public partial class TextProgressBar : System.Windows.Forms.ProgressBar
{
[System.Runtime.InteropServices.DllImport("user32.dll ")]
static extern IntPtr GetWindowDC(IntPtr hWnd);
[System.Runtime.InteropServices.DllImport("user32.dll ")]
static extern int ReleaseDC(IntPtr hWnd, IntPtr hDC);
// 添加文字相关的私有字段
private string text = "";
private Color textColor = Color.Black;
private Font font = new System.Drawing.Font("SimSun ", 9);
// 重写Text属性
[BrowsableAttribute(true)]
[BindableAttribute(true)]
public override string Text
{
get { return text; }
set { text = value; this.Invalidate(); }
}
// 文字颜色
public System.Drawing.Color TextColor
{
get { return textColor; }
set { textColor = value; this.Invalidate(); }
}
// 重写Font属性
[BrowsableAttribute(false)]
public override Font Font
{
get { return font; }
set { font = value; this.Invalidate(); }
}
protected override void WndProc(ref Message m)
{
base.WndProc(ref m);
if (m.Msg == 0xf || m.Msg == 0x133)
{
//拦截系统消息,获得当前控件进程以便重绘。
//一些控件(如TextBox、Button等)是由系统进程绘制,重载OnPaint方法将不起作用.
//所有这里并没有使用重载OnPaint方法绘制TextBox边框。
//MSDN:重写 OnPaint 将禁止修改所有控件的外观。
//那些由 Windows 完成其所有绘图的控件(例如 Textbox)从不调用它们的 OnPaint 方法,
//因此将永远不会使用自定义代码。请参见您要修改的特定控件的文档,
//查看 OnPaint 方法是否可用。如果某个控件未将 OnPaint 作为成员方法列出,
//则您无法通过重写此方法改变其外观。
//MSDN:要了解可用的 Message.Msg、Message.LParam 和 Message.WParam 值,
//请参考位于 MSDN Library 中的 Platform SDK 文档参考。可在 Platform SDK(“Core SDK”一节)
//下载中包含的 windows.h 头文件中找到实际常数值,该文件也可在 MSDN 上找到。
IntPtr hDC = GetWindowDC(m.HWnd);
if (hDC.ToInt32() == 0)
{
return;
}
//base.OnPaint(e);
System.Drawing.Graphics g = Graphics.FromHdc(hDC);
SolidBrush brush = new SolidBrush(textColor);
SizeF size = g.MeasureString(text, font);
float x = (this.Width - size.Width) / 2;
float y = (this.Height - size.Height) / 2;
g.DrawString(Text, font, brush, x, y);
// 下面的显示方法与上面的方法有相同的效果
//StringFormat format = new StringFormat();
//format.Alignment = StringAlignment.Center;
//format.LineAlignment = StringAlignment.Center;
//g.DrawString(text, font, brush, this.ClientRectangle, format);
//返回结果
m.Result = IntPtr.Zero;
//释放
ReleaseDC(m.HWnd, hDC);
}
}
}
}
#4
这可真是编程悲剧。你打算每次加一个功能,都破坏一次 WndProc ?
#5
重新修改了一下,让Font属性可见:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Text;
using System.Windows.Forms;
namespace SimpleWindowsFormsControlLibrary
{
[ToolboxItem(true)]
public partial class TextProgressBar : System.Windows.Forms.ProgressBar
{
[System.Runtime.InteropServices.DllImport("user32.dll ")]
static extern IntPtr GetWindowDC(IntPtr hWnd);
[System.Runtime.InteropServices.DllImport("user32.dll ")]
static extern int ReleaseDC(IntPtr hWnd, IntPtr hDC);
// 添加文字相关的私有字段
private string text = "";
private Color textColor = Color.Black;
private Font font = new Font("SimSun", 9F);
// 重写Text属性
[BrowsableAttribute(true)]
[BindableAttribute(true)]
public override string Text
{
get { return text; }
set { text = value; this.Invalidate(); }
}
// 文字颜色
public Color TextColor
{
get { return textColor; }
set { textColor = value; this.Invalidate(); }
}
// 重写Font属性
[BrowsableAttribute(true)]
public override Font Font
{
get { return font; }
set { font = value; this.Invalidate(); }
}
protected override void WndProc(ref Message m)
{
base.WndProc(ref m);
if (m.Msg == 0xf || m.Msg == 0x133)
{
//拦截系统消息,获得当前控件进程以便重绘。
//一些控件(如TextBox、Button等)是由系统进程绘制,重载OnPaint方法将不起作用.
//所有这里并没有使用重载OnPaint方法绘制TextBox边框。
//MSDN:重写 OnPaint 将禁止修改所有控件的外观。
//那些由 Windows 完成其所有绘图的控件(例如 Textbox)从不调用它们的 OnPaint 方法,
//因此将永远不会使用自定义代码。请参见您要修改的特定控件的文档,
//查看 OnPaint 方法是否可用。如果某个控件未将 OnPaint 作为成员方法列出,
//则您无法通过重写此方法改变其外观。
//MSDN:要了解可用的 Message.Msg、Message.LParam 和 Message.WParam 值,
//请参考位于 MSDN Library 中的 Platform SDK 文档参考。可在 Platform SDK(“Core SDK”一节)
//下载中包含的 windows.h 头文件中找到实际常数值,该文件也可在 MSDN 上找到。
IntPtr hDC = GetWindowDC(m.HWnd);
if (hDC.ToInt32() == 0)
{
return;
}
//base.OnPaint(e);
System.Drawing.Graphics g = Graphics.FromHdc(hDC);
SolidBrush brush = new SolidBrush(textColor);
SizeF size = g.MeasureString(text, font);
float x = (this.Width - size.Width) / 2;
float y = (this.Height - size.Height) / 2;
g.DrawString(Text, font, brush, x, y);
// 下面的显示方法与上面的方法有相同的效果
//StringFormat format = new StringFormat();
//format.Alignment = StringAlignment.Center;
//format.LineAlignment = StringAlignment.Center;
//g.DrawString(text, font, brush, this.ClientRectangle, format);
//返回结果
m.Result = IntPtr.Zero;
//释放
ReleaseDC(m.HWnd, hDC);
}
}
}
}
#6
对于着重于实际业务系统开发的人,我建议学点高级的 WPF 下的 XAML 酷设计,拒绝“玩儿” GDI 等东西。
#7
请问应该怎么改比较好?我刚学.net没几天。
#8
我是业余的,不是程序员。上学时学的C语言,后自学MFC和VB用来做些小工具。真要高级点的,我自学了Qt的一点皮毛。
想请教您一下,在WinForm里,这个问题如何解决比较合理?