Ceci est une page optimisée pour les mobiles. Cliquez sur ce texte pour afficher la vraie page.

XL 2016 VBA - Taux de recouvrement d'un RECT par un autre RECT

Dudu2

XLDnaute Barbatruc
Bonjour à tous,

Le point de départ de ce problème est la question "doit-on changer le OWNER d'un UserForm" ?
Parce que s'il est placé ou déplacé sur l'une des fenêtres d'un classeur qui n'est pas son OWNER, on le sait grâce à l'évènement UserForm_Layoit(), il sera masqué totalement ou partiellement par cette fenêtre dès lors qu'elle sera active. Et dans ce cas, il faut changer son OWNER par le Handle de la fenêtre en question.

D'où la question... Quel est le taux de recouvrement du UserForm RECT par un Window RECT.

La fonction PourcentageUserFormSurfaceCouverteParWindow dans ce fichier est à écrire !
 

Pièces jointes

  • Classeur5.xlsm
    29.9 KB · Affichages: 1
Dernière édition:

Dudu2

XLDnaute Barbatruc
Le souci est que quand un UserForm est ouvert pour un classeur, il ne l'est pas pour tous les classeurs ouverts.

Par exemple si j'ai un UserForm pour la saisie des salariés affiché pour un classeur de liste de salariés, il n'a aucune raison d'être encore affiché pour un autre classeur resté ouvert des menus de la cantine.

Donc l'idée c'est qu'en fermant le classeur des salariés, le UserForm de saisie des salariés se ferme aussi.
Or avec l'owner = 0, c'est précisément ce qui n'est pas possible si la gestion de ce UserForm est centralisée dans un classeur indépendant ou plutôt un complément qui traite globalement d'une activité particulière (HR ou Compta par exemple).

Car Excel qui ne s'intéresse qu'aux Windows, n'a pas prévu d'associer un UserForm avec un classeur.
Ni pour la gestion de la fermeture automatique, ni pour l'affichage ForeGround sur toutes les fenêtres du classeur. D'où les 2 bidouilles (TOPMOST et Owner = 0) qu'on est obligé de faire mais dont il faut gérer les conséquences qui vont au-delà de ce qu'on souhaiterait.

Et donc il faut le faire à sa place artificiellement en conservant les UserForms détachés des classeurs pour lesquels ils ont été ouverts et utiliser le Workbook_BeforeClose() ou plutôt une Classe_WorkbookBeforeClose() pour faire le ménage.
 
Dernière édition:

patricktoulon

XLDnaute Barbatruc
re je pige pas pourquoi ce userform devrait aller dans un addins si c'est pour un classeur salarié et pas un autre
autant le laisser dans le classeur salarié
faire de l'addins pour faire de l'addins c'est absurde
ou alors tu fait ton show perso façon calendaire et tu classe un object workbook dans le userform et c'est tout
pas compliqué le truc
 

Dudu2

XLDnaute Barbatruc
Faut juste une petite classe Class_UserFormWindowFree qui stocke les UserForms détachés et qui les ferme à la fermeture du classeur.
VB:
Option Explicit

'-------------------------------------------------------------------------------------------------------------------------
'Un UserForm détaché doit être un UserForm non Modal (UserForm.Show vbModeless).
'
'Un UserForm détaché est un UserForm dont le Owner initialement défini par Excel à sa Window de création a été forcé à 0
'via l'API SetWindowLongPtr UserFormHandle, GWL_HWNDPARENT, 0
'Cela pour éviter que la fermeture de sa Window de création ne le ferme également laissant les éventuelles autres
'Windows du classeur dépourvues du UserForm qui leur est potentiellement utile.
'
'Le problème est qu'à la fermeture du classeur, le UserForm normalement fermé à la fermeture de sa Window de création
'n'est pas fermé si un autre classeur est ouvert car tant que le classeur ou le complément créateur du UserForm est actif,
'l'instance du UserForm restera présente.
'
'Il faut donc un mécanisme de fermeture des UserForms détachés à la fermeture du classeur qui les a vu naître.
'-------------------------------------------------------------------------------------------------------------------------

'https://docs.microsoft.com/fr-fr/office/vba/api/excel.application(object)
Public WithEvents App As Application

Private Type UserFormWindowFree
    UserForm As Object
    Workbook As Workbook
End Type

Private TabUserFormWindowFree() As UserFormWindowFree
Private NbUserFormWindowFree As Integer

'------------------------------------------------
'Sub to call when setting the UserForm Owner to 0
'------------------------------------------------
Sub Add(UserForm As Object)
    Dim i As Integer

    'UserForm already stored ?
    For i = 1 To NbUserFormWindowFree
        If TabUserFormWindowFree(i).UserForm Is UserForm _
        And TabUserFormWindowFree(i).Workbook Is ActiveWorkbook Then Exit For
    Next i

    'Yes
    If i <= NbUserFormWindowFree Then Exit Sub
 
    'Add the UserForm
    NbUserFormWindowFree = NbUserFormWindowFree + 1
    ReDim Preserve TabUserFormWindowFree(1 To NbUserFormWindowFree)
    Set TabUserFormWindowFree(NbUserFormWindowFree).UserForm = UserForm
    Set TabUserFormWindowFree(NbUserFormWindowFree).Workbook = ActiveWorkbook
End Sub

'------------------------
'App_WorkbookBeforeClose
'------------------------
Private Sub App_WorkbookBeforeClose(ByVal Wb As Workbook, Cancel As Boolean)
    Dim i As Integer
    Dim k As Integer

    'Close Workbook UserForms
    i = 1
    Do While i <= NbUserFormWindowFree
        If TabUserFormWindowFree(i).Workbook Is Wb Then
            Unload TabUserFormWindowFree(i).UserForm
    
            'Remove table item
            For k = i To NbUserFormWindowFree - 1
                TabUserFormWindowFree(k) = TabUserFormWindowFree(k + 1)
            Next k
    
            NbUserFormWindowFree = NbUserFormWindowFree - 1
            If NbUserFormWindowFree = 0 Then
                Erase TabUserFormWindowFree
            Else
                ReDim Preserve TabUserFormWindowFree(1 To NbUserFormWindowFree)
            End If
    
            i = i - 1
        End If
 
        i = i + 1
    Loop
End Sub

Et dans le code:
VB:
Option Explicit

'Class for the management of Events of Window-Free-UserForms (Owner = 0)
Public ClassUserFormWindowFree As New Class_UserFormWindowFree

'------------------
'Ouverture classeur
'------------------
Sub Auto_Open()
    'Instanciation of Classes
    Set ClassUserFormWindowFree.App = Application
End Sub

'-----------------
'UserForm_Activate
'-----------------
Private Sub UserForm_Activate()
    'Fonctions de la ressource
    'https://excel-downloads.com/resources/vba-userform-et-moniteurs-system-menu-minimiser-restaurer-placement-programmation-avancee.1544/
 
    'Ajout de la minimisation système et autres settings
    Call SetUserFormSystemMenuOptions(Me, MinimizeToMonitor:=True, MinimizeButton:=True)
    Call SetUserFormTopMost(Me)
    Call SetUserFormWindowFree(Me)

    'Ou encore
    SetWindowLongPtr GetActivewindow, GWL_HWNDPARENT, 0

    'Mémorisation du UserForm détaché
    Call ClassUserFormWindowFree.Add(Me)
End Sub
 
Dernière édition:

Discussions similaires

Les cookies sont requis pour utiliser ce site. Vous devez les accepter pour continuer à utiliser le site. En savoir plus…