[英]How can I clear the Graphics before drawing another letter?
private void timer1_Tick(object sender, EventArgs e)
{
counter--;
DrawLetter();
if (counter == 0)
{
t.Stop();
TakeScreenShot();
}
}
private void DrawLetter()
{
var letter = counter.ToString();
Graphics g = Graphics.FromHdc(GetDC(IntPtr.Zero));
float width = ((float)this.ClientRectangle.Width);
float height = ((float)this.ClientRectangle.Width);
float emSize = height;
Font font = new Font(FontFamily.GenericSansSerif, emSize, FontStyle.Regular);
font = FindBestFitFont(g, letter.ToString(), font, this.ClientRectangle.Size);
SizeF size = g.MeasureString(letter.ToString(), font);
g.DrawString(letter, font, new SolidBrush(Color.White), (width - size.Width) / 2, 0);
}
private Font FindBestFitFont(Graphics g, String text, Font font, Size proposedSize)
{
// Compute actual size, shrink if needed
while (true)
{
SizeF size = g.MeasureString(text, font);
// It fits, back out
if (size.Height <= proposedSize.Height &&
size.Width <= proposedSize.Width) { return font; }
// Try a smaller font (90% of old size)
Font oldFont = font;
font = new Font(font.Name, (float)(font.Size * .9), font.Style);
oldFont.Dispose();
}
}
void TakeScreenShot()
{
bmpScreenshot = new Bitmap(Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height, PixelFormat.Format32bppArgb);
gfxScreenshot = Graphics.FromImage(bmpScreenshot);
gfxScreenshot.CopyFromScreen(Screen.PrimaryScreen.Bounds.X, Screen.PrimaryScreen.Bounds.Y, 0, 0, Screen.PrimaryScreen.Bounds.Size, CopyPixelOperation.SourceCopy);
bmpScreenshot.Save(Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory) + @"\ScreenCaptures\newfile.png", ImageFormat.Png);
}
我能够绘制字符串,但是它是在自身之上编写的。
我该如何清除? 基本上,我希望倒数出现在屏幕上,然后截图。
现在,该号码已被另一个覆盖。
您可以执行以下操作:创建其他透明窗体,它将显示计时器值。 这将允许您删除以前的值。 此外,这将允许通过PInvoke摆脱函数调用GetDC
。
Form timerForm; // main form field
// Create and show additional transparent form before starting the timer
timerForm = new Form
{
FormBorderStyle = FormBorderStyle.None,
WindowState = FormWindowState.Maximized,
TransparencyKey = SystemColors.Control,
ShowInTaskbar = false
};
timerForm.Show();
timer.Start();
如下更改方法DrawLetter
private void DrawLetter()
{
var letter = counter.ToString();
Graphics g = timerForm.CreateGraphics();
float width = ClientRectangle.Width;
float height = ClientRectangle.Width;
float emSize = height;
using (Font font1 = new Font(FontFamily.GenericSansSerif, emSize, FontStyle.Regular))
using (Font font2 = FindBestFitFont(g, letter, font1, ClientRectangle.Size))
using (var brush = new SolidBrush(Color.White))
{
SizeF size = g.MeasureString(letter, font2);
g.Clear(SystemColors.Control);
g.DrawString(letter, font2, brush, (width - size.Width) / 2, 0);
}
}
我们必须释放所有使用过的资源,例如字体和画笔。 为此,我using
。
更改计时器滴答事件处理程序,如下所示
private void timer1_Tick(object sender, EventArgs e)
{
counter--;
DrawLetter();
if (counter == 0)
{
timer.Stop();
TakeScreenShot();
timerForm.Dispose(); // must release
}
}
FindBestFitFont
和TakeScreenShot
方法保持不变。
将字体绘制到其他位图。 透明背景(或任何不会反转的背景,请参见下文-可能是黑色)。
(现在,您还可以使用其他彩色阴影来绘制它,以减轻在相似彩色背景上的绘制-但是下面的SRCINVERT / XOR的性质也会减轻这种情况)
使用BitBlt将其复制到屏幕
使用SRCINVERT栅格操作。 (注意:颜色可能会与下面的像素进行XOR运算而不同)
现在是时候擦除了,只需使用与以前相同的内容制作相同的bitblt,由SRCINVERT引起的双重XOR效果将具有擦除效果。
然后绘制下一个字体。
注意:如果在两次通话之间更新了桌面,则所有投注均关闭。
与其尝试使用透明背景,不如在白色背景上绘制它。 这将消除字体的对比度问题,消除对动态更新的关注,并消除擦除问题。 有时您不得不承认-方法和代码不是问题,需求才是问题。 这当然取决于需求的来源等。
如果需要看起来很专业,请不要将内容放在屏幕上,而是在截取屏幕后绘制它。
如果最终使用透明窗口方法,则屏幕截图可能会错过透明窗口。 要获得它,请参见以下问题: 捕获屏幕截图,包括.NET中的半透明窗口 。 (可以由更新的.net /更新的Windows版本修复)
您需要通过使用InvalidateRect函数来擦除先前绘制的字母来使桌面上的所有窗口无效 。
请参阅以下有关DrawLetter方法的其他代码。
[DllImport("user32")]
private static extern bool InvalidateRect(IntPtr hwnd, IntPtr rect, bool bErase);
private void DrawLetter()
{
var letter = counter.ToString();
Graphics g = Graphics.FromHdc(GetDC(IntPtr.Zero));
float width = ((float)this.ClientRectangle.Width);
float height = ((float)this.ClientRectangle.Width);
float emSize = height;
Font font = new Font(FontFamily.GenericSansSerif, emSize, FontStyle.Regular);
font = FindBestFitFont(g, letter.ToString(), font, this.ClientRectangle.Size);
SizeF size = g.MeasureString(letter.ToString(), font);
// Invalidate all the windows.
InvalidateRect(IntPtr.Zero, IntPtr.Zero, true);
// Sometimes, the letter is drawn before the windows are invalidated.
// To fix that, add a small delay before drawing the letter.
System.Threading.Thread.Sleep(100);
// Finally, draw the letter.
g.DrawString(letter, font, new SolidBrush(Color.White), (width - size.Width) / 2, 0);
}
一个解决方案是:
您必须先对要显示的区域进行快照,然后再进行所有操作。 然后,在每次调用DrawString函数之前,先调用DrawImage函数绘制快照图像。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.