0

I have embedded WindowsMediaPlayer in my C# (desktop) app and want to place a transparent Panel or PictureBox on top of it.

Since neither Panel or PictureBox has the TransparencyKey property, I can't use the, BackColor=TransparencyKey=Color.Magenta, approach.

I've tried setting the BackColor of the Panel to Color.Transparent. It doesn't seem to work. [Or maybe it does, but the WMP video is simply not showing through the (transparent) panel.]

The (ultimate) goal is to prevent users from directly interacting with the WMP and, ideally, to have an overlay on which "useful" info could be conveyed to the users.

Anyone managed to do something like this successfully? I'm open to most ideas on how to solve this.

EDIT:

Using the example from 'How to Make a UserControls BackColor Transparent in C#?', I have created "my own" Panel as follows:

    class TransarentPanel : Panel {

    public bool     drag = false;
    public bool     enab = false;
    private int     m_opacity = 100;

    private int     alpha;

    System.Drawing.Font         drawFont;
    System.Drawing.SolidBrush   drawBrush;
    System.Drawing.StringFormat drawFormat;

    public TransarentPanel() {
        SetStyle(ControlStyles.SupportsTransparentBackColor, true);
        SetStyle(ControlStyles.Opaque, true);
        this.BackColor = Color.Transparent;
    }

    public int Opacity {
        get {
            if (m_opacity > 100) {
                m_opacity = 100;
            } else if (m_opacity < 1) {
                m_opacity = 1;
            }
            return this.m_opacity;
        }
        set {
            this.m_opacity = value;
            if (this.Parent != null) {
                Parent.Invalidate(this.Bounds, true);
            }
        }
    }

    protected override CreateParams CreateParams {
        get {
            CreateParams cp = base.CreateParams;
            cp.ExStyle = cp.ExStyle | 0x20;
            return cp;
        }
    }

    protected override void OnPaint(PaintEventArgs e)
    {
        Graphics g = e.Graphics;
        Rectangle bounds = new Rectangle(0, 0, this.Width - 1, this.Height - 1);

        Color frmColor = this.Parent.BackColor;
        Brush bckColor = default(Brush);

        alpha = (m_opacity * 255) / 100;

        if (drag) {
            Color dragBckColor = default(Color);

            if (BackColor != Color.Transparent) {
                int Rb = BackColor.R * alpha / 255 + frmColor.R * (255 - alpha) / 255;
                int Gb = BackColor.G * alpha / 255 + frmColor.G * (255 - alpha) / 255;
                int Bb = BackColor.B * alpha / 255 + frmColor.B * (255 - alpha) / 255;
                dragBckColor = Color.FromArgb(Rb, Gb, Bb);
            } else {
                dragBckColor = frmColor;
            }

            alpha = 255;
            bckColor = new SolidBrush(Color.FromArgb(alpha, dragBckColor));
        } else {
            bckColor = new SolidBrush(Color.FromArgb(alpha, this.BackColor));
        }

        if (this.BackColor != Color.Transparent | drag) {
            g.FillRectangle(bckColor, bounds);
        }

        // Display overlay info
        {
            drawFont = new System.Drawing.Font("Arial", 24);
            drawBrush = new System.Drawing.SolidBrush(System.Drawing.Color.Black);
            drawFormat = new System.Drawing.StringFormat();

            g.DrawString("Overlay", drawFont, drawBrush, this.Location.X + 50, this.Location.Y + 30, drawFormat);

            drawFont.Dispose();
            drawBrush.Dispose();
            drawFormat.Dispose();
        }

        bckColor.Dispose();
        g.Dispose();    // Should this object be disposed of here since it was not created here?
        base.OnPaint(e);
    }

    protected override void OnBackColorChanged(EventArgs e)
    {
        if (this.Parent != null)
        {
            Parent.Invalidate(this.Bounds, true);
        }
        base.OnBackColorChanged(e);
    }

    protected override void OnParentBackColorChanged(EventArgs e)
    {
        this.Invalidate();
        base.OnParentBackColorChanged(e);
    }
}  // end class TransparentPanel

This achieves the goal of making an "invisible" Panel that overlays the WMP while allowing the WMP display to show through. However, I still need to display some info on top of (in front of) the WMP window.

