PC SOFT

PROFESSIONAL NEWSGROUPS
WINDEVWEBDEV and WINDEV Mobile

Home → WINDEV 2024 → [ Onglet dynamique détachable avec barre système ]
[ Onglet dynamique détachable avec barre système ]
Started by Damien, Jan., 22 2021 11:26 AM - 26 replies
Posted on January, 22 2021 - 11:26 AM
Bonjour,
J'aimerais faire une application avec des onglets dynamiques détachables. Cependant je me rends compte que les onglets dynamiques sont difficilement redimensionnables et on ne peut pas la coller sur les bords de son écran pour la mettre sur un moitié d'écran une fois détacher.

Dans ma barre système de mon onglet, actuellement je n'ai que la croix, je ne peux redimensionner la fenêtre qu'en mettant la souris au bord de celle-ci et en l'étirant… Ce n'est pas du tout pratique pour l'utilisateur.

J'aimerais avoir la barre système de mon onglet ainsi : (Pour pour pouvoir au moins mettre en plein écran et réduire l'onglet.)



J'aimerais aussi que l'on puisse la coller sur un bord de l'écran pour l'onglet prennent que la moitié de l'écran par exemple comme le font n'importe quelle fenêtre aujourd'hui.

Est-ce que cela est possible ?
Registered member
9 messages
Posted on January, 22 2021 - 12:10 PM
Bonjour,

Il y a un exemple d'utilisation des onglets par Windev : WD Gestion Commerciale

Tu trouveras surement ce qu'il te faut dedans.
Posted on January, 22 2021 - 1:47 PM
Merci de ta réponse.
En effet ils utilisent des onglets dynamiques, mais c'est exactement ce que j'ai actuellement et que je voudrais changé.
Je voulais savoir s'il y avait moyen de faire différemment pour que les onglets une fois détachés puissent être redimensionné etc plus facilement. Car pour moi la seule fonctionnalité de pouvoir sortir de l'onglet n'est pas très utile si derrière on ne peut pas placer et redimensionner sa fenêtre facilement.

