Plus transparent que lui tu meurs


Description

Bonjour

C'est avec un immense plaisir que je vous propose cette gestion. Il m'a fallu une semaine compête de recherche, d'essais pour obtenir ce que je voulais. Je souhaite qu'elle vous rende service ...

Tout d'abord un grand merci à SAUVEUR ( Source : CREATEUR D'UN FICHIER RESSOURCE)

Son programme (partie constitution d'une Form particularisée) a été le point de départ de ma réflexion.

"Comment adapter les contrôles courant (Frame, optionbutton, listbox, ...) de Window à une Form particularisée que j'aurais créé ?
Comment éviter ces couleurs de fond de contrôle non en harmonie avec mon fond de Form ?"

et ce sans passer par des form "fantômes" comme celle que j'avais proposé dans la série "TRANSPARENCE et MOBILITE D'UN CONTROL"

C'est finalement tout simple ... Il suffit d'utiliser la procédure "RendControlTransparent" inclus dans le programme "Pixellisation" joint

Ne me demandez pas comment fonctionne les "Régions" je ne suis pas assez calé pour répondre. Mais ça marche.

Le code ci-dessous permet de prendre en compte les cas de figure où l'utilisateur modifie l'apparence de son PC (le mettre en rose saumon par exemple) à travers les constantes "COLOR_ ..."

Dans la démo jointe, j'ai exploré 3 cas de figure :

1/ Utilisation de contrôles inclus dans une PictureBox (contrôles traditionnels ou faisant partie des composants Microsoft Form 2.0 Object library

2/ Utilisation d'une bitmap incluse dans une PictureBox

3/ Utilisation de contrôles courant Window (hors Form 2.0 object library) inclus ou pas dans un frame

Source / Exemple :


' Récapitulatif des éléments nécessaires pour une exploitation :

' 1/ API à utiliser :

Public Declare Function SetWindowRgn Lib "user32" (ByVal hwnd As Long, ByVal hRgn As Long, ByVal bRedraw As Boolean) As Long
Public Declare Function CreateRectRgn Lib "gdi32" (ByVal X1 As Long, ByVal Y1 As Long, ByVal X2 As Long, ByVal Y2 As Long) As Long
Public Declare Function CombineRgn Lib "gdi32" (ByVal hDestRgn As Long, ByVal hSrcRgn1 As Long, ByVal hSrcRgn2 As Long, ByVal nCombineMode As Long) As Long
Public Declare Function PaintRgn Lib "gdi32" (ByVal hdc As Long, ByVal hRgn As Long) As Long
Public Declare Function DeleteObject Lib "gdi32" (ByVal hObject As Long) As Long
Public Declare Function GetWindowDC Lib "user32" (ByVal hwnd As Long) As Long
Public Declare Function GetSysColor Lib "user32" (ByVal nIndex As Long) As Long

' 2/ Constantes :

'*****  Constantes Couleurs Systèmes  ***** ( Ces couleurs correspondent aux choix proposés dans la partie "Système", dans Backcolor par exemple)

Public Const COLOR_BTNFACE = 15
Public Const COLOR_BTNHIGHLIGHT = 20
Public Const COLOR_3DHILIGHT = 20
Public Const COLOR_3DHIGHLIGHT = 20
Public Const COLOR_BTNHILIGHT = 20
Public Const COLOR_BTNSHADOW = 16
Public Const COLOR_3DSHADOW = 16
Public Const COLOR_BTNTEXT = 18
Public Const COLOR_CAPTIONTEXT = 9
Public Const COLOR_GRAYTEXT = 17
Public Const COLOR_HIGHLIGHT = 13
Public Const COLOR_HIGHLIGHTTEXT = 14
Public Const COLOR_INACTIVEBORDER = 11
Public Const COLOR_INACTIVECAPTION = 3
Public Const COLOR_INACTIVECAPTIONTEXT = 19
Public Const COLOR_MENU = 4
Public Const COLOR_MENUTEXT = 7
Public Const COLOR_SCROLLBAR = 0
Public Const COLOR_WINDOW = 5
Public Const COLOR_WINDOWFRAME = 6
Public Const COLOR_WINDOWTEXT = 8
Public Const COLOR_ACTIVEBORDER = 10
Public Const COLOR_ACTIVECAPTION = 2
Public Const COLOR_ADJ_MAX = 100
Public Const COLOR_ADJ_MIN = -100 'shorts
Public Const COLOR_APPWORKSPACE = 12
Public Const COLOR_BACKGROUND = 1
Public Const COLOR_DESKTOP = 1

'*****  Modes de liaisons entre 2 régions  *****
Public Const RGN_DIFF = 4
Public Const RGN_AND = 1
Public Const RGN_COPY = 5
Public Const RGN_MAX = RGN_COPY
Public Const RGN_MIN = RGN_AND
Public Const RGN_OR = 2
Public Const RGN_XOR = 3

' 3/ Variables

Public PictRgn As Long, TempRgn As Long

Public Sub RendControlTransparent(Ecran As Form, ControlATraiter As Object, CouleurDeTransparence As Long)
    Dim x As Integer   'Position Colonne   (ATTENTION : Valeur donnée par position LEFT)
    Dim y As Integer   'Position Ligne     (ATTENTION : Valeur donnée par position TOP)
    Dim FrameDC As Long
    Dim Verifie As Long
    
    'A- Le contrôle à traiter possède t'il d'origine une handle Device Context ?
    On Error Resume Next
    
    Verifie = ControlATraiter.hdc
    If Err.Number > 0 Then
    '   A-1/ Non ! créons lui en une
        FrameDC = GetWindowDC(ControlATraiter.hwnd)
        'Un frame, un OptionButton, ... n'ont pas de ".hDC" (Handle vers DeviceContext). Il a donc fallu lui en créer un artificiellement
        '(Sauf erreur, seuls un Form, une PictureBox ou un SSTab l'ont)
    Else
    '   A-2/ Oui ! reprenons la
        FrameDC = ControlATraiter.hdc
    End If
    
    On Error GoTo 0 'fin contrôle des erreurs
    
    'B- Détermination d'une région "arbitraire" et transparente puisque vide
    
    'Les valeurs -4 et +4 (pixels) servent à délimiter la zone "Travail" . ATTENTION : left, Top, Width et Height correspondent à une gestion en "pixels.
    'Si vous utilisez une gestion en "Twips" (ScaleMode) les Left, Top, Width et Heigt dans la proc. doivent être divisé par 15

    With Ecran: PictRgn = CreateRectRgn(.Left + 4, .Top + 4, (.Width - 4), (.Height - 4)): End With
    
    'C- Gestion de la liaison Régions
    
    For y = 0 To ControlATraiter.Height '(Top)
        
        For x = 0 To ControlATraiter.Width + 45 '(LEFT)
            
            'Le RGN_XOR fonctionne avec le signe " <> "
            If GetPixel(FrameDC, x, y) <> CouleurDeTransparence Then
                If GetPixel(FrameDC, x, y) <> -1 Then ' -1 = passage sur une zone recouverte par un control (ex. Option3 recouvre une partie de PixelForm)

                    TempRgn = CreateRectRgn(x, y, x + 1, y + 1)
                    Call CombineRgn(PictRgn, TempRgn, PictRgn, RGN_XOR)
                    Call DeleteObject(TempRgn)

                End If  'GetPixel(FrameDC, x, y) <> -1

            End If  'GetPixel(FrameDC, x, y) <> CouleurDeTransparence
            
        Next    'x = 0 To ControlATraiter.Width + 45
        x = 0
     Next   'y = 0 To ControlATraiter.Height
    
    'D- Transfert du résultat sur le contrôle
    Call SetWindowRgn(ControlATraiter.hwnd, PictRgn, True)  'On redessine le contrôle
    Call DeleteObject(PictRgn)  'on a plus besoin de la région
    
End Sub

' la commande qui lance ... :  (exemple)

Public Sub Command5_Click()
    Dim resultat As Long
    
    Command5.Enabled = False
    
     DOEVENTS

    resultat = GetSysColor(COLOR_GRAYTEXT)   'récupère la couleur Window Système attribuée à la couleur " Text inactivé "
    Call RendControlTransparent(PixelForm, PixelForm.Option3, resultat)
    
    resultat = GetSysColor(COLOR_BTNFACE)   'récupère la couleur Window Système attribuée à la couleur " Sommet du bouton "
    Call RendControlTransparent(PixelForm, PixelForm.Check3, resultat)
    Call RendControlTransparent(PixelForm, PixelForm.Frame3, resultat)
    
     DOEVENTS

End Sub

Conclusion :


sur le cas 1/ Il y a un décalage de 2 pixels en hauteur et largeur généré . Je n'ai pas pu le corriger autrement qu'en corrigeant les positions des contrôles en fin de la procédure : Essai2

Sur le cas 2/ Tout d'abord il ne faut pas être pressé. Le système prend son temps. On peut voir que le décalage existe également (proc. Essai3)

Sur le cas 3/ Le fin du fin ! point n'était besoin des 2 cas précédent. La solution résidait dans le GetSysColor et dans l'ajout de la ligne supplémentaire : If GetPixel(FrameDC, x, y) <> -1. En effet, Window voit ce que l'on voit si je puis dire. La doc. SDKPlatform sur le "CombineRgn" indique bien dans le cas du RGN_XOR que toutes les zones "overlapped" ne sont pas prises en compte (Pixel de valeur Null ou -1)

CE QU'IL FAUT RETENIR :

1/ les zones qui laissent voir le fond de l'écran sont "TRANSPARENTES" ce qui veut dire que tout clic souris sur celle-ci ne provoque rien. Amusez vous à le faire sur le ComboBox par exemple. Pour avoir accès à la liste des propositions il faut cliquer sur la flèche "Noire" => Attribuez au contrôle une couleur de fond qui se rapproche le plus de votre fond d'écran ...

2/ Le prog de SAUVEUR lance la Transparence dans la proc. FORM_LOAD. Cela marche très bien car c'est la FORM elle-même qui doit être adaptée, la région de référence étant le BUREAU window. Et le processus de transparence s'effectue alors que seul le Border de la Form est constitué.

Il n'en va pas de même pour les contrôles. IL FAUT IMPERATIVEMENT QUE LE FORM SOIT TOTALEMENT CONSTITUE A L'ECRAN (VISIBLE A ...) AVANT DE LANCER LE PROCESSUS.

Il ne suffit pas de mettre Nom de la form ".show" dans un Sub Main du module principal puis d'introduire en suivant l'appel à la procédure. Cela ne marchera pas, car il ne faut pas oublier que les évènements "Interface Utilisateur" sont gérés en dernier. VB prendra note qu'il faut montrer le Form, éxécutera toutes les instructions (hors interfaces suivantes) puis reviendra sur le souhait de présenter le Form.

Une possibilité : introduire l'appel dans un form_Move avec une var.static qui empêche le rappel à chaque move du form

Dans certains cas mettre l'appel dans un Form_Activate. Cela ne marche pas tout le temps. L'essai fait avec la démo a planté. Le même essai effectué sur une de mes applic. faisant appel à WindowProc pour gérer certains messages a été positif.
Personnellement, dans mes applics j'ai pu régler le prob. parce que l'ordre a été lancé depuisl'extérieur des programmes ( via un autre prog et en fin d'ouverture du programme à traiter) . Dans la démo c'est les boutons de commandes "Pixelliser" qui lancent ...

3/ Les contrôles rendu transparents sont utilisables éventuellement avec les procs, fonctions proposées dans TRANSPARENCE & MOBILITE ...
Ce qui permet soit de les déplacer hors de la Form, sur le bureau Window,soit d'obtenir une gestion personnalisée des masques de saisie en opacifiant plus ou moins certaines zones (l'utilisateur perçoit mieux ainsi les questions auquelles il doit répondre à un moment donné)

Il va sans dire que je suis preneur de toutes suggestions , etc... je suis loin d'avoir inventé la lune

Portez vous bien

Codes Sources

A voir également

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.