I have tried to 'Draw' directly on this transparent panel, [see the code block at '// Display overlay info' in OnPaint()], but this does not show. However, if I 'Hide()' the WMP window, the writing does show (but, of course, WMP doesn't). If I make my transparent panel only cover half the screen and add a "regular" panel (with a BackgroundImage), it shows up unless any part of it overlaps the transparent panel, in which case it does not show.

I have noted comments about the Parent drawing the Panel's background. I don't understand this, but making my transparent panel's Parent be the WMP (TP.Parent = WMP;) didn't make any difference.

I am prepared to believe I'm missing something basic here, since my knowledge of Forms/Controls is rudimentary at best. Having come this close, though, I'd really like to understand what I'm missing so I can add it to my knowledge base, fix my problem here, and move on.

[And bless George Birbilis without whom I'd still be at square one! :-) ]

Community
  • 1
  • 1
  • I think you can disable controls on the WMP ti prevent users from interacting withit. When you place a transparent control (by changing opacity) you can click through it, so I doubt you will achieve your objective with a transparent control – Yaman Jan 20 '17 at 00:45
  • You can disable/hide the visible controls (and I have), but not the right-clicking on the screen that brings up a list of actions. Regardless, one of the other reasons for trying to have a transparent overlay is to allow info to be displayed on it (as supplementary data) "over" the running video. – JudgeRoyBean Jan 20 '17 at 02:47
  • you could also add a descendent class of those and override the method they use for painting themselves to not erase the background and/or not paint anything – George Birbilis Jan 20 '17 at 03:00
  • You probably need to use another top-level windows and handle all the interactions so that it appears as one form to the end user. Maybe it could works with some third party controls but not standard ones. – Phil1970 Jan 20 '17 at 03:54
  • What class /control do you use for WMP ? – Yaman Jan 20 '17 at 05:07
  • @George - descendent class of ??? (Panel/PictureBox?) – JudgeRoyBean Jan 20 '17 at 07:46
  • @Yaman - I'm not sure what you're asking. I added WMP to my project (main form) per the directions at 'https://msdn.microsoft.com/en-us/library/windows/desktop/dd564585(v=vs.85).aspx'. It appears to be a COM component, and accessing it is rather "primitive". – JudgeRoyBean Jan 20 '17 at 07:48
  • @JudgeRoyBean Just wanna check the class methods and properties. See what it can do to your case – Yaman Jan 20 '17 at 18:27
  • see http://stackoverflow.com/questions/9358500/making-a-control-transparent and use Panel as ancestor (instead of Object) – George Birbilis Jan 21 '17 at 23:11
  • @George - Thank-you. Just the ticket! This has solved the transparency problem so WMP shows through without allowing user clicks on the window. Now I'd also like to be able to display info on this panel somehow. I've tried setting the .BackgroundImage with a .png that is mostly transparent except for some opaque digits. It doesn't show up. Any chance you can help me here, too? :-) – JudgeRoyBean Jan 22 '17 at 19:55
  • I see the sample code there does call Base.OnPaint (the parent's paint method), so if you use a Panel for ancestor (instead of Object), it should be able to accept children controls. So why not add labels or whatever as children to that selectively-transparent panel and set their text? From a quick look at that code, I think it doesn't change the transparency of the children, just of the panel's background. If you want them translucent too, make Label descendents with similar painting code and use them as children at that Panel descendent – George Birbilis Jan 24 '17 at 13:26
  • @George - My "TransparentPanel" ('TP') was derived from 'Panel' (as suggested). I've tried "newCtl.Parent=TP;" using both Label and TextBox - no dice. I've tried a "regular" Panel (with an image with transparent background), also to no avail (with and without TP as Parent) - also no good. In fact, any "normal Panel doesn't even display at all if it overlaps the TP _anywhere_. And, when not overlapping TP but setting TP as Parent, it also doesn't show. Did I misunderstand your suggestion? – JudgeRoyBean Jan 25 '17 at 00:01
  • @JudgeRoyBean maybe try this one first https://msdn.microsoft.com/en-us/library/wk5b13s4(v=vs.90).aspx (and read user comments on UserControl and Transparency at http://stackoverflow.com/questions/14305950/how-to-make-a-usercontrols-backcolor-transparent-in-c/34404064) and if it doesn't work get back to the one I suggested and try drawing text at OnPaint using e.Graphics (where e is the event object). Could draw text etc. like that instead of adding child controls – George Birbilis Jan 27 '17 at 11:17

2 Answers2

0

Blockquote

In the form of loading, the background of the PictureBox1 specified as transparent, and then the PictureBox1 designated as the parent of the PictureBox2 container can be achieved in PictureBox2 transparent and transparent with the background of the PictureBox1. VB2010 environment. The code is as follows: attached to the left side of the screen is running effect, the right is the programming environment, I hope this effect you will be satisfied

    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
    PictureBox1.BackColor = Color.Transparent
    PictureBox2.Parent = PictureBox1

or gdi+

the Add Paint event

 Dim g As Graphics = Me.CreateGraphics
Liber013
  • 1
  • 3
  • I'll believe this might work if I were working with two instances of PictureBox. Unfortunately, my underlying "image producer" is an embedded COM object, so I'm not entire sure how to apply what you've suggested. – JudgeRoyBean Jan 20 '17 at 07:52
0

In the designer.cs file add this statement, this.YOURWINDOWSMEDIAPLAYER.Controls.Add(this.YOURTRANSPARENTPANEL);

Order of controls will depends on the order you follow in the designer.cs to add the child controls.

Hope this will help to resolve your issue, although it's bit late.