Zeiger in Messages übergeben

Allgemein

Pointer in Messages weitergeben ist ganz einfach, wenn man folgendes beachtet:

SendMessage: Referenzierung von Objekten auf dem Stack, im statischen Speicher und auf dem Heap möglich
PostMessage: nur Referenzierung von Objekten im statischen Speicher und auf dem Heap möglich

Sender

// Handle auf eine bel. Form
HANDLE hForm = ...;

// einen Dateinamen zusammenbauen
char pcFileName[MAX_PATH];
strcpy(pcFileName, "c:\\test.txt");

// Nachricht WM_MAKESCREENSHOT absetzen und auf Ausführung warten
SendMessage(hMainForm, WM_MAKESCREENSHOT, 0, (LPARAM)&pcFileName);

Empfänger

void TfrmMain::MMakeScreenShot(TMessage M)
{
     TForm::Dispatch(&M);
     
     // Zeiger in LParam auslesen und in den gewünschten Typ wandeln
     char *pcFileName = (char*)M.LParam;
     AnsiString sFileName(pcFileName);

     MessageDlg(sFileName, mtInformation, TMsgDlgButtons() << mbOK, 0);
}

Anwendung von der Beendigung von Windows benachrichtigen

  • Auswerten der Windowsmessage WM_QUERYENDSESSION, die vom System vor dem Herunterfahren an alle Applikationen gesendet wird
  • Sobald diese Message empfangen wird, muss sich die Anwendung z.B. mit Close(); beenden, damit wird auch der Destruktor ordnungsgemass aufgerufen
// *.h: 

protected:
BEGIN_MESSAGE_MAP

    VCL_MESSAGE_HANDLER(WM_QUERYENDSESSION, TMessage, OnShutdown)

END_MESSAGE_MAP(TForm)

void __fastcall OnShutdown(TMessage & Msg);

...

// *.cpp: 

void __fastcall TForm1::OnShutdown(TMessage &Msg)
{
    // irgenwelcher Code, z.b: offene Dateien schließen

    TObject:: Dispatch(&Msg);
    Close();
}

Grundgerüst für die Verwendung von VCL Messages

  • als erstes im public-Teil der Form-Headerdatei (von der Form, in der die Messages empfangen werden sollen) Messagehandler (Makro), die zugehörigen Funktionen und die Messages definieren
#define WM_TEST_MSG 10000 // Wert für die Message festlegen

class TForm1 : public TForm
{
    __published:
    TButton *Button1;
    TButton *Button2;
    void __fastcall Button1Click(TObject *Sender);
    void __fastcall Button2Click(TObject *Sender);

    private: // durch die Message aufgerufene Funktion
    void __fastcall TestFunktion(TMessage M);

    public:
    __fastcall TForm1(TComponent* Owner);
    // Message-Map verwaltet die eigentlichen Messages
    BEGIN_MESSAGE_MAP

        // Aufruf: VCL_MESSAGE_HANDLER(Message-Id, Typ, selbstdefinierte Aufruf-Funktion)
        VCL_MESSAGE_HANDLER(WM_TEST_MSG, TMessage, TestFunktion); 

    END_MESSAGE_MAP(TForm) // "TForm" bedeutet, dass der Handler zum Standard-TForm Messagehandler hinzugefügt wird 
};
  • in der Form-CPP die Messagefunktionen programmieren, mit WParam und LParam können beliebige Parameter über die Message mitgeschickt werden
void __fastcall TForm1::TestFunktion(TMessage M)
{
    TForm::Dispatch(&amp;M);

    AnsiString sAusgabeText = &quot;Message angekommen, WParam=&quot;+IntToStr(M.WParam)+&quot; LParam=&quot;+IntToStr(M.LParam);

    ShowMessage(sAusgabeText); 
} 
// Aufrufen (Auslösen) der Message, Typ 1: 
void __fastcall  TForm1::Button1Click(TObject *Sender)
{
    // Message &quot;WM_TEST_MSG&quot; an Form1 senden
    // und auf deren Ausführung warten
    // WParam = 0
    // LParam = 0
    SendMessage(this->Handle, WM_TEST_MSG, 0, 0); 
}
// Aufrufen (Auslösen) der Message, Typ 2:
void __fastcall  TForm1::Button2Click(TObject *Sender)
{
    // Message &quot;WM_TEST_MSG&quot; an Form1 in den MessageQueue
    // senden und sofort zurückkehren (nicht auf die Ausführung warten)
    // WParam = 0
    // LParam = 0
    PostMessage(this->Handle, WM_TEST_MSG, 0, 0); 
}