22. september 2005 - 14:53Der er
6 kommentarer og 1 løsning
postmessage og events
Jeg har lavet en program med en masse units. Alle disse units kan sende en masse forskellige beskeder tilbage til hoved programmet, med PostMessage(), hvor jeg fanger beskeden med: Application->OnMessage = AppMessage;
I funktionen AppMessage har jeg så en masse if-else-if sætninger og det kode der skal udføres på den type besked der nu bliver fanget.
Kan man ikke registrere beskederne, så der bliver én funktion til hver besked? fx. OnUnit1TimerTimeOut() OnUnit2MenuClick()
Jeg ved godt at min kode stadig kommer til at fylde det samme, måske end lidt mere. En løsning kunne også være at i AppMessage() kunne kalde funktionen OnUnit1TimerTimeOut(), i stedet for at ha kode til den i AppMesage().
Bare det at skulle registrere alle typerne af beskeder til enkelte funktion ville jo svare meget til sidst nævnte exempel, så i virkligheden ville jeg vel helt at registreringen kunne ske i mine units, så hvis man opretter en funktion i sit hovedprogram der hedder OnUnit1TimerTimeOut(), bliver den kaldt når timeren løber ud, hvis ikke funktionen findes sker der ikke noget.
Sikke en lang smørre, normalt ville jeg nok ikke selv have læst så meget hvis ikke der havde været billeder i :)
Men er der nogen af jeg der har nogle bud ? Jeg bruger forresten bcb6.
Hver message har forhåbentlig et unikt id, så vil jeg da foreslå at når man registrere en message, så give man en funktionspointer med, derefter ligger man det ind i en hashtabel, så key er id og value er funktionspointeren.
Når du så skal håntere din besked, så laver du et lookup i hashtabellen, og få en funktionspointer ud som du så kalder.
Dette gør det også ret nemt at få flere beskeder til at kalde samme metode, evt. kunne du definere at alle funktionspointerne skulle tage en message med som parameter.
Er det sådan noget her du mener ? Jeg syntes det er ret tæt på at være smart, men: Jeg har prøvet at lade TestMouseClick() være en del af min klasse, men så får jeg en fejl: [C++ Error] Unit1.cpp(26): E2034 Cannot convert 'void (* (_closure )(unsigned char,int))(unsigned char,int)' to 'void (*)(unsigned char,int)' Kan jeg slippe for den ?
Det var lige sådan jeg havde tænkt mig det (som i den sidste) :).
Ved desværre ikke hvordan du slipper for den fejlbesked, hvad er det du får ud af dit handles map, tror fejlen ligger der uden lige at kunne sige hvordan den fixes.
#include <iostream> #include <map> class X { public: typedef int (X::*fptr)(int a, int b); std::map <char, fptr>Map; int add(int a, int b) { return a + b; } int sub(int a, int b) { return a - b; }
X() { Map['+'] = &X::add; Map['-'] = &X::sub; }
int Some(int a, int b) { return ((*this).*(Map['+']))(a, b); } };
int main() { X x; std::cout << x.Some(3, 4) << std::endl; }
mr_chaos du skal ha points for at besvare mit spørsmål.
bertelbrander, der er noget med at det er ret svært at få afsat nogle points til dig, men du har helt sikkert fortjent nogle. Så send et svar hvis du aligevel vil ha lidt.
Jeg har rodet en del mere med det her, og har bland andet også prøvet at lave det hele med MESSAGE_MAP. MESSAGE_MAP havde desværre det problem at den ikke fanger en message posted til application, men kun de messages posted til den form de blev oprettet i.
Men, jeg har lavet det som jeg nævnte jeg ønskede, hvor brugeren bare kan oprette de funktioner han/hun skal bruge, og være ligeglad med resten.
Kort sagt har jeg en form med den funktionallitet jeg ønsker, virtuel, og jeg nedarver fra i mit egentlige projekt.
Det er vidst bedre med lidt exempler. Her er platformen: class TPlatForm : public TForm { public: //Event map, all events will be registred in this table typedef void __fastcall(TPlatForm::*EventHandle)(unsigned char FixSite, int action); map<int, EventHandle>handles;
//constructor __fastcall TPlatForm(TComponent* Owner):TForm(Owner) { //set up application event handler Application->OnMessage = AppMessage; //Register all the known messages handles[RegisterWindowMessage("FixSiteTimerTimeOut")] = &TPlatForm::FixSiteTimerTimeOut; };
Min hoved form starter så med at arve fra TPlatForm class TMainForm : public TPlatForm { ...
Hvis nu jeg vil ha en håndtering af TimeOut tingen, kan man bare lave en funktion til det: void __fastcall TMainForm::FixSiteTimerTimeOut(fsFixSite FixSite, int progress) { switch(progress) ... Hvis ikke man lave den funktion sker der bare ikke noget når timeren løber ud.
Synes godt om
Ny brugerNybegynder
Din løsning...
Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.