簡體   English   中英

反轉控件上的顏色

[英]Invert colors on a control

我做了一個使用OnPaint和base.OnPaint的控件。 現在,我希望所有顏色在特定條件下都可以反轉。 但是我該怎么做呢? 我知道如何反轉圖像,但是如何處理Graphics對象?

protected override void OnPaint(PaintEventArgs e)
{
  base.OnPaint(e);
  MyOwnPaint(e);

  if(Condition)
    InvertColors(e);
}

在開始之前,我想說我同意Xaero的觀點。 看來您的預期目標將從ErrorProvider類中受益。

也就是說,您可以通過P / Invoke使用BitBlt反轉圖形區域的內容。 盡管沒有優化,但此功能可以為您實現。 我把那部分留給你。 此功能使用柵格操作來反轉目標區域。 將白色源與目標進行XOR運算將導致目標上的顏色被反轉(通過邏輯值,不一定是色彩空間)。

private void InvertGraphicsArea(Graphics g, Rectangle r)
{
    if (r.Height <= 0) { return; }
    if (r.Width <= 0) { return; }

    using (Bitmap bmpInvert = GetWhiteBitmap(g, r))
    {
        IntPtr hdcDest = g.GetHdc();
        using (Graphics src = Graphics.FromImage(bmpInvert))
        {
            int xDest = r.Left;
            int yDest = r.Top;
            int nWidth = r.Width;
            int nHeight = r.Height;
            IntPtr hdcSrc = src.GetHdc();
            BitBlt(hdcDest, xDest, yDest, nWidth, nHeight, 
                   hdcSrc, 0, 0, (uint)CopyPixelOperation.DestinationInvert);
            src.ReleaseHdc(hdcSrc);
        }
        g.ReleaseHdc(hdcDest);
    }
}

在包含此實用程序功能的類中,您需要導入System.Runtime.InteropServices以及BitBlt()的定義。 同樣,使用GetWhiteBitmap()幫助器方法,此函數的內部更為簡潔。

using System.Runtime.InteropServices;

// ...

[DllImport("gdi32.dll", 
           EntryPoint="BitBlt", 
           CallingConvention=CallingConvention.StdCall)]
extern public static int BitBlt(
    IntPtr hdcDesc, int nXDest, int nYDest, int nWidth, int nHeight, 
    IntPtr hdcSrc, int nXSrc, int nYSrcs, uint dwRop);

private Bitmap GetWhiteBitmap(Graphics g, Rectangle r)
{
    int w = r.Width;
    int h = r.Height;

    Bitmap bmp = new Bitmap(w, h);
    using (Graphics gTmp = Graphics.FromImage(bmp))
    {
        gTmp.Clear(Color.White);
    }
    return bmp;
}

這不是圖形表面上顏色的真正顏色轉換,但是與舊win32天中的高光顯示方式非常相似。 為了測試這一點,我破解了一個默認的WinForms應用程序,並添加了以下代碼,該代碼可處理雙擊,繪制並具有用於備用狀態的成員變量。

bool m_Highlight = false;

private void Form1_DoubleClick(object sender, EventArgs e)
{
    m_Highlight = !m_Highlight;
    this.Invalidate();
}

private void Form1_Paint(object sender, PaintEventArgs e)
{
    // Note: sloppy, but just to show that everything is inverted.
    using(Font font = new Font(FontFamily.GenericSerif, 20.0f, FontStyle.Bold))
    {
        e.Graphics.DrawString("Hello World!", font, Brushes.Red, 0.0f, 0.0f);
    }

    if (m_Highlight)
    {
        InvertGraphicsArea(e.Graphics, e.ClipRectangle);
    }
}

這不是您問題的直接答案,而是一種可能的替代方法,它更干凈一些,並且我認為,與反轉控件的顏色相比,它更符合Windows標准。

ErrorProvider類

ErrorProvider類

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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