<p>I want to simulate a 'Web 2.0' Lightbox style UI technique in a <a href="http://en.wikipedia.org/wiki/Windows_Forms" rel="noreferrer">Windows Forms</a> application. That is, to draw attention to some foreground control by 'dimming' all other content in the client area of a window. </p>

<p>The obvious solution is to create a control that is simply a partially transparent rectangle that can be docked to the client area of a window and brought to the front of the Z-Order. It needs to act like a dirty pain of glass through which the other controls can still be seen (and therefore continue to paint themselves). Is this possible? </p>

<p>I've had a good hunt round and tried a few techniques myself but thus far have been unsuccessful. 
If it is not possible, what would be another way to do it?</p>

<p>See: <a href="http://www.useit.com/alertbox/application-design.html" rel="noreferrer">http://www.useit.com/alertbox/application-design.html</a> (under the Lightbox section for a screenshot to illustrate what I mean.)</p>

[{'answer_id': 73062, 'author': 'Joel Coehoorn', 'author_id': 3043, 'author_profile': 'https://Stackoverflow.com/users/3043', 'pm_score': 1, 'selected': False, 'text': "<p>The forms themselves have the property <code>Opacity</code> that would be perfect, but I don't think most of the individual controls do.  You'll have to owner-draw it.</p>\n"}, {'answer_id': 73065, 'author': 'chakrit', 'author_id': 3055, 'author_profile': 'https://Stackoverflow.com/users/3055', 'pm_score': 1, 'selected': False, 'text': '<p>The big dimming rectangle is good.</p>\n\n<p>Another way to do it would be:</p>\n\n<p>Roll your own base Form class says a <code>MyLightboxAwareForm</code> class that would listen to a <code>LightboxEvent</code> from a <code>LightboxManager</code>. Then have all your forms inherit from <code>MyLightboxAwareForm</code>.</p>\n\n<p>On calling the <code>Show</code> method on any <code>Lightbox</code>, the <code>LightboxManager</code> would broadcast a <code>LightboxShown</code> event to all <code>MyLightboxAwareForm</code> instances and making them dim themselves.</p>\n\n<p>This has the advantage that normal Win32 forms functionality will continue to work such as taskbar-flashing of the form when you click on one of its modal dialogs or the management of mouseover/mousedown events would still work normally etc.</p>\n\n<p>And if you want the rectangle dimming style, you could just put the logic in MyLightboxAwareForm</p>\n'}, {'answer_id': 73146, 'author': 'Miroslav Zadravec', 'author_id': 8239, 'author_profile': 'https://Stackoverflow.com/users/8239', 'pm_score': 0, 'selected': False, 'text': '<p>Every form has "Opacity" property. Set it to 50% (or 0.5 from code) so will be half transparent. Remove borders and show it maximized before the form you want to have focus. You can change BackColor of the form or even set background image for different effects.</p>\n'}, {'answer_id': 73191, 'author': 'Phil Wright', 'author_id': 6276, 'author_profile': 'https://Stackoverflow.com/users/6276', 'pm_score': 4, 'selected': False, 'text': '<p>Can you do this in .NET/C#? </p>\n\n<p>Yes you certainly can but it takes a little bit of effort. I would recommend the following approach. Create a top level Form that has no border or titlebar area and then give make sure it draws no client area background by setting the TransparencyKey and BackColor to the same value. So you now have a window that draws nothing...</p>\n\n<pre><code>public class DarkenArea : Form\n{\n    public DarkenArea()\n    {\n        FormBorderStyle = FormBorderStyle.None;\n        SizeGripStyle = SizeGripStyle.Hide;\n        StartPosition = FormStartPosition.Manual;\n        MaximizeBox = false;\n        MinimizeBox = false;\n        ShowInTaskbar = false;\n        BackColor = Color.Magenta;\n        TransparencyKey = Color.Magenta;\n        Opacity = 0.5f;\n    }\n}\n</code></pre>\n\n<p>Create and position this DarkenArea window over the client area of your form. Then you need to be able to show the window without it taking the focus and so you will need to platform invoke in the following way to show without it becoming active...</p>\n\n<pre><code>public void ShowWithoutActivate()\n{\n    // Show the window without activating it (i.e. do not take focus)\n    PlatformInvoke.ShowWindow(this.Handle, (short)SW_SHOWNOACTIVATE);\n}\n</code></pre>\n\n<p>You need to make it actually draw something but exclude drawing in the area of the control you want to remain highlighted. So override the OnPaint handler and draw in black/blue or whatever you want but excluding the area you want to remain bright...</p>\n\n<pre><code>protected override void OnPaint(PaintEventArgs e)\n{\n    base.OnPaint(e);\n    // Do your painting here be exclude the area you want to be brighter\n}\n</code></pre>\n\n<p>Last you need to override the WndProc to prevent the mouse interacting with the window if the user tries something crazy like clicking on the darkened area. Something like this...</p>\n\n<pre><code>protected override void WndProc(ref Message m)\n{\n    if (m.Msg == (int)WM_NCHITTEST)\n        m.Result = (IntPtr)HTTRANSPARENT;\n    else\n        base.WndProc(ref m);\n}\n</code></pre>\n\n<p>That should be enough to get the desired effect. When you are ready to reverse the effect you dispose of the DarkenArea instance and carry on.</p>\n'}, {'answer_id': 169855, 'author': 'ZeroBugBounce', 'author_id': 11314, 'author_profile': 'https://Stackoverflow.com/users/11314', 'pm_score': 3, 'selected': False, 'text': '<p>This is a really cool idea - I will probably use it, so thanks. Anyway, my solution is really simple... open a new 50% opaque form over your current one and then custom draw a background image for that form with a rectangle matching the bounds of the control you want to highlight filled in the color of the transparency key.</p>\n\n<p>In my rough sample, I called this form the \'LBform\' and the meat of it is this:</p>\n\n<pre><code>public Rectangle ControlBounds { get; set; }\nprivate void LBform_Load(object sender, EventArgs e)\n{\n    Bitmap background = new Bitmap(this.Width, this.Height);\n    Graphics g = Graphics.FromImage(background);\n    g.FillRectangle(Brushes.Fuchsia, this.ControlBounds);\n\n    g.Flush();\n\n    this.BackgroundImage = background;\n    this.Invalidate();\n}\n</code></pre>\n\n<p>Color.Fuchia is the TransparencyKey for this semi-opaque form, so you will be able to see through the rectangle drawn and interact with anything within it\'s bounds on the main form.</p>\n\n<p>In the experimental project I whipped up to try this, I used a UserControl dynamically added to the form, but you could just as easily use a control already on the form.  In the main form (the one you are obscuring) I put the relevant code into a button click:</p>\n\n<pre><code>private void button1_Click(object sender, EventArgs e)\n{\n    // setup user control:\n    UserControl1 uc1 = new UserControl1();\n    uc1.Left = (this.Width - uc1.Width) / 2;\n    uc1.Top = (this.Height - uc1.Height) / 2;\n    this.Controls.Add(uc1);\n    uc1.BringToFront();\n\n    // load the lightbox form:\n    LBform lbform = new LBform();\n    lbform.SetBounds(this.Left + 8, this.Top + 30, this.ClientRectangle.Width, this.ClientRectangle.Height);\n    lbform.ControlBounds = uc1.Bounds;\n\n    lbform.Owner = this;\n    lbform.Show();\n}\n</code></pre>\n\n<p>Really basic stuff that you can do your own way if you like, but it\'s just adding the usercontrol, then setting the lightbox form over the main form and setting the bounds property to render the full transparency in the right place.  Things like form dragging and closing the lightbox form and UserControl aren\'t handled in my quick sample.  Oh and don\'t forget to dispose the Graphics instance - I left that out too (it\'s late, I\'m really tired).</p>\n\n<p><a href="http://cid-12d219ccfc930f76.skydrive.live.com/self.aspx/Code/LightBox000.zip" rel="noreferrer">Here\'s my very did-it-in-20-minutes demo</a></p>\n'}, {'answer_id': 5757080, 'author': 'Gad', 'author_id': 25152, 'author_profile': 'https://Stackoverflow.com/users/25152', 'pm_score': 1, 'selected': False, 'text': "<p>Another solution that doesn't involve using a new Form :</p>\n\n<ul>\n<li>make a picture of your container (form / panel / whatever), </li>\n<li>change its opacity,</li>\n<li>display it in a new panel's background.</li>\n<li>Fill your container with that panel.</li>\n</ul>\n\n<p>And now the code... </p>\n\n<p>Let's say I have a UserControl called Frame to which I'll want to apply my lightbox effect:</p>\n\n<pre><code>public partial class Frame : UserControl\n{\n    private Panel shadow = new Panel();\n    private static float LIGHTBOX_OPACITY = 0.3f;\n\n    public Frame()\n    {\n        InitializeComponent(); \n        shadow.Dock = DockStyle.Fill;\n    }\n\n    public void ShowLightbox()\n    {\n        Bitmap bmp = new Bitmap(this.Width, this.Height);\n        this.pnlContainer.DrawToBitmap(bmp, new Rectangle(0, 0, this.Width, this.Height));\n        shadow.BackgroundImage = SetImgOpacity(bmp, LIGHTBOX_OPACITY );\n        this.Controls.Add(shadow);\n        shadow.BringToFront();\n    }\n\n    // http://www.geekpedia.com/code110_Set-Image-Opacity-Using-Csharp.html\n    private Image SetImgOpacity(Image imgPic, float imgOpac)\n    {\n        Bitmap bmpPic = new Bitmap(imgPic.Width, imgPic.Height);\n        Graphics gfxPic = Graphics.FromImage(bmpPic);\n        ColorMatrix cmxPic = new ColorMatrix();\n        cmxPic.Matrix33 = imgOpac;\n        ImageAttributes iaPic = new ImageAttributes();\n        iaPic.SetColorMatrix(cmxPic, ColorMatrixFlag.Default, ColorAdjustType.Bitmap);\n        gfxPic.DrawImage(imgPic, new Rectangle(0, 0, bmpPic.Width, bmpPic.Height), 0, 0, imgPic.Width, imgPic.Height, GraphicsUnit.Pixel, iaPic);\n        gfxPic.Dispose();\n        return bmpPic;\n    }\n}\n</code></pre>\n\n<p>The advantages to using this technique are :</p>\n\n<ul>\n<li>You won't have to handle all of the mouse events</li>\n<li>You won't have to manage multiple forms to communicate with the lightbox elements</li>\n<li>No overriding of WndProc</li>\n<li>You'll be cool because you'll be the only one not to use forms to achieve this effect.</li>\n</ul>\n\n<p>Drawbacks are mainly that this technique is much slower because you have to process an entire image to correct each pixel point using the ColorMatrix.</p>\n"}]
['https://Stackoverflow.com/questions/72994', 'https://Stackoverflow.com', 'https://Stackoverflow.com/users/6199/']