WM_User & Appli multiform ? [Résolu]

DeltaFX 459 Messages postés lundi 19 avril 2004Date d'inscription 8 avril 2009 Dernière intervention - 17 avril 2006 à 16:51 - Dernière réponse : cs_Delphiprog 4580 Messages postés samedi 19 janvier 2002Date d'inscription 9 janvier 2013 Dernière intervention
- 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.
Afficher la suite 

Votre réponse

9 réponses

Meilleure réponse
cs_shining 329 Messages postés lundi 30 décembre 2002Date d'inscription 10 mars 2012 Dernière intervention - 18 avril 2006 à 12:29
3
Merci
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

enumerate all TForms of a Project?
http://www.swissdelphicenter.ch/torry/showcode.php?id=1104

enumerate windows and child windows?
http://www.swissdelphicenter.ch/torry/showcode.php?id=410

Nota : tu peux aussi faire une Interface que tu mettra dans la partie partager par ton Application

IGlobalForm = Interface
procedure DoSomething_1;
end;

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

FindGlobalComponent('Form1')

chai pas si c'est clair lol
@+

Merci cs_shining 3

Avec quelques mots c'est encore mieux Ajouter un commentaire

Codes Sources a aidé 75 internautes ce mois-ci

Commenter la réponse de cs_shining
Meilleure réponse
cs_Delphiprog 4580 Messages postés samedi 19 janvier 2002Date d'inscription 9 janvier 2013 Dernière intervention - 19 avril 2006 à 10:28
3
Merci
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.

Merci cs_Delphiprog 3

Avec quelques mots c'est encore mieux Ajouter un commentaire

Codes Sources a aidé 75 internautes ce mois-ci

Commenter la réponse de cs_Delphiprog
DeltaFX 459 Messages postés lundi 19 avril 2004Date d'inscription 8 avril 2009 Dernière intervention - 17 avril 2006 à 17:11
0
Merci
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.
Commenter la réponse de DeltaFX
cs_shining 329 Messages postés lundi 30 décembre 2002Date d'inscription 10 mars 2012 Dernière intervention - 17 avril 2006 à 17:29
0
Merci
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
Commenter la réponse de cs_shining
DeltaFX 459 Messages postés lundi 19 avril 2004Date d'inscription 8 avril 2009 Dernière intervention - 17 avril 2006 à 18:06
0
Merci
"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.
Commenter la réponse de DeltaFX
cs_shining 329 Messages postés lundi 30 décembre 2002Date d'inscription 10 mars 2012 Dernière intervention - 17 avril 2006 à 19:01
0
Merci
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 !!!
Commenter la réponse de cs_shining
DeltaFX 459 Messages postés lundi 19 avril 2004Date d'inscription 8 avril 2009 Dernière intervention - 18 avril 2006 à 01:04
0
Merci
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 ?
Commenter la réponse de DeltaFX
DeltaFX 459 Messages postés lundi 19 avril 2004Date d'inscription 8 avril 2009 Dernière intervention - 19 avril 2006 à 13:57
0
Merci
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.
Commenter la réponse de DeltaFX
cs_Delphiprog 4580 Messages postés samedi 19 janvier 2002Date d'inscription 9 janvier 2013 Dernière intervention - 30 avril 2006 à 13:50
0
Merci
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.
Commenter la réponse de cs_Delphiprog

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.