Comment mettre de la transparence sur un menu contextuel Windows Forms

Bonjour,

Vous  avez créé une application qui se minimise dans le systray (à côté de l’horloge de Windows) et vous ajoutez à cette application un ContextMenuStrip afin d’afficher un menu contextuel.

Vous vous dites que ce serait bien de pouvoir rendre ce menu un peu plus attirant en y ajoutant de la transparence par exemple (c’est à la mode et ça plait bien :o)).

Dans la fenêtre des propriétés du contrôle ContextMenuStrip, aucune propriété ne laisse sous-entendre que cela est possible.
Toutefois, en creusant un peu sur la MSDN, vous apercevez que la propriété Opacity existe bel et bien sur le contrôle ContextMenuStrip.
Vous vous empressez alors de la modifier, mais à votre grand désespoir, vous vous rendez compte que si votre menu contextuel contient des sous-menus, alors les sous-menus ne sont pas transparents :

image

Il faut donc le faire avec du code natif en appelant directement l’API système SetLayeredWindowAttributes.

Voici un exemple de code qui parcourt le menu et met de la transparence sur tous les sous-menus :

[

DllImport("user32.dll")]
static extern bool SetLayeredWindowAttributes(
  IntPtr hwnd,
  uint crKey,
  byte bAlpha,
  uint dwFlags);

[DllImport("user32.dll", SetLastError = true)]
private static extern int SetWindowLong(
  IntPtr hWnd,
  int nIndex,
  int dwNewLong);

[DllImport("user32.dll", SetLastError = true)]
private static extern int GetWindowLong(
  IntPtr hWnd,
  int nIndex);

private const int GWL_EXSTYLE = -20;
private const int WS_EX_LAYERED = 0x80000;
private const int LWA_ALPHA = 0x2;
double alpha = 0.7;

public Form1()
{
InitializeComponent();
}

private void Form1_Load(object sender, EventArgs e)
{
contextMenuStrip1.Opacity = alpha;
  foreach (ToolStripMenuItem subMenuItem in contextMenuStrip1.Items)
{
setSubMenuTransparency(subMenuItem);
}

}

private void setSubMenuTransparency(ToolStripMenuItem subMenuItem)
{
  if (subMenuItem.HasDropDownItems)
{
    ToolStripItem tsi = subMenuItem.DropDownItems[0];
SetWindowLong(
tsi.Owner.Handle,
GWL_EXSTYLE,
GetWindowLong(tsi.Owner.Handle, GWL_EXSTYLE) ^ WS_EX_LAYERED);

SetLayeredWindowAttributes(
tsi.Owner.Handle,
0,
(byte)(alpha * 255),
LWA_ALPHA);

    foreach(ToolStripMenuItem smi in subMenuItem.DropDownItems)
setSubMenuTransparency(smi);
}

Et voilà le résultat obtenu :

image

A bientôt,
Aurélien