Search code examples
vb.netwinformstransparencyalpha-transparency

How Can I use Graphics.CopyFromScreen to enable alpha transparent controls?


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.


Solution

  • 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));
    }