(Peut-être que du coup ce n'est pas possible mais je garde espoir)
Registered member
3,845 messages
Popularité : +227 (347 votes)
Posted on January, 22 2021 - 3:46 PM
Bonjour,
Tu pourrais essayer de regarder du côté des panneaux dockables

--
Il y a peut être plus simple, mais, ça tourne
Registered member
3,311 messages
Popularité : +93 (137 votes)
Posted on January, 22 2021 - 9:52 PM
LST n°62 : WD Volets MDI
Cet exemple montre comment utiliser les zones MDI d'une fenêtre mère MDI pour les transformer en volets ancrables.
Chaque zone (gauche, bas, droite, ...) peut être redimensionnée par programmation grâce aux propriétés ..MDIGauche, ..MDIBas, ..MDIDroite, ...
L'ajout d'un splitter sur les bordures de ces zones permet alors de contrôler le redimensionnement de ces zones par programmation. Tous les champs ancrés se trouvant sur ces zones seront redimensionnés automatiquement par le mouvement du splitter.
Je crois qu'il peut répondre a tes besoin
Registered member
213 messages
Popularité : +12 (12 votes)
Posted on January, 24 2021 - 7:07 PM
Je me permets de faire un bout de chemin sur le sujet de Damien.

Les panneaux dockables ne sont pas la solution, on parle d'onglets dynamiques "détachables".
Les fonctions MDIGauche et similaires ne s'appliquent qu'aux fenêtres MDI (Mère/Fille), ce qui n'est pas l'objectif ici.

Mes tentatives pour résoudre ce même problème par programmation sont toutes vaines.

Dans la fenêtre interne appelée par mon champ onglet, j'ai la procédure suivante.
La procédure a un timer d'une seconde déclenché à l'ouverture de la fenêtre interne.
Procedure ProFlottant()
SI OngletEtat(WfenTest.FongTest, WfeiTest..Alias) = voletFlottant ALORS
Trace("Flottant")
SINON
Trace("Pas flottant")
FIN

Naturellement, "Pas flottant" est dans la trace tant que le volet est attaché.
Puis lorsque je détache le volet et que je le relâche, la trace change pour "Flottant".

Dans mon SINON j'ai toute tenté.
- Soit je me retrouve à changer la dimension de la fenêtre qui contient l'onglet.
- Soit je me fais dire que je tente de manipuler un objet qui n'existe pas.
- Soit je change les dimensions du champ Onglet parent.

Pourtant, Windev reconnaît l'onglet "flottant" puisque je retrouve l'élément suivant dans le INI:
[WfenTest_WfeiTest_FsepTest]

Une sauvegarde de FAA pour la position du séparateur.
Fenêtre, Nom de fenêtre interne, Séparateur

Il semblerait qu'un "volet détaché" ne possède pas de Hauteur, Largeur ou autres éléments de références.
Pourtant et tel que le mentionne Damien, je peux redimensionner le volet détaché manuellement.

Si vous avez une solution je suis preneur.

Bon dev.

Serge

--
-----
Parfois, la logique est implacable...
Posted on January, 26 2021 - 3:16 PM
Peut-être qu'en utilisant le code que tu as mis on peut faire un fermeOnglet et un ouvreFille plutôt que la fonction détacher de base.
J'ai eu cette idée mais je n'ai pas réussi à aller au bout et en faire quelque chose de fonctionnelle.
Mais peut être que quelqu'un y arrivera en cherchant de son coté

En attendant toutes réponse peut être constructives, je prends tout ce que vous avez à proposer sur le sujet !
Merci.
Registered member
213 messages
Popularité : +12 (12 votes)
Posted on January, 26 2021 - 11:00 PM
Damien,

Plutôt que de faire une telle gymnastique je serais porté à éliminer l'onglet.

J'utilise les onglets pour ce qu'ils sont, des onglets.
À ce moment ils ne sont pas détachables.

Bon dev.

Serge

--
-----
Parfois, la logique est implacable...
Registered member
3,311 messages
Popularité : +93 (137 votes)
Posted on January, 27 2021 - 8:57 AM
C'est pas pour rien que voroltinquo et moi même on propose des alternatives.
Registered member
213 messages
Popularité : +12 (12 votes)
Posted on February, 03 2021 - 2:33 AM
Popoy:
En effet et j'apprécie l'intention, je t'assure.

Damien:
Peut-être qu'en utilisant le code que tu as mis on peut faire un fermeOnglet et un ouvreFille plutôt que la fonction détacher de base.

Si j'ai rejeté ton idée elle a tout de même hantée mes pensées.


Logique d'utilisation:
1) Depuis une liste affichée dans l'onglet statique l'utilisateur demande pour un produit spécifique
2) Ouverture d'un onglet dynamique selon le processus usuel
3) Cette "fenêtre interne" contient un nouveau bouton "Détacher"
4) L'utilisateur clique sur le bouton "Détacher"
5) Ouverture d'une fenêtre qui reprend le dossier du produit affiché
6) Fermeture de l'onglet dynamique


Mise en contexte:
WfenAvecOnglet = Fenêtre qui contient l'onglet dynamique
FongDynamique = Onglet dynamique de WfenAvecOnglet
WfeiUnDossier = Fenêtre interne chargée par l'onglet

WfenDétaché = NOUVELLE fenêtre qui recevra l'onglet qui sera "détaché"
FfeiDétaché = "CHAMP" fenêtre interne qui recevra l'onglet qui sera détaché

--
-----
Parfois, la logique est implacable...
Registered member
213 messages
Popularité : +12 (12 votes)
Posted on February, 03 2021 - 2:34 AM
WfenDétaché (Nouvelle fenêtre)

1) Création de la fenêtre
- Dimensions au choix
- Mémoriser la taille et la position n'est *PAS* coché (Mon cas)
- Adapter la taille en fonction du contenu est coché
- Redimensionnable est coché

2) Ajout du champ "FfeiDétaché" à "WfenDétaché"
- Ce champ occupe pratiquement tout l'espace disponible
- Il est ancré en largeur tout comme en hauteur
- Il est le seul champ de cette fenêtre

3) Paramètres de "WfenDétaché"
- LOCAL pFenêtre est une chaîne,
- LOCAL pClé est une chaîne,
- LOCAL pTitre est une chaîne,
- LOCAL pIcone est une Icône

4) Fin d'initialisation de "WfenDétaché"
- ChangeFenêtreSource(FfeiDétaché, pFenêtre, pClé, Faux) <--- Faux = Bouton "Détacher" non visible
- WfenDétaché..Titre = pTitre
- WfenDétaché..icone = pImage <--- Ne fonctionne pas

