DeltaFX
Messages postés449Date d'inscriptionlundi 19 avril 2004StatutMembreDernière intervention 8 avril 2009
-
17 avril 2006 à 16:51
cs_Delphiprog
Messages postés4297Date d'inscriptionsamedi 19 janvier 2002StatutMembreDernière intervention 9 janvier 2013
-
30 avril 2006 à 13:50
'alut les gens ,
Comme d'hab, je me pose une question tordue : Je me demande comment faire pour envoyer un message a toute les forms d'une appli, à partir d'une form secondaire de cette appli. J'ai zieuté le tuto de Delphiprog et deux-3 autres sources mais ca reste fortement nébuleux, ces windowseries
Pour l'instant: j'ai une form A dédiée à la surveillance d'une carte IO qui lorsqu'une entrée précise passe à 1, me change une variable globale. Mes autres forms sont équipées de timers, et régulièrement, regardent l'état de cette variable globale et agissent en conséquence. Donc le temps de réaction de chaque form dépend de son timer. L'idée qui me turlupine, serait que ma form A puisse broadcaster une sorte de WM-User Message dans toute mon appli, sans avoir besoin de connaitre chacune des autres forms susceptibles de comprendre ce message.
Imaginer la vigie d'un bateau qui choppe le micro et balance "Icerberg a tribord" dans le circuit audio (Tout l'équipage l'entend, ceux qui doivent réagir a une annonce de ce type font ce qu'ils ont a faire, les autres le message les concernent pas) plutot qu'enchainer des messages genre "vigie a passerelle, icerberg a tribord.", " vigie a timonerie, icerberg a tribord" etc etc etc.
cs_shining
Messages postés304Date d'inscriptionlundi 30 décembre 2002StatutMembreDernière intervention10 mars 2012 18 avril 2006 à 12:29
euh non Application.Form.Count ça n'existe pas !!!
Application.Form[i].JustDo(WhatISay) ; même si Application.Form existait ça ne marcherait pas !!! car TForm ne possède pas ta fonction
dans ce cas là tu crée une nouvelle fiche et tu mets ta déclaration comme suit
TGlobalForm = class(TForm)
...
public
procedure JustDo;
ensuite dans le menu de Delphi Projet->Voir le source
tu retires
Application.CreateForm(TGlobalForm..) car le but c'est d'avoir une classe de Base
ensuite dans tes déclarations des Form il suffit de remplacer
MyForm class(TForm) par MyForm class(TGlobalForm)
et c'est seulement là qu'on peut faire un transtypage universel pour tes Fiches
TGlobalForm(Formxx).JustDo !!! capich ??
maintenant concernant l'énumération des Forms, c'est extremement facile si c'est des fiches MDIChilds ce qui ne semble pas être ton cas !!
maintenant il existe de nombreuses solutions pour les non MDI
pour faire très court je te mets des liens
Ensuite dans chaque Fiche tu mets TMyForm1 = class(TForm , IGlobalForm)
et là pareil IGlobalForm(MyForm1).DoSomething_1; la différence est qu'il est plus facile avec la 1er méthode d'appeler une fiche juste avec son nom avec par exemple
cs_Delphiprog
Messages postés4297Date d'inscriptionsamedi 19 janvier 2002StatutMembreDernière intervention 9 janvier 201332 19 avril 2006 à 10:28
Salut,
Ton problème correspond parfaitement à la définition du design pattern Observer. Dans ton cas, chaque fiche ayant besoin d'être notifiée viendrait s'enregistrer auprès du sujet.
Du coup, tu n'utilises qu'un timer pour relever l'état du signal et tu notifies les fiches présentes uniquement en cas de changement d'état.
Ce n'est absolument pas compliqué à mettre en place et c'est nettement plus performant.
Il existe une multitude d'exemples sur le net et je te recommande l'exemple fourni par Pierre Castelain.
May Delphi be with you !
<HR color=#008000>
Pensez à cliquer sur Réponse acceptée lorsque la réponse vous convient.
DeltaFX
Messages postés449Date d'inscriptionlundi 19 avril 2004StatutMembreDernière intervention 8 avril 20092 17 avril 2006 à 17:11
Accessoirement l'autre idée sous-jacente serait de n'avoir qu'un seul timer dans mon appli, du genre un truc qui boucle a 20 ms, et qui puissent emettre plusieurs message en fonction des besoin (en multiple de 20ms ).
Au moment du create d'une form, elle broadcaste un message genre "je veux un timer a 200ms", la form-principale qui contient ce meta-timer timer répond au message "ok timer crée" et tout les 10 beat (10 fois 20ms), le meta-timer envoie un message particulier. La form qui avait besoin de ce timer n'a qu'à écouter les message circulant dans l'appli, et quand elle recoit celui qui l'interresse , elle déclenche ou pas ce qu'elle doit faire. selon l'état d'un bouléen.
cs_shining
Messages postés304Date d'inscriptionlundi 30 décembre 2002StatutMembreDernière intervention10 mars 2012 17 avril 2006 à 17:29
une autre alternative c'est de mettre dans chaque Form
en protected
procedure WMAlert(var Message : TMessage); message WM_ALERT;
ensuite dans un fichier par exemple MyConst.pas
tu mets
Uses
Messages;
WM_ALERT = WM_USER + 10;
WM_AUTRE = WM_USER + 20;
WM_ALERT est un exemple bien entendu !!
ensuite dans la Form principale qui se charge des événements lues depuis la carte il suffirait d'une énumération des Fiches de l'Application voir même en les mettants dans un Lookup si besoin est !!
puis un simple
Perform(WM_ALERT , 0 , 0); <=== remarque tu peux aussi transmettre des variables avec un Transtypage en Integer exemple Integer(@MyString)
le but étant d'éviter l'usage intempestif des Timers
Vous n’avez pas trouvé la réponse que vous recherchez ?
DeltaFX
Messages postés449Date d'inscriptionlundi 19 avril 2004StatutMembreDernière intervention 8 avril 20092 17 avril 2006 à 18:06
"ensuite dans la Form principale qui se charge des événements lues
depuis la carte il suffirait d'une énumération des Fiches de
l'Application voir même en les mettants dans un Lookup si besoin est !!"
Le probleme est que la form qui se charge de la partie hardware n'est pas la form principale. Et surtout si je dois enumerer les fiches, on perd en simplicité, autant déclarer dans chaque fiche une fonction/procédure publique, déclarer ces fiches dans le use implementation de ma form hardware et déclencher comme ca. Le but est que mes forms ne se connaissent pas entre elles.
cs_shining
Messages postés304Date d'inscriptionlundi 30 décembre 2002StatutMembreDernière intervention10 mars 2012 17 avril 2006 à 19:01
le problème c'est que SendMessage nécessite un Handle précis !! donc il faut obligatoirement connaître la fenêtre pour lui envoyée un Message !!!
si non il faudra obligatoirement créer un nouveau composant
Exemple
Unit MessageHookers;
Uses
Windows , Forms, Messages, Fiche1, Fiche2;
Type
TMessageHooker = class(TComponent)
private
protected
function WinHook(var Message : TMessage): Boolean;
......
implementation
function TMessageHooker.WinHook(var Message : TMessage): Boolean;
begin
case Message.MSG
WM_ALERT : if Message.WParam = FichIndex1 then ShowMessage('Alert Fiche1');
end;//Case
end;
procedure TMessageHooker.Create(AOwner : TComponent);
begin
inherited Create(AOwner);
Application.HookMainWindow(WinHook);
end;
procedure TMessageHooker.Destroy;
begin
Application.UnhookMainWindow(WinHook);
inherited Destroy;
end;
voilà et on envoi
SendMessage(Application.Handle , WM_ALERT , IndexDeLaFicheCible , 0);
où peut être qu'on peut faire un SetWindowsHookEx dans chaque form j'ai pas tester !!!
DeltaFX
Messages postés449Date d'inscriptionlundi 19 avril 2004StatutMembreDernière intervention 8 avril 20092 18 avril 2006 à 01:04
Ouhla, Jecapte pas tout maisj'ai saisis le principe, je crois. Oublions zindowz et ses wm_message.
Via le code, est-il possible de récupérer la liste des forms d'une application sans que le nom de ces forms soit écrit en dur ?
De cela découle tout le reste. Suis moi :
Toutes mes forms connaissent l'unit CenterCore (présente dans le use d' Interface, et qui regroupe tout mes types, mes classes, mes variables globales...). A partir de là, de chaque form je peux appeler une procedure présentent dans Centercore. Si j'ai Shout comme suit :
unit Unit_CenterCore;
interface
uses Windows,Graphics,SysUtils,Forms,Math;
procedure Shout(WhatISay : string);
implementation
procedure Shout(WhatISay : string);
var i: integer
begin
for i:=0 to Application.Form.Count-1 do {ici le code qui me turlupine}
Application.Form[i].JustDo(WhatISay) ;
end;
Il me suffit désormais d'avoir par form une fonction JustDo en publique. Toutes recevront ce que j'ai a dire mais seule celles que ca interresse réagiront. Et nul besoin que mes forms se connaissent entre-elles.
Ou bien me goure-je?
Peux tu m'eclairer sur cette énumeration des forms d'une appli ?
DeltaFX
Messages postés449Date d'inscriptionlundi 19 avril 2004StatutMembreDernière intervention 8 avril 20092 19 avril 2006 à 13:57
Et en plus, en n'ayant qu'un timer que je lance au début et que j'éteins a la fin de mon appli , en utilisant timeBeginPeriod(1) et timeEndPeriod(1), je peux forcer timeGetTime à une precision de1ms.
cs_Delphiprog
Messages postés4297Date d'inscriptionsamedi 19 janvier 2002StatutMembreDernière intervention 9 janvier 201332 30 avril 2006 à 13:50
Re-bonjour à tous.
@DeltaFx : je viens de publier, dans la catégorie codes sources, un code et un tuto sur l'utilisation du design pattern observer. Je pense que cela répond parfaitement à ta problématique.
Ne connaissant pas la nature exacte de ton problème, je fournis une application de station météo diffusant les informations aux fiches présentes et enregistrées.
L'utilisation des design patterns est plus universelle que celle des messages Windows qui ne sont utilisables que dans l'environnement...Windows et pas avec tous les langages.
J'espère que tu trouveras la solution à ce qui te préoccupes.
May Delphi be with you !
<hr color="#008000">
Pensez à cliquer sur Réponse acceptée lorsque la réponse vous convient.