如何用C#实现跟随鼠标移动的稳定屏幕绘制字符串?
解决C#绘制跟随鼠标移动的字符串时的重复绘制与消失问题
我尝试用C#在屏幕上绘制跟随鼠标光标移动的字符串,字符串内容和位置随鼠标移动变化。现在遇到的问题是:鼠标移动时,字符串会在多个位置重复绘制,而且会在不到1秒内明显消失。想知道有没有方法实现稳定的绘制效果?目标效果是类似跟随鼠标的悬浮提示,字符串稳定显示且仅在当前鼠标位置更新。
用户提供的部分代码:
System.Drawing.Point drawPoint = new System.Drawing.Point(mouse_click_x, mouse_click_y); Graphics g = Graphics.FromHdc(desktopPtr); g.DrawString(oState1.SmartTagText(oPath), drawFont, drawBrush, drawPoint);
问题根源
直接通过桌面HDC绘制的内容属于临时绘制,系统刷新桌面(比如窗口移动、屏幕重绘)时就会被清除;而且鼠标移动时每次绘制都不清理之前的内容,导致重复残留。
稳定实现的两种方案
方案1:使用无边框透明窗体承载文本(推荐)
这是最可靠的方式,用一个始终在最顶层的透明窗体显示文本,跟随鼠标移动:
- 创建透明提示窗体:
public class TextTooltipForm : Form { public TextTooltipForm() { FormBorderStyle = FormBorderStyle.None; ShowInTaskbar = false; TopMost = true; BackColor = Color.Magenta; // 用特殊颜色作为透明键 TransparencyKey = Color.Magenta; DoubleBuffered = true; // 消除闪烁 } public void UpdateTextAndPosition(string text, Point mousePos) { Text = text; // 适配文本大小调整窗体尺寸 using (var g = CreateGraphics()) { SizeF textSize = g.MeasureString(text, Font); Size = new Size((int)textSize.Width + 8, (int)textSize.Height + 4); } // 让文本在鼠标右下方显示,避免遮挡光标 Location = new Point(mousePos.X + 10, mousePos.Y + 10); if (!Visible) Show(); } } - 在鼠标移动事件中更新窗体:
private TextTooltipForm _tooltipForm; private void OnMouseMove(object sender, MouseEventArgs e) { _tooltipForm ??= new TextTooltipForm(); string displayText = oState1.SmartTagText(oPath); _tooltipForm.UpdateTextAndPosition(displayText, e.Location); }
方案2:Hook桌面重绘,持续刷新绘制内容
如果不想用窗体,可通过定时刷新或监听桌面重绘事件,每次重新绘制文本(但易闪烁):
- 定时刷新实现:
private Timer _drawTimer; private Rectangle _lastDrawRect = Rectangle.Empty; private void InitializeDrawing() { _drawTimer = new Timer { Interval = 16 }; // 60帧/秒 _drawTimer.Tick += (s, e) => RedrawText(); _drawTimer.Start(); } private void RedrawText() { Point mousePos = Cursor.Position; IntPtr desktopDC = GetDC(IntPtr.Zero); using (Graphics g = Graphics.FromHdc(desktopDC)) { // 清除上一次绘制的区域 if (_lastDrawRect != Rectangle.Empty) { g.FillRectangle(new SolidBrush(SystemColors.Desktop), _lastDrawRect); } // 绘制新文本 string text = oState1.SmartTagText(oPath); SizeF textSize = g.MeasureString(text, drawFont); _lastDrawRect = new Rectangle(mousePos.X, mousePos.Y, (int)textSize.Width, (int)textSize.Height); g.DrawString(text, drawFont, drawBrush, mousePos); } ReleaseDC(IntPtr.Zero, desktopDC); } // 引入Win32 API [DllImport("user32.dll")] private static extern IntPtr GetDC(IntPtr hWnd); [DllImport("user32.dll")] private static extern int ReleaseDC(IntPtr hWnd, IntPtr hDC);
内容的提问来源于stack exchange,提问作者Sameh_Saady
相关产品推荐
相关产品推荐

