簡體   English   中英

在繪制另一個字母之前,如何清除圖形?

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

FindBestFitFontTakeScreenShot方法保持不變。

將字體繪制到其他位圖。 透明背景(或任何不會反轉的背景,請參見下文-可能是黑色)。

(現在,您還可以使用其他彩色陰影來繪制它,以減輕在相似彩色背景上的繪制-但是下面的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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM