0

I am trying to use (and this may be my problem already) e.Graphics.CopyFromScreen() in the OnPaint() method of my control to prepare a background onto which I can draw the content of the control. The goal is a tool-tip with rounded corners and other specific features to replace the default Windows tool tip.

Ideally the tool tip could be antialiased and blended into the backdrop, however at a pinch I could tolerate an aliased boundary. This may also be necessary as the control will often be covering a control with an OpenGL overlay and the whole blending procedure may end up a nightmare.

I have created a custom user control, a persistent instance of which belonds to my applications's main form, overriding the OnPaint and OnPaintBackground methods. The application of transparency however is challenging. As I understand, the graphics object passed to the paint method starts with a copy of the current VisibleClipBounds, where generally the first move is to clear the control with a solid colour and start drawing the main features. My first thought was to bypass the fill and start drawing on the captured background. For the first redraw this works fine, but subsequent redraws keep the previous content instead of re-capturing the backdrop. I hoped that CopyFromScreen would specifically eliminate the currently drawing control from its capture so as to start from a clean base but this is not the case, it captures the rectangle of the new location including the image of the previous location if it is in the bounds.

Other solutions and permutations thereof such as

SetStyle(ControlStyles.SupportsTransparentBackColor, True)

Me.BackColor = Color.Transparent

e.Graphics.Clear(Color.FromArgb(0,0,0,0))

have to-date yielded no appropriate results.

I started with a transparent form using the transparent key colour. This worked with aliasing but using a form as a tool tip seemed excessive and caused annoying artifacts (some of which could be overcome) such as the temporary presence of the taskbar button, focus loss of underlying form with subsequent visual feedback in the host form's title bar colour. The control is much lighter weight but I am struggling to make it work even as well as the form.

At this point I simply ask how to achieve the desired result and whether CopyFromScreen is a part of that solution.

John Arlen
  • 6,539
  • 2
  • 33
  • 42
J Collins
  • 2,106
  • 1
  • 23
  • 30

2 Answers2

2

That's a lot of text to read - but addressing transparency to achieve a custom-shaped form/control... Control.Region can do the same thing:

[DllImport("Gdi32.dll", EntryPoint = "CreateRoundRectRgn")]
private static extern IntPtr CreateRoundRectRgn
(
    int nLeftRect, // x-coordinate of upper-left corner
    int nTopRect, // y-coordinate of upper-left corner
    int nRightRect, // x-coordinate of lower-right corner
    int nBottomRect, // y-coordinate of lower-right corner
    int nWidthEllipse, // height of ellipse
    int nHeightEllipse // width of ellipse
    );

private void CreateRegion()
{
    this.Region = System.Drawing.Region.FromHrgn(CreateRoundRectRgn(0, 0, Width, Height, 40, 40));
}
John Arlen
  • 6,539
  • 2
  • 33
  • 42
  • While I might be only a few breaths away from getting into semi-transparency and its implementation in a new question, that is an excellent solution. I could nitpick that it isn't antialiased, but performance is perfect even over the OpenGL areas. – J Collins Jun 26 '12 at 20:24
0

If your control is set as a top-level window and you're running it on Windows 7 or 8, check into DwmEnableBlurBehindWindow. In the parameter structure, I set enable to true and I create a region 1x1 pixels for the blur. With BackColor and TransparencyKey set to Black, this gives me a entirely transparent window (complete with mouse pass-through) that I can paint 32-bit images to with full alpha transparency (using Graphics.FromHwnd). A bonus to this method is that if the window moves or the background changes, Windows DWM does all the work--I don't have to update a thing.

dynamichael
  • 807
  • 9
  • 9