如何在 ToolStrip 上渲染图形
How to render graphics on ToolStrip
我创建了一个自定义用户控件,它将显示文本和一个指示灯来显示我们服务的当前 运行 状态,如下表所示。它在窗体上工作得很好,但我想把它放在 StatusStrip 控件上。我创建了一个派生自 ToolStripControlHost 的 class 以启用对 StatusStrip 上我的控件的支持,但它根本不呈现。控件的宽度为零,并且在 IDE 中打开时窗体会闪烁。
我查看了 ToolStripRendering class,但在我看来,它旨在与现有受支持的控件一起使用。
实现此目标的最佳方法是什么?如果可能的话?我的代码如下。
我正在使用 Visual Studio 2010 和 .NET 4.0
用户控制代码:
public partial class ServiceStatus : UserControl
{
public ServiceStatus()
{
IndicatorSize = new System.Drawing.Size(20, 20);
Padding = new Padding(1, 1, 1, 1);
InitializeComponent();
}
public ServiceControllerStatus GetStatus()
{
using (var service = new ServiceController("MyService"))
{
return service.Status;
}
}
private void getStatusInfo(out string statusText, out Color indicatorColor)
{
try
{
ServiceControllerStatus status = GetStatus();
switch (status)
{
case ServiceControllerStatus.ContinuePending:
statusText = Properties.Resources.SERVICE_CONTINUE_PENDING;
indicatorColor = Color.Yellow;
break;
case ServiceControllerStatus.Paused:
statusText = Properties.Resources.SERVICE_PAUSED;
indicatorColor = Color.Yellow;
break;
case ServiceControllerStatus.PausePending:
statusText = Properties.Resources.SERVICE_PAUSE_PENDING;
indicatorColor = Color.Yellow;
break;
case ServiceControllerStatus.Running:
statusText = Properties.Resources.SERVICE_RUNNING;
indicatorColor = Color.Green;
break;
case ServiceControllerStatus.StartPending:
statusText = Properties.Resources.SERVICE_START_PENDING;
indicatorColor = Color.Yellow;
break;
case ServiceControllerStatus.Stopped:
statusText = Properties.Resources.SERVICE_STOPPED;
indicatorColor = Color.Red;
break;
case ServiceControllerStatus.StopPending:
statusText = Properties.Resources.SERVICE_STOP_PENDING;
indicatorColor = Color.Yellow;
break;
default:
statusText = default(String);
indicatorColor = default(Color);
break;
}
}
catch
{
statusText = Properties.Resources.SERVICE_CANNOT_CONNECT;
indicatorColor = Color.Red;
}
}
public Size IndicatorSize { get; set; }
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
string statusText;
Color indicatorColor;
getStatusInfo(out statusText, out indicatorColor);
Size textSize = TextRenderer.MeasureText(e.Graphics, statusText, Font, new Size(int.MaxValue, int.MinValue), TextFormatFlags.NoPadding);
this.Size = new Size(Padding.Left + textSize.Width + 5 + IndicatorSize.Width + Padding.Right,
Padding.Top + Math.Max(textSize.Height, IndicatorSize.Height) + Padding.Bottom);
Point textStart = new Point(Padding.Left, (this.Size.Height-textSize.Height) / 2);
Rectangle textBounds = new Rectangle(textStart, textSize) ;
Brush indicatorBrush = new SolidBrush(indicatorColor) ;
Point indicatorStart = new Point(textStart.X + textSize.Width + 5, (this.Size.Height-IndicatorSize.Height) / 2) ;
Rectangle indicatorBounds = new Rectangle(indicatorStart, IndicatorSize) ;
e.Graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
TextRenderer.DrawText(e.Graphics, statusText, Font, textBounds, ForeColor, TextFormatFlags.NoPadding);
e.Graphics.FillEllipse(indicatorBrush, indicatorBounds);
}
}
工具条控件主机代码:
[ToolStripItemDesignerAvailability(ToolStripItemDesignerAvailability.All)]
public class ToolStripServiceStatus : ToolStripControlHost
{
public ToolStripServiceStatus()
: base(new ServiceStatus())
{
}
}
我想多了。 ToolStripStatusLabel 具有文本和图像属性。
[ToolStripItemDesignerAvailability(ToolStripItemDesignerAvailability.All)]
public class ToolStripServiceStatus : ToolStripStatusLabel
{
Timer _statusRefresh = null;
public ToolStripServiceStatus() : base()
{
this.TextImageRelation = System.Windows.Forms.TextImageRelation.TextBeforeImage;
RefreshStatus();
}
void _statusRefresh_Tick(object sender, EventArgs e)
{
RefreshStatus();
}
public ServiceControllerStatus GetStatus()
{
using (var service = new ServiceController("MyService"))
{
return service.Status;
}
}
public ServiceControllerStatus GetStatusInfo(out string statusText, out Color indicatorColor)
{
ServiceControllerStatus status = default(ServiceControllerStatus);
try
{
status = GetStatus();
switch (status)
{
case ServiceControllerStatus.ContinuePending:
statusText = Properties.Resources.SERVICE_CONTINUE_PENDING;
indicatorColor = Color.Yellow;
break;
case ServiceControllerStatus.Paused:
statusText = Properties.Resources.SERVICE_PAUSED;
indicatorColor = Color.Yellow;
break;
case ServiceControllerStatus.PausePending:
statusText = Properties.Resources.SERVICE_PAUSE_PENDING;
indicatorColor = Color.Yellow;
break;
case ServiceControllerStatus.Running:
statusText = Properties.Resources.SERVICE_RUNNING;
indicatorColor = Color.Green;
break;
case ServiceControllerStatus.StartPending:
statusText = Properties.Resources.SERVICE_START_PENDING;
indicatorColor = Color.Yellow;
break;
case ServiceControllerStatus.Stopped:
statusText = Properties.Resources.SERVICE_STOPPED;
indicatorColor = Color.Red;
break;
case ServiceControllerStatus.StopPending:
statusText = Properties.Resources.SERVICE_STOP_PENDING;
indicatorColor = Color.Yellow;
break;
default:
statusText = default(String);
indicatorColor = default(Color);
break;
}
}
catch
{
statusText = Properties.Resources.SERVICE_CANNOT_CONNECT;
indicatorColor = Color.Red;
}
return status;
}
string _previousStatusText = "";
public ServiceControllerStatus RefreshStatus()
{
if (_statusRefresh == null)
{
_statusRefresh = new Timer() { Interval = 1000 };
_statusRefresh.Tick += new EventHandler(_statusRefresh_Tick);
}
_statusRefresh.Enabled = false;
string statusText;
Color indicatorColor;
ServiceControllerStatus status = GetStatusInfo(out statusText, out indicatorColor);
if (_previousStatusText != statusText)
{
Text = statusText;
Image bmp = new Bitmap(Height, Height);
using (Graphics g = Graphics.FromImage(bmp))
{
g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
g.FillEllipse(new SolidBrush(indicatorColor), new Rectangle(0, 0, Height - 1, Height - 1));
}
this.Image = bmp;
}
_statusRefresh.Enabled = (status != ServiceControllerStatus.Stopped && status != ServiceControllerStatus.Running && status != ServiceControllerStatus.Paused);
return status;
}
}
我创建了一个自定义用户控件,它将显示文本和一个指示灯来显示我们服务的当前 运行 状态,如下表所示。它在窗体上工作得很好,但我想把它放在 StatusStrip 控件上。我创建了一个派生自 ToolStripControlHost 的 class 以启用对 StatusStrip 上我的控件的支持,但它根本不呈现。控件的宽度为零,并且在 IDE 中打开时窗体会闪烁。
我查看了 ToolStripRendering class,但在我看来,它旨在与现有受支持的控件一起使用。
实现此目标的最佳方法是什么?如果可能的话?我的代码如下。
我正在使用 Visual Studio 2010 和 .NET 4.0
用户控制代码:
public partial class ServiceStatus : UserControl
{
public ServiceStatus()
{
IndicatorSize = new System.Drawing.Size(20, 20);
Padding = new Padding(1, 1, 1, 1);
InitializeComponent();
}
public ServiceControllerStatus GetStatus()
{
using (var service = new ServiceController("MyService"))
{
return service.Status;
}
}
private void getStatusInfo(out string statusText, out Color indicatorColor)
{
try
{
ServiceControllerStatus status = GetStatus();
switch (status)
{
case ServiceControllerStatus.ContinuePending:
statusText = Properties.Resources.SERVICE_CONTINUE_PENDING;
indicatorColor = Color.Yellow;
break;
case ServiceControllerStatus.Paused:
statusText = Properties.Resources.SERVICE_PAUSED;
indicatorColor = Color.Yellow;
break;
case ServiceControllerStatus.PausePending:
statusText = Properties.Resources.SERVICE_PAUSE_PENDING;
indicatorColor = Color.Yellow;
break;
case ServiceControllerStatus.Running:
statusText = Properties.Resources.SERVICE_RUNNING;
indicatorColor = Color.Green;
break;
case ServiceControllerStatus.StartPending:
statusText = Properties.Resources.SERVICE_START_PENDING;
indicatorColor = Color.Yellow;
break;
case ServiceControllerStatus.Stopped:
statusText = Properties.Resources.SERVICE_STOPPED;
indicatorColor = Color.Red;
break;
case ServiceControllerStatus.StopPending:
statusText = Properties.Resources.SERVICE_STOP_PENDING;
indicatorColor = Color.Yellow;
break;
default:
statusText = default(String);
indicatorColor = default(Color);
break;
}
}
catch
{
statusText = Properties.Resources.SERVICE_CANNOT_CONNECT;
indicatorColor = Color.Red;
}
}
public Size IndicatorSize { get; set; }
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
string statusText;
Color indicatorColor;
getStatusInfo(out statusText, out indicatorColor);
Size textSize = TextRenderer.MeasureText(e.Graphics, statusText, Font, new Size(int.MaxValue, int.MinValue), TextFormatFlags.NoPadding);
this.Size = new Size(Padding.Left + textSize.Width + 5 + IndicatorSize.Width + Padding.Right,
Padding.Top + Math.Max(textSize.Height, IndicatorSize.Height) + Padding.Bottom);
Point textStart = new Point(Padding.Left, (this.Size.Height-textSize.Height) / 2);
Rectangle textBounds = new Rectangle(textStart, textSize) ;
Brush indicatorBrush = new SolidBrush(indicatorColor) ;
Point indicatorStart = new Point(textStart.X + textSize.Width + 5, (this.Size.Height-IndicatorSize.Height) / 2) ;
Rectangle indicatorBounds = new Rectangle(indicatorStart, IndicatorSize) ;
e.Graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
TextRenderer.DrawText(e.Graphics, statusText, Font, textBounds, ForeColor, TextFormatFlags.NoPadding);
e.Graphics.FillEllipse(indicatorBrush, indicatorBounds);
}
}
工具条控件主机代码:
[ToolStripItemDesignerAvailability(ToolStripItemDesignerAvailability.All)]
public class ToolStripServiceStatus : ToolStripControlHost
{
public ToolStripServiceStatus()
: base(new ServiceStatus())
{
}
}
我想多了。 ToolStripStatusLabel 具有文本和图像属性。
[ToolStripItemDesignerAvailability(ToolStripItemDesignerAvailability.All)]
public class ToolStripServiceStatus : ToolStripStatusLabel
{
Timer _statusRefresh = null;
public ToolStripServiceStatus() : base()
{
this.TextImageRelation = System.Windows.Forms.TextImageRelation.TextBeforeImage;
RefreshStatus();
}
void _statusRefresh_Tick(object sender, EventArgs e)
{
RefreshStatus();
}
public ServiceControllerStatus GetStatus()
{
using (var service = new ServiceController("MyService"))
{
return service.Status;
}
}
public ServiceControllerStatus GetStatusInfo(out string statusText, out Color indicatorColor)
{
ServiceControllerStatus status = default(ServiceControllerStatus);
try
{
status = GetStatus();
switch (status)
{
case ServiceControllerStatus.ContinuePending:
statusText = Properties.Resources.SERVICE_CONTINUE_PENDING;
indicatorColor = Color.Yellow;
break;
case ServiceControllerStatus.Paused:
statusText = Properties.Resources.SERVICE_PAUSED;
indicatorColor = Color.Yellow;
break;
case ServiceControllerStatus.PausePending:
statusText = Properties.Resources.SERVICE_PAUSE_PENDING;
indicatorColor = Color.Yellow;
break;
case ServiceControllerStatus.Running:
statusText = Properties.Resources.SERVICE_RUNNING;
indicatorColor = Color.Green;
break;
case ServiceControllerStatus.StartPending:
statusText = Properties.Resources.SERVICE_START_PENDING;
indicatorColor = Color.Yellow;
break;
case ServiceControllerStatus.Stopped:
statusText = Properties.Resources.SERVICE_STOPPED;
indicatorColor = Color.Red;
break;
case ServiceControllerStatus.StopPending:
statusText = Properties.Resources.SERVICE_STOP_PENDING;
indicatorColor = Color.Yellow;
break;
default:
statusText = default(String);
indicatorColor = default(Color);
break;
}
}
catch
{
statusText = Properties.Resources.SERVICE_CANNOT_CONNECT;
indicatorColor = Color.Red;
}
return status;
}
string _previousStatusText = "";
public ServiceControllerStatus RefreshStatus()
{
if (_statusRefresh == null)
{
_statusRefresh = new Timer() { Interval = 1000 };
_statusRefresh.Tick += new EventHandler(_statusRefresh_Tick);
}
_statusRefresh.Enabled = false;
string statusText;
Color indicatorColor;
ServiceControllerStatus status = GetStatusInfo(out statusText, out indicatorColor);
if (_previousStatusText != statusText)
{
Text = statusText;
Image bmp = new Bitmap(Height, Height);
using (Graphics g = Graphics.FromImage(bmp))
{
g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
g.FillEllipse(new SolidBrush(indicatorColor), new Rectangle(0, 0, Height - 1, Height - 1));
}
this.Image = bmp;
}
_statusRefresh.Enabled = (status != ServiceControllerStatus.Stopped && status != ServiceControllerStatus.Running && status != ServiceControllerStatus.Paused);
return status;
}
}