--
-----
Parfois, la logique est implacable...
Registered member
213 messages
Popularité : +12 (12 votes)
Posted on February, 03 2021 - 2:35 AM
WfeiUnDossier (Fenêtre interne chargée par l'onglet)

1) Paramètres de "WfeiUnDossier"
- LOCAL pNoProduit est un entier (Paramètre existant)
- LOCAL pDétacher est un booléen = Vrai (Nouveau paramètre)

2) Fin d'initialisation de "WfeiUnDossier"
FbtnDétacher..Visible = pDétacher

Le bouton est visible lorsque chargé dans un onglet
Le bouton est NON visible lorsque chargé dans une fenêtre

3) Ajout du bouton "FbtnDétacher"

3) Code "Clic" de FbtnDétacher
//--- Prend note du libellé de l'onglet
chiLibellé est une chaîne = WfenAvecOnglet.FongDynamique[WfenAvecOnglet.FongDynamique]..Libellé

//--- Ouvre une fenêtre pour détacher l'onglet
OuvreSoeur(WfenDétaché, "WfeiUnDossier", pNoProduit, chiLibellé, WfenAvecOnglet..Icone)

//--- Ferme l'onglet actuel
OngletFerme()

5) Code du bouton "Fermer" de "WfeiUnDossier"
SI FbtnDétacher..Visible = Vrai ALORS OngletFerme() ...
SINON Ferme()

--
-----
Parfois, la logique est implacable...
Registered member
213 messages
Popularité : +12 (12 votes)
Posted on February, 03 2021 - 2:37 AM
WfenAvecOnglet (Fenêtre existante)

Sur ouverture d'un onglet d'ynamique:
OngletOuvre(FongListe, "Nom du produit", "WfeiUnDossier", es4NoProduit, Vrai) <--- Vrai = Bouton "Détacher" visible

--
-----
Parfois, la logique est implacable...
Registered member
213 messages
Popularité : +12 (12 votes)
Posted on February, 03 2021 - 2:38 AM
Mes notes:

Le passage de l'onglet dynamique vers WfenDétaché est, selon moi, transparent.
J'aime l'idée.

Il serait aisé d'imaginer le processus inverse.
Soit de "ré" attacher la fiche produit à un onglet dynamique.
Je ne vois pas l'intérêt.


Dans mon cas, chaque fiche produit est ouverte en consultation (onglet dynamique).
Un bouton "Modifier" permet de passer en modification.
Dans un tel cas "Détacher" est grisé.

On ne détache pas une fiche produit en cours de modification.
Une décision qui évite d'avoir à passer tous les champs et leurs valeurs en paramètre.


Je ne parviens pas à assigner l'icône de WfenDétaché.
Une technicalité, il suffit de trouver comment faire pour plaire à Windev.


Ce qui m'agace:
Avant de charger un nouvel onglet dynamique je confirme que la fiche produit n'est pas déjà active.
Si tel est le cas je donne le focus à cet onglet dynamique existant.

J'aimerais faire la même chose si la fiche produit est "détachée".
MAIS... Je ne parviens pas à lister les fenêtres pour la retracer.
https://forum.pcsoft.fr/fr-FR/pcsoft.fr.windev/246351-liste-fenetres/read.awp


Voilà, ton idée fait un bout de chemin.

Bon dev.

Serge

--
-----
Parfois, la logique est implacable...
Registered member
213 messages
Popularité : +12 (12 votes)
Posted on February, 05 2021 - 3:30 AM
Problème de la fiche produit "détachée" résolu.
Je peux la localiser et lui donner la préséance.

https://forum.pcsoft.fr/fr-FR/pcsoft.fr.windev/246351-liste-fenetres/read.awp

Pour être heureux, il me reste à trouver comment affecter l'icône de la fenêtre détachée.
8)

--
-----
Parfois, la logique est implacable...
Registered member
213 messages
Popularité : +12 (12 votes)
Posted on February, 05 2021 - 4:21 AM
!#@ de !!!

Je passais l'icône en paramètre en tant qu'image, et non comme une chaîne qui donne son chemin\nom.
Il faut le "nom" de l'icône, et non sa représentation graphique, je le sais pourtant.

Parfois, on fait des détours inutilement.
:p

Bref, le volet dynamique "détaché", c'est résolue pour ce qui est de moi.
Je vais tester avec d'autres cas d'utilisation au cours des semaines à venir.

Bon dev.

Serge

--
-----
Parfois, la logique est implacable...
Posted on February, 05 2021 - 3:24 PM
Bonjour,

