Post scriptum à suite et fin transparence & mobilite de controles


Contenu du snippet

Le dernier point pour que l'on puisse utiliser les contrôles transparents ... est de supprimer éventuellement leur mobilité. Et faire ainsi qu'il(s) suive(nt) le Form principal dans son déplacement.

Dans le programme qui avait été proposé, hormis le fait qu'ils sont utilisables et peuvent devenir transparents, l'ensemble "List1/Text1" et Combo1 peuvent se déplacer également, n'importe où, dans et hors le Form Principal.

Je vous propose, comme exemple, de rajouter les instructions ci-dessous pour "ANCRER" Combo1 à Form1

Principe : Une window "Encapsuleur" est une FORM indépendante de la principale. Lors du la création de cette window "encaps..." celle-ci va se positionner dans l'écran à des coordonnées SCREEN. Ces coordonnées sont à une certaine distance de celles du Form Principal. Comme on souhaite qu'au long des déplacements de la form principal, notre Window "Encaps..." soit toujours à la même position, il nous suffit de connaître la "DIFFERENCE" entre les positions SCREEN (au DEPART) de ces deux forms.et d'appliquer systématiquement celle-ci Pour que le contrôle, à travers sa window, semble "attaché" ...

Source / Exemple :


Au niveau MODULE1 ...

1/ Déclaration d'API, constantes, Type, variables

1-a/ API :    'Nécessaire pour pouvoir recevoir le message "WM_MOVE" envoyé par Form1 lors de déplacement

Public Declare Function CallWindowProc Lib "user32" Alias "CallWindowProcA" (ByVal lpPrevWndFunc As Long, ByVal hwnd As Long, ByVal Msg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long

1-b/ CONSTANTES :

Public Const GWL_WNDPROC = (-4)

Public Const WM_MOVE = &H3

1-c/ TYPE :

Rajouter au type "Encapsuleur" ...

    DiffRectLeft As Long    'Différence entre LEFT Form principal et contrôle à encapsuler (coordonnées SCREEN en pixels)
    DiffRectTop As Long     'Différence entre TOP ...

1-d/ VARIALES :

Public lpPrevWndProc As Long    'Récupère l'ancienne adresse MEM. de gestion de Form1

Public XPos, YPos As Integer     'Coordonnées SCREEN de Form1 

2/ Procédures-Fonctions

2-a/ ... à rajouter au programme

'Détermine une adresse MEM. "Extra" qui permettra une gestion "plus approfondie" de Form1, tout en sauvegardant l'adresse "Officielle"
Public Sub Accrocher()
    lpPrevWndProc = SetWindowLong(Form1.hwnd, GWL_WNDPROC, AddressOf WindowProc)
End Sub

'Redirige toute la gestion de Form1 vers son adresse MEM. "Officielle"
Public Sub Decrocher()
    Dim temp As Long
    temp = SetWindowLong(Form1.hwnd, GWL_WNDPROC, lpPrevWndProc)
End Sub

Public Function WindowProc(ByVal hwnd As Long, ByVal uMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long    'Cas Ecran Princ + Ecran Details
    
    Select Case uMsg
        Case WM_MOVE    '2 paramètres sont renvoyés par le message WM_MOVE : le LEFT Screen et le TOP Screen
                        ' ceux-ci sont gardés en partie HAUTE (TOP Screen) et BASSE (LEFTScreen) de la valeur contenu dans lParam
            YPos = CLng("&H" & Left(right("00000000" & Hex(lParam), 8), 4))     'TOP Screen en pixels
            XPos = CLng("&H" & right(right("00000000" & Hex(lParam), 8), 4))    'LEFT Screen en pixels
            
            'Avec ces coordonnées, réactualisons la position de la window "Encapsuleur" qui enchasse Combo1 
            Call SetWindowPos(TheEncapsule(1).hwnd, -1, XPos + TheEncapsule(1).DiffRectLeft, _
            YPos + TheEncapsule(1).DiffRectTop, (Form1.Combo1.Width / 15), (Form1.Combo1.Height / 15), SWP_FRAMECHANGED)
        
            'Si on souhaitait "ancrer" également List1/Text1, à travers Frame1, il faudrait créer une autre instruction SetWindowPos en y remplaçant The Encapsule(1)par TheEncapsule(2)
        
        Case Else
      
    End Select

    'Laissons le programme gérer les autres instructions concernant Frame1
    WindowProc = CallWindowProc(lpPrevWndProc, hwnd, uMsg, wParam, lParam)
    
End Function

2-b/ ... à modifier

dans la fonction "EncapsulerControl..." remplacer :

    Call GetWindowRect(ControlAEncapsuler.hwnd, NomWndRect) 'Reprenons les coordonnées SCREEN du contrôle à encapsuler

    'Positionnons le form "Encapsuleur" en lieu et place du contrôle ...

par ...

    Call GetWindowRect(Form1.hwnd, FrmRect)
    Call GetWindowRect(ControlAEncapsuler.hwnd, NomWndRect) 'Reprenons les coordonnées SCREEN du contrôle à encapsuler
    
    With EncapsulerControl
        .DiffRectLeft = NomWndRect.Left - FrmRect.Left
        .DiffRectTop = NomWndRect.Top - FrmRect.Top
    End With
    
    'Positionnons le form "Encapsuleur" en lieu et place du contrôle ...

AU NIVEAU FORM1 ...

remplacer Private sub Form_unload(cancel ...    end sub  par

Private Sub Form_Unload(Cancel As Integer)

    Call SetParent(Picture1.hwnd, Form1.hwnd)   'N'oublions pas la picture. Elle n'est pas dans le proc "LibereEncapsulage"
    
    'IL NE FAUT JAMAIS OUBLIER DE SUPPRIMER LA ZONE MEM. EXTRA AVANT DE QUITTER LE PROGAMME
    Module1.Decrocher
    
    End 'Fin de programme, on décharge la mémoire de tous les composants résiduels
    
End Sub

Conclusion :


Il ne faut pas prendre en compte le commentaire que j'avais déposé le 08/07/04 à 21:04:46. Cette forme d'attachement marche, mais elle n'est pas élégante

Si quelqu'un comprend pourquoi dans Form_Unload l'instruction END située juste après Module1.Decrocher vire le prog (utilisation en version non compilée) qu'il me le fasse savoir, je suis preneur.

Un dernier mot : Si vous souhaitez encapsuler des contrôles faisant appel à plusieurs frames superposés, mettez l'ensemble dans un frame. C'est ce dernier qui sera encapsulé.

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.