isilrion Posted August 31, 2003 Posted August 31, 2003 Hello. I need to display some data on top of a video, but I need the containers to be transparent (i.e: no grey box around the letters of the label control, just the letters). The BackColor=Color.Transparent solution seems to work only if the background is a still image. So far, the best thing I've managed to do (don't laugh, I know it can't be right) is to put the 'to be transparent' controls on top of a transparent form on top of the video... Not a nice solution. Any idea? Isilrion Quote
aewarnick Posted August 31, 2003 Posted August 31, 2003 Is DoubleBuffer enabled on the controls? If you DoubleBuff and still have problems, DrawString directly to the movie surface without a label. Quote C#
isilrion Posted August 31, 2003 Author Posted August 31, 2003 DoubleBuffer? 1- What is DoubleBuffer? 2- Enabled on what control? (I'm playing the video with the AudioVideoPlayback class from DirectX 9, if doubleBuffer refers to the use of a back surface and flip, I just don't know if the audioVideoPlayback uses it) 3- How do I enable it? 4- Draw directly to the video surface? Won't the next frame erase the drawing? Thanks. Isilrion. Quote
isilrion Posted August 31, 2003 Author Posted August 31, 2003 I set the DoubleBuffer in a control I inherited from UserControl. (onPaint and onPaintBackground methods overriden, and doing nothing). The control is just a black rectangle sitting in front of the video. (No transparency). Without overriding the two methods, the control shows the from background, not the video. (I need to see the video through the control). Quote
aewarnick Posted August 31, 2003 Posted August 31, 2003 Put this in the constructor of your control: this.SetStyle(ControlStyles.DoubleBuffer, true); this.SetStyle(ControlStyles.AllPaintingInWmPaint, true); this.SetStyle(ControlStyles.UserPaint, true); Yes, DoubleBuffer refers to drawing to a backsurface first. However, you don't need to handle all that jazz when you draw in OnPaint after you use the code above. The control is probably black because you forgot to put base.OnPaint(e); in OnPaint. For transparency in your control put this.SetStyle(ControlStyles.SupportsTransparentColor, true); in your constructor as well. I'm not sure if I wrote that just right. But you'll see it in the list or ControlStyles. To Paint the control transparent paint the background color with Color.FromArgb(0,0,0,0); You can also just paint directly to the video screen control with your text, overriding OnPaint and then you must always call the base.OnPaint(e); method, either before your code or after. And yes, it will erase in the next frame but will redraw because it is in OnPaint. Quote C#
isilrion Posted August 31, 2003 Author Posted August 31, 2003 Hmm. This is weird. I haven't tried painting directly on the video, but I don't think it will work. The OnPaint method of my control doesn't get called after every frame (I added a MessageBox.Show to my OnPaint and OnPaintBackground methods to see when they get called - it only shows when I force it to repaint (like covering the window with another). Even then, the painting is erratic. If I enable the doublebuffer like you did, the background gets painted of black *after* leaving the OnPaint method (my guess: backbuffer is black and it never changed color?). I've tried painting the background with the Color.Transparent and the Color.fromARGB(0,0,0,0) in my OnPaint -still all black. But, right before the OnPaint finishes, I *almost* get what I'm looking for (the 'debug' messageBox is the last instruction on my OnPaint). If I don't use the DoubleBuffer style, I almost get what I'm looking for (the same *almost*). When I hide the window (not minimize, not covering with another window, but moving the control off-screen and then moving it back in quickly), I get the desired effect on some random regions of the control. On the rest of the control, I either get the same black or grey background, or the form background, whatever is behind the form (usually a piece of the VS.NET IDE). Ah, the effect is exactly the same wether I call base.OnPaint/base.OnPaintBackground or not. BTW, how do I get the graphics object asociated with a control? I'm used to Java's '.getGraphics()'. Thanks. Quote
aewarnick Posted August 31, 2003 Posted August 31, 2003 Graphics g= control.CreateGraphics(); Are you able to post some code? Are you overriding the video controls OnPaint or the form? You should be overriding the videos. What are you trying to paint transparent? Did you set the ControlsStyles to transparent also like posted above? Quote C#
isilrion Posted September 1, 2003 Author Posted September 1, 2003 Yes, I'll post some code. I don't have it now (I'm on another computer), but I'll try to post it tomorrow. Well, I wasn't overriding the video controls OnPaint. I did, however, attach a PaintEventHandler to it, and it wasn't getting called. (can it have something to do with the fact that is DirectX/AudioVideoPlayback who is playing the video, like I said before?) The control that I'm trying to paint transparent is just a subclass of UserControl. Originaly I wanted to make a label with transparent background, now I at least want to have a way to draw text over the video. And I set my UserControls ControlStyle like you said before my last reply. Thanks again. Quote
aewarnick Posted September 1, 2003 Posted September 1, 2003 The Label does support transparent color. You should be able to set it's Background color to Color.FromArgb(0,0,0,0); and see your movie behind it. If you can't, DirectX probably has something to do with why you can't. I haven't dealt with DirectX at all yet. There may be a factor in there that I wouldn't know the least bit about. But like I said, the label should work. Quote C#
AndreRyan Posted September 1, 2003 Posted September 1, 2003 I'm reasonably sure that AudioVideoPlayback uses DirectDraw and DirectSound so putting things over the surface(in GDI/GDI+) will not show as DirectX draws straight to the Video Card memory. You could put the control to the side rather than on the video, otherwise you could try drawing over it with DirectDraw. Quote .Net allows software to be written for any version of Windows and not break like Unmanaged applications unless using Unmanaged procedures like APIs. If your program uses large amounts of memory but releases it when something else needs it, then what's the problem?
isilrion Posted September 1, 2003 Author Posted September 1, 2003 Yes, that was my guess. Now I have a couple of questions: 1-) Is there any way to play a video to GDI/GDI+? 2-) Alternatively (and possibly better), how can I use directdraw to draw over the video? I haven't managed to tell AudioVideoPlayback to draw over a DirectDraw surface, so I don't know where to paint. It draws it to Direct3D (the sample uses D3D), but not D.Draw. thanks. Quote
isilrion Posted September 1, 2003 Author Posted September 1, 2003 Ah, just in case there is a better soltion I haven't thought about. The original idea was to show a marquee on the bottom of the video, like those that appear on some movies saying 'This movie is copyrighted, bla bla bla', and from the beggining I was thinking on painting the text and not use labels, but right now, anything will do. Quote
AndreRyan Posted September 2, 2003 Posted September 2, 2003 Are you displaying the movie in a Control or on the form? If it's in a control you could just make a marquee control and stick it at the bottom of the control hosting the video. Drawing with DirectDraw requires a lot of setting up, I didn't mean draw to the surface, I ment set the target to the Control then create a DirectDraw Device and attach it to the Control as well. Then use a loop to continously draw over the video. Quote .Net allows software to be written for any version of Windows and not break like Unmanaged applications unless using Unmanaged procedures like APIs. If your program uses large amounts of memory but releases it when something else needs it, then what's the problem?
isilrion Posted September 2, 2003 Author Posted September 2, 2003 Let me see if I got you (my english isn't nearly as good as it should be). I'm playing the movie on a panel. I have no problem with playing it on a inherited control, if that's what you mean. Now, if I create a new DirectDraw device on that control, will it be the same as the one playing the video? (That's what I understood from your reply). And painting the text directly there on a while(true) kind of loop (that's also what I understood)... wouldn't that be very cpu expensive, and with a lot of flickering? (I guess I can answer that question myself after I get to my computer) And about the lot of work setting up D.Draw, I already got a marquee working on it, I just haven't been able to put it on the movie. Thanks. Isilrion Quote
aewarnick Posted September 2, 2003 Posted September 2, 2003 If you are only writing a few words, you probably won't even recognize a speed difference. Quote C#
AndreRyan Posted September 3, 2003 Posted September 3, 2003 What I ment is that if you have it in a panel, which you said you do, you could just put the text underneath it rather than over it. With DirectDraw you have a Device object, if you attach it to the Panel (SetCooperativeMode) and then use a loop to continuously redraw the text it will go over everything there. It will not be the same device used by AudioVideoPlayback but it will draw over AudioVideoPlayback. Most DirectX programs use a loop, all DirectX games certainly use a loop, because Windows can draw over DirectDraw and Direct3D so you need to continuously refresh the DirectDraw things. No it does not flicker if you do it properly, Event managing of DirectX objects is not very effective so loops are the best way to manage them. Quote .Net allows software to be written for any version of Windows and not break like Unmanaged applications unless using Unmanaged procedures like APIs. If your program uses large amounts of memory but releases it when something else needs it, then what's the problem?
isilrion Posted September 6, 2003 Author Posted September 6, 2003 Well, I think I did what you said, but nothing got displayed. I attached the DDraw device to the same control holding the video and filled a magenta rectangle in the while(true) loop. The rectangle never showed (running the prog w/o the video being rendered showed the rectangle). In a previous post you (Ryan) mentioned to draw 'underneath' the video. I didn't understand what you wanted to say with that, but today I was doing -another- web search, and I got to a page where a similar answer was given. I don't know exactly what they were talking about, but if that's what you meant, I think I could do some research about it. The quote is Overlay Mixer is a Leagcy filter, but it is great, because it allow yout set a color Key ( Transparent Color). Then you can Put a normal Window behind video window. If the background of your application windows is the same of colorKey you will see the video throught the window, except in the places with another colors ( drwaings, text etc on the your window). I also found in the samples something very similar to what I was looking for (a marquee, with transparent background, moving on the video), but it was using C++ & DirectShow. Should I search the DirectX threads for a way to use the [unmagaged] DirectShow on my app? thnx again. Quote
DJANGO Posted October 3, 2003 Posted October 3, 2003 (edited) I've got a similar problem and found a solution that should work. Here a sample in C#: using System; using System.Collections; using System.ComponentModel; using System.Drawing; using System.Data; using System.Windows.Forms; namespace xxx { public class CustomControl1 : System.Windows.Forms.Control { /// <summary> /// Erforderliche Designervariable. /// </summary> private System.ComponentModel.Container components = null; public CustomControl1() { InitializeComponent(); } protected override void Dispose( bool disposing ) { if( disposing ) { if( components != null ) components.Dispose(); } base.Dispose( disposing ); } #region Vom Komponenten-Designer generierter Code /// <summary> /// Erforderliche Methode für die Designerunterstützung. /// Der Inhalt der Methode darf nicht mit dem Code-Editor geändert werden. /// </summary> private void InitializeComponent() { components = new System.ComponentModel.Container(); } #endregion protected override void OnPaint(PaintEventArgs pe) { base.OnPaint(pe); } protected override void OnPaintBackground(PaintEventArgs pevent) { // do nothing } protected override CreateParams CreateParams { get { CreateParams cp = base.CreateParams; cp.ExStyle |= 0x20; return cp; } } protected override void OnMove(EventArgs e) { RecreateHandle(); } Unfortunately it doesn't work with doublebuffering. But maybe somebody knows how to do this because I want to reduce flickering. Edited October 3, 2003 by DJANGO Quote
isilrion Posted October 4, 2003 Author Posted October 4, 2003 Hmm... that might work. Still trying to make it work, though (nothing is getting painted, but I just copied/pasted that, I'll take a deeper look at the code - it seems that the video is erasing it). However, the transparency effect seems to be better than one achieved with the ControlStyles.SupportsTransparentBackColor. Thanks, I'll try to make it work, I'll let you know if it worked. What style is 0x20? Quote
Nick5454 Posted November 10, 2003 Posted November 10, 2003 Flickering override the paint event and dont call the base. The base resets the image. of course using buffered surfaces then flipping the primary surface would avoid that but thats beyond your ? Quote
isilrion Posted November 11, 2003 Author Posted November 11, 2003 No, I tried that. It is not my own control who is earsing itself in the paint method. It is the parent control who does. I can't do the double buffering, because I don't have access to the parent control surface. In fact, I think I started this thread for my own ignorance (I saw what I think now could possibly be a bug: When I hide the window (not minimize, not covering with another window, but moving the control off-screen and then moving it back in quickly), I get the desired effect on some random regions of the control. On the rest of the control, I either get the same black or grey background, or the form background, whatever is behind the form (usually a piece of the VS.NET IDE). and I was trying to reproduce it as it was nearly the desired effect) The 0x20 style was actually the answer to my question - though not the solution to my problem. If the parent paints in its 'onpaint' event, it does exactly what I what it to do. In my case, though, DirectX handles the painting and my app never knows about it. I guess I'll have to keep digging on how to use DirectShow's Overlay Mixer from C#, but that should go in the DirectX section. If any of you have done that/have any ide about how to do it, please let me know! (wrappers, code, etc). If not - it is not urgent now, i'll keep exploring, and I'll post here if and when I solve it. Thanks for the help. I learned a lot in this thread. Quote
Nick5454 Posted November 12, 2003 Posted November 12, 2003 Can I understand what you mean by that You say you move it over then back but then say if I hide the window. I dont understand. You mean dragging a control by the mouse or programmatically. Do you mean hide with the method or maybe I just dont get it. This is interesting and if I understand it more I can help. if possible a sample app so I can physically see the issue or a code sample would be nice. nick Quote
isilrion Posted November 12, 2003 Author Posted November 12, 2003 Sorry, nick, my fault. My english is not as good as it should. I didn't express myself well enough. I have (had) the window playing the video, with the 'transparent' controls on it - only they weren't transparent at all. (by transparent I mean, with the transparent styles set, and doing nothing but painting a line on my onpaint). Then I moved the window out of the screen, and moved it back in (with the mouse, manually, dragging it), and surprise! the control was transparent now. I tried that on another computer, and it didn't become transparent. A weird bug in my computer, I guess. Let me dig up some code - if I find wich N in 'ApplicationN' is the one, I'll post it. Quote
isilrion Posted November 12, 2003 Author Posted November 12, 2003 Code I didn't find my old code, but I managed to reproduce it... it has the same effect now: This is the transparent control (I want it to look like just a diagonal static line, and I want the rest to be invisible) class Transpanel : UserControl { public Transpanel():base() { this.SetStyle(ControlStyles.SupportsTransparentBackColor,true); this.SetStyle(ControlStyles.UserPaint,true); this.SetStyle(ControlStyles.AllPaintingInWmPaint,true); this.BackColor=Color.Transparent; } protected override void OnPaint(PaintEventArgs e) { e.Graphics.DrawLine(Pens.Red,0,0,this.Width,this.Height); } protected override void OnPaintBackground(PaintEventArgs e) { //Do nothing } } This works with static background, or when the background is updated on the 'onpaint'. Usually that's how it happens - but in my case, I'm calling it from: public class Form1 : System.Windows.Forms.Form { private UserControl panel1; private System.ComponentModel.Container components = null; public Form1() { InitializeComponent(); this.panel1.BackColor=Color.Transparent; Video v = new Video("c:\\videos\\prueba7.avi"); v.Owner=this; v.Play(); } protected override void Dispose( bool disposing ) { if( disposing ) { if (components != null) { components.Dispose(); } } base.Dispose( disposing ); } #region Windows Form Designer generated code /// <summary> /// Required method for Designer support - do not modify /// the contents of this method with the code editor. /// </summary> private void InitializeComponent() { this.panel1 = new Transpanel(); this.SuspendLayout(); // // panel1 // this.panel1.Location = new System.Drawing.Point(48, 32); this.panel1.Name = "panel1"; this.panel1.TabIndex = 0; this.panel1.Height=20; // // Form1 // this.AutoScaleBaseSize = new System.Drawing.Size(5, 13); this.ClientSize = new System.Drawing.Size(292, 273); this.Controls.AddRange(new System.Windows.Forms.Control[] { this.panel1}); this.Name = "Form1"; this.Text = "Form1"; this.ResumeLayout(false); } #endregion [sTAThread] static void Main() { Application.Run(new Form1()); } } I run this, and I don't get the control transparent (red line on a grey box on a moving video), wich has a lot of sense. I move it out of the screen and back in (mouse drag and drop) and it becomes transparent (I see the red line on top of the moving video) I haven't been able to reproduce it on another computer, but that's the effect I was looking for. I'm sure now, however, that it was a bug (but if it happened as a bug, perhaps there is a way to make it happen for real) Sorry for posting the whole code. I just wanted to make sure no one reading this would miss anything. Isilrion. Quote
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.