ce code ajoute les boutons maximize et minimize dans la barre de titre de la la fenêtre détachée.
A copier dans le code de l'onglet
//Initialisation de ONG_TEST
//---------------------------------
GLOBAL
gtabHwnd est un tableau d'entier


//Dans l'évènement : Création d'un volet dans ONG_TEST
//--------------------------------------------------------------
Volet est un Champ
Volet <- OngletOuvre(ONG_TEST, "Nouveau document") //, FI_Document)

gtabHwnd.Ajoute(Handle(Volet..Alias))


//Dans l'évènement : Détachement d'un volet de ONG_TEST
//-----------------------------------------------------------------
SetCaption( ) //Appel d'une procédure automatique

//---------------------------------------------------------------------------------------------------
//Déclarer une nouvelle procédure automatique
// Procédure automatique :
// La procédure est exécutée manuellement, lors d'un appel dans le code, avec un différé de 0s
//
//Automatisme de la procedure
//
//Type
// Timer/Procédure différée
//
//Quand
// Différé de OO:OO:OO:OO (HH:MM:SS:CC}, après l'appel de la procédure

PROCÉDURE SetCaption(LOCAL tabHwnd est tableau d'entiers)

soit GWL_STYLE = -16
soit WS_MAXIMIZEBOX = 0x00010000
soit WS_MINIMIZEBOX = 0x00020000

N est entier
POUR TOUT N DE tabHwnd
SI API("user32", "IsWindow", N) ALORS
nHwnd est entier
BOUCLE
nHwnd = N
N = API("user32","GetParent", nHwnd)
À FAIRE TANTQUE N > 0

nWL est entier = API(USERDLL,"GetWindowLongW", nHwnd, GWL_STYLE)
nNewWL est entier = nWL | WS_MAXIMIZEBOX | WS_MINIMIZEBOX
API(USERDLL,"SetWindowLongW", nHwnd, GWL_STYLE, nNewWL)
FIN
FIN

Bonne journée
Registered member
27 messages
Posted on March, 07 2022 - 4:40 PM
Bonjour,

Je sais que le sujet date mais la solution de Christian m'a l'air simplifié mais j'ai deux problèmes :
-A quoi correspond USERDLL - > API(USERDLL,"SetWindowLongW", nHwnd, GWL_STYLE, nNewWL)
-Dans l'appel de SetCaption( ) //Appel d'une procédure automatique il faut bien mettre -> SetCaption(gtabHwnd)

Bonne journée.
Registered member
1 message
Posted on March, 09 2022 - 12:30 PM
En partant du code proposé par Christian, j'ai effectué quelques ajustements et corrections.
Principalement parce que le code de Christian traitait, à chaque appel à la procédure SetCaption(), tous les handles mémorisés dans le tableau, alors qu'il suffit de ne traiter celui de l'onglet/fenêtre concerné.

De plus une petite omission dans le code faisait que les handles étaient ajoutés dans le tableau sans jamais être retirés à la fermeture des onglets/fenêtres. Du coup cela s'empilait à l'infini, risquant un plantage ou un problème de mémoire à la longue.

Merci Christian pour m'avoir mis sur la voie, j'espère que le code qui suit aidera les autres :-)

//A mettre dans le CODE DU PROJET ou de la fenêtre contenant ONG_TEST
//---------------------------------
gtaTabsHandles est un tableau associatif d'entier


//Dans l'évènement : Création d'un volet dans ONG_TEST ou à la création d'un volet via un autre moyen
//--------------------------------------------------------------
Volet est un Champ
Volet <- OngletOuvre(ONG_TEST, "Nouveau")

gtaTabsHandles[Volet..Alias]=Handle(Volet..Alias)


//Dans l'évènement : Détachement d'un volet de ONG_TEST
//-----------------------------------------------------------------
//*** ON NE GÈRE QUE LE VOLET CONCERNÉ !!!
SetCaption(gtaTabsHandles[ONG_TEST[ONG_TEST]..Alias]) //Appel d'une procédure automatique

//Dans l'évènement : Fermeture d'un volet de ONG_TEST
//-----------------------------------------------------------------
//*** ON NE GÈRE QUE LE VOLET CONCERNÉ !!!
gtaTabsHandles.supprime(ONG_TEST[ONG_TEST]..Alias) // Supprimer l'onglet de la liste des Handles


//---------------------------------------------------------------------------------------------------
//Déclarer une nouvelle procédure automatique
// Procédure automatique :
// La procédure est exécutée manuellement, lors d'un appel dans le code, avec un différé de 0s
//10:09 09/03/2022
//Automatisme de la procedure
//
//Type
// Timer/Procédure différée
//
//Quand
// Différé de OO:OO:OO:OO (HH:MM:SS:CC}, après l'appel de la procédure

