[英]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.