Question HUD and Form opacity

raff89

New member
Joined
Nov 2, 2012
Messages
2
Programming Experience
5-10
I'm trying to create a HUD using Windows Forms, C# and VisualStudio 2010, with Windows 7 64-bit. My HUD is just a set of semi-transparent boxes that must provide additional information to the window they are attached to. The problem is that I cannot make my hud element semi-transparent when it is inside a parent form. My hud element is a box that inherits from the Form class. It's nothing but a borderless form (BorderStyle is set to "None", 100% opacity) with some colored labels inside, no code was added when creating it. So, I have a main form class called Form1 and another form class called HUDBox which is the hud element I want to display inside Form1. Both inherit from the Form class.
If I set HUDBox object's opacity to anything less then 100%, the HUDBox object just won't display inside Form1 object. I also tried using TransparencyKey, SetWindowLong and SetLayeredWindowAttributes via PInvoke but it makes everything transparent, not just the HUDBox object. Here is the code:

Program.cs:
C#:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Text;

namespace MyHUD
{
    public static class Program
    {
        public static Form1 mainForm;

        [STAThread]
        static void Main()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            mainForm = new Form1();
            HUD psHUD = new HUD();
            Application.Run(mainForm);
        }
    }
}
HUD.cs
C#:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
using System.Diagnostics;
using System.Drawing;

namespace MyHUD
{

    class HUD
    {
        private static int HOW_MANY_HUDBOXES = 4;

        [DllImport("user32.dll", SetLastError = true)]
        static extern IntPtr SetParent(IntPtr hWndChild, IntPtr hWndNewParent);

        private List<HUDBox> hudBoxes = new List<HUDBox>(HOW_MANY_HUDBOXES);

        public HUD()
        {
            initHudBoxes();
        }

        private void initHudBoxes()
        {
            for (int hb = 0; hb < HOW_MANY_HUDBOXES; hb++)
            {
                HUDBox newHudBox = new HUDBox();
                hudBoxes.Add(newHudBox);
                SetParent(newHudBox.Handle, Program.mainForm.Handle);
                newHudBox.Show();
            }
        }

    }
}
Code for HUDBox.cs and Form1.cs are not relevant as they are simple auto-generated Forms. This program adds 4 copies of my hud element inside the main form. My Form1 class is just for testing, it will be replaced by a real application's window in the future.
Opacity works fine for my hud boxes when I don't use the SetParent function, because they are not set as Form1's children.
How can I make those hud boxes semi-transparent inside Form1 so that you can see the Form1 background behind them?
 
Last edited:

JohnH

C# Forum Moderator
Staff member
Joined
Apr 23, 2011
Messages
815
Location
Norway
Programming Experience
10+
SetParent is equivalent of setting the forms TopLevel property to False and parenting it just like any control (set Parent property or adding it to a Controls collection), you don't need the SetParent function for that.
Opacity property can only be used for toplevel forms.
As a control you can set BackColor property to a semi-transparent color to make it see-through, but you must also first set style ControlStyles.SupportsTransparentBackColor in its constructor.
The semi-transparent color is created by specifying the alpha component of the color, for example using Color.FromArgb method.

If you're only using this HUD as a control you should design it as a UserControl rather than a Form.
If you want the label controls in HUD to be semi-transparent as well you must set each BackColor to a semi-transparent color.
Both UserControl class and Label class has SupportsTransparentBackColor style set by default.
 

raff89

New member
Joined
Nov 2, 2012
Messages
2
Programming Experience
5-10
Thank you for the suggestions, but it still doesn't work as I need. Here are the code changes according to your suggestions:

HUD.cs:
C#:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
using System.Diagnostics;
using System.Drawing;

namespace MyHUD
{

    class HUD
    {
        private static int HOW_MANY_HUDBOXES = 4;

        [DllImport("user32.dll", SetLastError = true)]
        static extern IntPtr SetParent(IntPtr hWndChild, IntPtr hWndNewParent);

        private List<HUDBox> hudBoxes = new List<HUDBox>(HOW_MANY_HUDBOXES);

        public HUD()
        {
            initHudBoxes();
        }

        private void initHudBoxes()
        {
            for (int hb = 0; hb < HOW_MANY_HUDBOXES; hb++)
            {
                HUDBox newHudBox = new HUDBox();
                hudBoxes.Add(newHudBox);
                //SetParent(newHudBox.Handle, Program.mainForm.Handle);
                newHudBox.Show();
            }
            [B]UserControl1 control = new UserControl1();
            SetParent(control.Handle, Program.mainForm.Handle);
            control.Show();[/B]
        }

    }
}
Then I created a new UserControl named UserControl1.cs:
C#:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace MyHUD
{
    public partial class UserControl1 : UserControl
    {
        public UserControl1()
        {
            InitializeComponent();
            SetStyle(ControlStyles.SupportsTransparentBackColor, true);
            this.BackColor = Color.FromArgb(127, 0, 0, 255);
        }

        private void UserControl1_Load(object sender, EventArgs e)
        {

        }
    }
}
I've manually added a UserControl1 to Form1 using VisualStudio, and it shows fine with correct opacity, but then I added another UserControl1 via SetParent and the transparency doesn't work.
hud1.png


SetParent is equivalent of setting the forms TopLevel property to False and parenting it just like any control (set Parent property or adding it to a Controls collection), you don't need the SetParent function for that.
Opacity property can only be used for toplevel forms.
In my case SetParent allowed me to insert my HUDBox forms inside another window, so that if I dragged them, they would stay inside that window. Everyting works fine using SetParent except the transparency issue. This HUD will be applied to other application's windows that I cannot edit via code or editor, so I guess I need the SetParent function for putting my stuff inside it. Is there another way? I've also tried to use combinations of the following functions but nothing worked, the transparency applied to the whole window instad of just the hud elements inside it:

C#:
        [DllImport("user32.dll")]
        static extern int SetWindowLong(IntPtr hWnd, int nIndex, int dwNewLong);
        [DllImport("user32.dll")]
        static extern bool SetLayeredWindowAttributes(IntPtr hwnd, uint crKey, byte bAlpha, uint dwFlags);
        [DllImport("user32.dll", SetLastError=true)]
        static extern int GetWindowLong(IntPtr hWnd, int nIndex);

        public const int GWL_EXSTYLE = -20;
        public const int WS_EX_LAYERED = 0x80000;
        public const int LWA_ALPHA = 0x2;
        public const int LWA_COLORKEY = 0x1;

        //set the window style to alpha appearance
        private void setWindowOpacity(IntPtr handle, byte opacity)
        {
            SetLayeredWindowAttributes(handle, 0, opacity, LWA_ALPHA);
        }

        private void setWindowLayered(IntPtr handle)
        {
            SetWindowLong(handle, GWL_EXSTYLE, GetWindowLong(handle, GWL_EXSTYLE) ^ WS_EX_LAYERED);
        }
 
Last edited:

JohnH

C# Forum Moderator
Staff member
Joined
Apr 23, 2011
Messages
815
Location
Norway
Programming Experience
10+
This HUD will be applied to other application's windows that I cannot edit via code or editor
I didn't read that in your first post. My advice is not relevant for that, except for the fact that you can't use Opacity property with SetParent.
 
Top Bottom