Procedure SetCaption(LOCAL sTabAlias est une chaîne)

//*** ON NE GÈRE QUE LE VOLET CONCERNÉ !!!
nTabHandle est un entier = gtaTabsHandles[sTabAlias]

soit GWL_STYLE = -16
soit WS_MAXIMIZEBOX = 0x00010000
soit WS_MINIMIZEBOX = 0x00020000

SI API("user32", "IsWindow", nTabHandle) ALORS
nHwnd est entier
BOUCLE
nHwnd = nTabHandle
nTabHandle = API("user32","GetParent", nHwnd)
À FAIRE TANTQUE nTabHandle > 0

nWL est entier = API("user32","GetWindowLongW", nHwnd, GWL_STYLE)
nNewWL est entier = nWL | WS_MAXIMIZEBOX | WS_MINIMIZEBOX
API("user32","SetWindowLongW", nHwnd, GWL_STYLE, nNewWL)
FIN
Message modified, March, 09 2022 - 12:31 PM
Registered member
27 messages
Posted on March, 10 2022 - 2:09 PM
Merci Andy :)
Posted on December, 22 2022 - 6:09 PM
Bonjour,

J'ai repris votre exemple, j'ai fais un programme de test et je n'arrive pas à avoir les boutons d'agrandissement sur la fenêtre détachée.

La condition ci-dessous renvoie Faux :
SI API("user32", "IsWindow", nTabHandle) ALORS

J'ai même mis en commentaire ce test mais ça ne fonctionne toujours pas.

Pouvez-vous faire un programme de test et le partagez SVP.

Merci beaucoup
Posted on December, 23 2022 - 9:08 AM
En analysant le code j'ai vu qu'il y avait une erreur, il faut remplacer

SetCaption(gtaTabsHandles[ONG_TEST[ONG_TEST]..Alias]) //Appel d'une procédure automatique


Par
SetCaption(ONG_TEST[ONG_TEST]..Alias) //Appel d'une procédure automatique
Posted on December, 23 2022 - 1:08 PM
Maintenant que la fenêtre interne soit détachée, avec les boutons Réduire / Agrandir, il y a un autre soucis.

Les ancrages ne fonctionnent pas lorsque l'on clic sur le bouton pour agrandir de la fenêtre.

J'ai mis un bouton en bas à droite de la fenêtre interne, avec un ancrage afin que celui-ci soit toujours en bas à droite.

=> Lorsqu'on clic sur le bouton agrandir, les ancrages ne fonctionnent pas.

Avez-vous une astuce SVP ? (il me manque plus que ça)
Posted on January, 20 2023 - 10:17 AM
Quelqu'un peu apporter son expertise ? :)
Registered member
446 messages
Popularité : +31 (43 votes)
Posted on January, 26 2023 - 2:00 PM
Bonjour

Si quelqu'un à une idée je suis également preneur merci ;)

cdlt

DG
Registered member
31 messages
Popularité : +3 (3 votes)
Posted on January, 26 2023 - 11:10 PM
Bonjour,

Pour la demande initiale de Damien, je propose que tout le monde fasse la demande d évolution au support technique pcsoft :
=> Pouvoir maximiser, réduire un volet détaché d un onglet dynamique (avoir le 3 boutons systèmes d une fenêtre Windows pour un volet détaché)

J ai fait la demande il y a 2 semaines environ => plus nous serons nombreux à le demander, plus nous aurons une chance de l obtenir…

A+

--
Alexandre HIRAULT
TACT Conseil
http://www.tact-conseil.fr
Posted on February, 03 2023 - 10:25 AM
Je n'ai pas encore essayé par manque de temps mais peut-être qu'en indiquant à la fenêtre que sa taille à changer, ça pourrait fonctionner (à condition que les évènements interne à Windev soit déclenché).

Il s'agit de faire
SendMessage (Handle, WM_SIZE, SIZE_RESTORED, CreateLParam(nWidth, nHeight))

ou une autre écriture
SendMessage (Handle, WM_SIZE, SIZE_RESTORED, (nWidth & 0xFFFF) | ((nHeight & 0xFFFF) << 16))

ou une autre écriture
SendMessage (Handle, WM_SIZE, SIZE_RESTORED, MAKELPARAM(nWidth, nHeight))