Contrôles transparents Win32 sur toutes les versions de Windows

Je travaille sur une application Win32 GUI utilisant l’API Win32 simple (pas de MFC ou .NET). Le problème que je vois est de rendre les contrôles transparents. J’ai mis au point une méthode qui fonctionne pour la plupart des choses, dans Windows Vista +, je le fais dans le WndProc:

case WM_CTLCOLORSTATIC: { SetBkMode((HDC)wParam, TRANSPARENT); return (INT_PTR)::GetStockObject(NULL_PEN); } break; 

Dans Windows XP, je le fais dans le WndProc:

 case WM_CTLCOLORSTATIC: { HBRUSH hbr = (HBRUSH)DefWindowProc(hDlg, message, wParam, lParam); ::DeleteObject(hbr); SetBkMode((HDC)wParam, TRANSPARENT); return (LRESULT)(HBRUSH)(COLOR_WINDOW); } 

Maintenant, cela fonctionne pour la plupart des contrôles, cependant je reçois un arrière-plan transparent sur l’étiquette en haut d’un contrôle de zone de groupe qui dessine la ligne de zone de groupe dans le texte. J’ai commencé à travailler sur un cas simple pour les boîtes de groupe, mais je suis sûr que c’est un problème qui a dû être résolu avant et que je ne veux pas réinventer la roue.

Existe-t-il une méthode éprouvée pour rendre les contrôles transparents?

Merci J

Pour obtenir des contrôles transparents, vous devez savoir que:

  • Vous ne pouvez pas vraiment. Les contrôles Windows standard ne supportent tout simplement pas la peinture “transparente”.
  • Même si vous le faites correctement, le dialog va mal tourner si vous le redimensionnez.
  • Les «hacks» pour que la peinture transparente des contrôles fonctionne ont tendance à être différents si le thème est activé ou désactivé, et change entre les versions de Windows.

Habituellement, le but de rendre les contrôles “transparents” est tel qu’un skin de bitmap sous les contrôles est visible. La manière d’obtenir ce type de transparence est de créer un bitmap pour l’arrière-plan du contrôle. Ensuite, utilisez CreatePatternBrush partir du bitmap.

Ce morceau de code DialogProc implémente la méthode de skinning la plus simple possible et s’occupera ensuite de peindre à la fois l’arrière-plan de la boîte de dialog et la plupart des contrôles prenant en charge cette forme de peinture:

  // _hwnd is the dialogs handle // _hbrSkin is a pattern brush handle HWND hwndCtl; POINT pt; HDC hdc; case WM_CTLCOLORDLG: return (INT_PTR)_hbrSkin; case WM_CTLCOLORSTATIC: case WM_CTLCOLORBTN: hdc = (HDC)wParam; SetBkMode(hdc,TRANSPARENT); // Ensure that "static" text doesn't use a solid fill pt.x = 0; pt.y = 0; MapWindowPoints(hwndCtl,_hwnd,&pt,1); SetBrushOrgEx(hdc,-pt.x,-pt.y,NULL); return (INT_PTR)_hbrSkin; 

Les contrôles qui se chevauchent ne s’afficheront pas correctement car on peindra son arrière-plan “transparent” sur l’autre. Vous pouvez réduire le scintillement en:

  • Ne pas autoriser le redimensionnement de la boîte de dialog.
  • définir le style WS_EX_COMPOSITED dans la boîte de dialog, mais comme le DWM Windows NT 6 ne le prend pas en charge, il est essentiellement inutile de Vista sur.
  • Définition du style WS_CLIPCHILDREN sur la boîte de dialog & ou WS_CLIPSIBLINGS: ces styles empêchent l’utilisation de zones de groupe et de contrôles d’onglet car ils reposent sur des contrôles se chevauchant.
  • sous-classer tous les contrôles, en utilisant le message WM_PRINTCLIENT pour les peindre sur un backbuffer, puis blitter le backbuffer préparé en un seul passage. Le travail acharné et tous les contrôles ne prennent pas en charge WM_PRINTCLIENT.