Novembre 2024 | Lun | Mar | Mer | Jeu | Ven | Sam | Dim |
---|
| | | | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | | Calendrier |
|
|
| Jack, la fonction OBJECT_INTERNAL ne fonctionne plus! RESOLU | |
| | Auteur | Message |
---|
Klaus
Nombre de messages : 12331 Age : 75 Localisation : Ile de France Date d'inscription : 29/12/2009
| Sujet: Jack, la fonction OBJECT_INTERNAL ne fonctionne plus! RESOLU Jeu 24 Mar 2016 - 23:26 | |
| Jack, tu avais réalisé la fonction OBJECT_INTERNAL, à ma demande. J'en étais très heureux et je m'en suis servi beaucoup. Une partie non négligeable de mes fonctions en dépendent. J'avais déjà signalé un changement dans l'interface entre Panoramic et KGF.dll, mais je n'avais pas vraiment d'informations très précises. Je subodorais simplement un changement de version de l'outil de réalisations de Panoramic, ce qui conduisait à une incompatibilité entre les versions de VCL. Aujourd'hui, cela se précise. En effet, la fonction OBJECT_INTERNAL retourne toujours une valeur référençant un objet Panoramic, mais la structure en est différente maintenant. Un seul exemple: si j'attends une valeur OBJECT_INTERNAL dans une fonction DLL, je déclare le paramètre comme TWinControl, ou alors comme Integer utilisé par (paramètre as TWinControl) ou (Paramètre as TListBox) etc. Tout cela marchait parfaitement. Or, ce n'est plus le cas. Certaines propriétés de TWinControl sont encore accessibles (Height, Width, Top, Left, ClassName etc), mais d'autres non. Et le plus important est Handle. Il n'y a plus moyen d'avoir le handle de l'objet passé par OBJECT_INTERNAL. Il est vu comme 0 (zéro). Seule solution, brutale, c'est de passer les deux valeurs comme paramètre: OBJECT_INTERNAL(N) et HANDLE(N). Et cela change non seulement le format d'appel de toutes les fonctions dans ce cas, mais encore pose des problèmes dans le cas des fonctions qui ont déjà 6 paramètres. Je suis assez pessimiste quant à la solution réelle de ce problème, étant donné que je ne songe en aucun cas à t'imposer un outil de développement quelconque. Mais il faut trouver un moyen de contourner cela. Et si c'est possible au prix d'un changement du fonctionnement de OBJECT_INTERNAL, ce serait peut-être envisageable. Pourrais-tu faire de sorte que cette fonction retourne l'adresse vers une structure composée de 2 mots de 32 bits, le premier contenant la valeur actuelle de OBJECT_INTERNAL, soit integer(...), et le deuxième mot le handle de cet objet ? Dans ce cas, je pourrais modifier mes fonctions sans avoir à changer la syntaxe partout. Est-ce envisageable ? Par exemple, en passant l'adresse d'un record de ce type: - Code:
-
type Object_Internal = record Control: TControl; Handle: HWND; end;
Dernière édition par Klaus le Ven 25 Mar 2016 - 21:15, édité 1 fois | |
| | | Klaus
Nombre de messages : 12331 Age : 75 Localisation : Ile de France Date d'inscription : 29/12/2009
| Sujet: Re: Jack, la fonction OBJECT_INTERNAL ne fonctionne plus! RESOLU Ven 25 Mar 2016 - 3:12 | |
| Jack, je retire ma demande ! J'ai trouvé un moyen de déterminer le handle d'un objet visuel passé par OBJECT_INTERNAL: - Code:
-
function GetHandleFromControl(ct: TControl):HWND; var d, t: integer; p: TPoint; r, rp, rc: TRect; vis, visp: boolean; begin rp := ct.Parent.BoundsRect; // prendre le rectangle extérieur du parent del'objet choisi rc := ct.Parent.ClientRect; // prendre le rectangle iintérieur du parent del'objet choisi r := TWinControl(ct).BoundsRect; // prendre rectangle extérieur de l'objet choisi d := Round((rp.Right-rp.Left - rc.Right)/2); // calculer la largeur du bord droit ou gauche du parent t := rp.Bottom-rp.Top - rc.Bottom - d; // calculer la hauteur du bord haut (ou barren de titre) p.X := r.Left+rp.Left + d + 5; // calculer les coordonnées écran du point (5,5) de l'objet choisi p.Y := r.Top+rp.Top + t + 5; visp := ct.Parent.Visible; // mémoriser l'état de visibilité du parent de l'objet choisi if not visp then ct.Parent.Visible := true; // le rendre visible si nécessaire vis := ct.Visible; // mémoriser l'état de visibilité de l'objet choisi if not vis then ct.Visible := true; // le rendre visible si nécessaire result := WindowFromPoint(p); // demander son handle à Windows if not vis then ct.Visible := false; // le rendre invisible si nécessaire if not visp then ct.Parent.Visible := false; // le rendre le parent invisible si nécessaire end; Je vais donc utiliser cette fonction au lieu de la propriété Handle d'un TWinControl, et tout rentrera dans l'ordre. C'est un peu de la gymnastique, mais ça doit marcher partout, quelque soit le type de bordure de la form parente ou de l'objet parent, et quelque soit le système. EDITJ'ai apporté une modification pour pouvoir appliquer cette fonction sur un objet caché par HIDE, et ce même si son parent est caché. | |
| | | Klaus
Nombre de messages : 12331 Age : 75 Localisation : Ile de France Date d'inscription : 29/12/2009
| Sujet: Re: Jack, la fonction OBJECT_INTERNAL ne fonctionne plus! RESOLU Ven 25 Mar 2016 - 13:50 | |
| Il y a trois limites à ma technique de récupération du handle: 1. Clignotement le fait d'avoir un objet et/ou un oarent d'objet caché, provoque une brève apparition de ces objets à l'écran avant leur disparition à nouveau. Si cela se fait dans une boucle sur plusieurs objets, cela peut conduire à un clignotement désagréable. Mais c'est malheureusement inévitable, car l'objet à tester doit être visible à l'écran pour que l'API WindowFromPoint fonctionne. 2. profondeur d'arborescence si l'arboescence des objets est plus profonde (form 0 contenant un container contenant un panel contenant un mémo, par exemple), et si un des objets supérieurs est caché (comme le container dans cet exemple), l'objet (le mémo dans cet exemple) ne pourra pas être rendu visible et on n'obtiendra pas son handle. Sauf à faire une boucle sur les ascendants jusqu'en haut, et appliquer le même traitement de visibilité à tous les ascendants. 3. objet caché par un autre si l'objet visé est caché par un autre placé en avant_plan, alors on trouvera le handle de cet autre objet et non celui de l'objet vise. Et là, je n'ai pas de solution, pour le moment.
Alors, Jack, si éventuellement tu pouvais tout de même changer le fonctionnement de OBJECT_INTERNAL de sorte à retourner l'adresse d'un record du type indiqué dans me premier post, ce serait évidemment une solution plus cohérente. | |
| | | Klaus
Nombre de messages : 12331 Age : 75 Localisation : Ile de France Date d'inscription : 29/12/2009
| Sujet: Re: Jack, la fonction OBJECT_INTERNAL ne fonctionne plus! RESOLU Ven 25 Mar 2016 - 21:14 | |
| Heureka ! J'ai trouvé la solution pérenne qui marche dans tous les cas, que l'objet soit visible ou pas, ou qu'il soit enfant d'un enfant d'un enfant d'un objet invisible, ça n'y change rien. Après avoir débuggé et dumpé la mémoire dans tous les sens, j'ai découvert que pour un TWinControl créé par mon Delphi 6 PE, la propriété Handle est mémorisée à l'offset 384 (décimal) de l'adresse représentée par integer(WinControl). Or, pour les objets passés par Panoramic via OBJECT_INTERNAL, le handle se trouve à l'offset 392, soit 8 octets plus loin. Du coup, j'ai simplifié ma fonction: - Code:
-
function GetHandleFromControl(ct: TControl):HWND; begin result := pinteger(integer(ct)+392)^; end; C'est on ne peut plus simple, et ça marche dans tous les cas. Je me suis longuement battu contre toutes sortes de blocages, des violations de mémoire etc. J'ai fait fi des déclarations péremptoires des spécialises Delphi, déclarant qu'on ne peut pas passer un TWinControl à travers les limites entre programme principal et DLL. Et j'ai trouvé que c'est une simple histoire d'offset. Certes, ce n'est pas "propre". Et en cas d'autres changements de version des outils de production, j'aurai à nouveau ce problème à résoudre. Mais maintenant, la voie est tracée, et ce sera une simple question d'ajustement de l'offset. Donc, Jack, je retire définitivement ma demande de modification et je continue d'utiliser avec gratitude cette belle fonction OBJECT_INTERNAL ! | |
| | | Minibug
Nombre de messages : 4570 Age : 58 Localisation : Vienne (86) Date d'inscription : 09/02/2012
| Sujet: Re: Jack, la fonction OBJECT_INTERNAL ne fonctionne plus! RESOLU Ven 25 Mar 2016 - 21:46 | |
| Bonsoir Klaus !
Cela semble être d'après tes dire une excellente nouvelle et je suis très content pour toi !
Cela veut il dire que tu vas de nouveau pouvoir refaire fonctionner l'ensemble des fonctions KGF dans Panoramic comme les fonctions sur le grid par exemple ?
| |
| | | Klaus
Nombre de messages : 12331 Age : 75 Localisation : Ile de France Date d'inscription : 29/12/2009
| Sujet: Re: Jack, la fonction OBJECT_INTERNAL ne fonctionne plus! RESOLU Ven 25 Mar 2016 - 21:53 | |
| Je vais approfondir la question du Grid. C'est beaucoup plus complexe, encore, mais maintenant que j'ai le handle, je vais voir si je peux agir directement par des APIs, via le handle. Donc, patience...
Mais il est vrai que je savoure ce succès qui se matérialise par une seule ligne de code ! | |
| | | Minibug
Nombre de messages : 4570 Age : 58 Localisation : Vienne (86) Date d'inscription : 09/02/2012
| Sujet: Re: Jack, la fonction OBJECT_INTERNAL ne fonctionne plus! RESOLU Ven 25 Mar 2016 - 22:05 | |
| Je te souhaite bon courage... J’espère que ta persévérance sera récompensé Et pour nous, c'est la possibilité d'utiliser toutes ces belles fonctions que tu nous fais. | |
| | | Contenu sponsorisé
| Sujet: Re: Jack, la fonction OBJECT_INTERNAL ne fonctionne plus! RESOLU | |
| |
| | | | Jack, la fonction OBJECT_INTERNAL ne fonctionne plus! RESOLU | |
|
Sujets similaires | |
|
| Permission de ce forum: | Vous ne pouvez pas répondre aux sujets dans ce forum
| |
| |
| |