Before I begin, I'd like to say that I agree with Xaero on his point. It seems like your intended goal would benefit from the ErrorProvider class.
That said, you can invert the contents of a graphics area by using BitBlt via P/Invoke. Here is a function that can do it for you, although with no optimizations. I'll leave that part up to you. This function uses raster operations to invert the target area. A XOR with a white source onto the destination results in the colors at the destination being inverted (by logical value, not necessarily color-space).
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);
}
}
In the class that contains this utility function, you need to import System.Runtime.InteropServices and also the definition for BitBlt(). Also, the internals of this function are a little more succinct with a GetWhiteBitmap() helper method.
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;
}
This isn't true color-conversion inversion of the colors on the graphics surface- but this is pretty much analogous to how highlights were done in the old win32 days. To test this, I hacked up a default WinForms app and added the following code, which handles double-click, paint, and has a member variable for alternate state.
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);
}
}