2009-11-17 41 views
0

我做了一個使用OnPaint和base.OnPaint的控件。 現在我想要在某些條件下將所有顏色都顛倒過來。但我該怎麼做?我知道如何反轉圖像,但我如何處理圖形對象?在控件上反轉顏色

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

    if(Condition) 
    InvertColors(e); 
} 
+1

這裏沒有問題。 – Lazarus

+0

出於興趣,你爲什麼想要這樣做?也許有更好的解決方案。 –

+0

對不起。但現在是一個問題 – magol

回答

2

在我開始之前,我想說,我有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); 
    } 
} 
1

這是不是直接回答你的問題,但一個可能的替代這是一個有點清潔,在我看來,對符合標準的Windows比反相控制的顏色有點接近。

ErrorProvider Class

ErrorProvider Class

+0

+1的控制,正如我的回答中所述 - 我同意這樣做更好。 – meklarian

+0

感謝downvote沒有解釋...毫無意義! –