2017-08-15 2 views
3

Meine Anwendung füllt einige Panels mithilfe eingehender Nachrichten unter Verwendung der SendStructMessage()-Funktion in Message.hpp.Wann erhält eine VCL-Anwendung ihr Application-> MainForm-> Handle?

SendStructMessage() brauchen ein gültiges Windows-Handle zu senden.

Ich habe die SendStrucMessage() in einer Funktion, wie das verkapselte:

bool sendAppMessage(ApplicationMessageEnum msgID, void* s) 
{ 
    if(!Application || !Application->MainForm || !Application->MainForm->Handle) 
    { 
     Log(lError) << "Failed to get a valid handle when trying to send application message"; 
     return false; 
    } 
    HWND h = Application->MainForm->Handle; 

    AppMessageStruct data; 
    data.mMessageEnum = msgID; 
    data.mData = s; 

    LRESULT res = SendStructMessage(h, UWM_MESSAGE, 0, &data); 
    if(res) 
    { 
     Log(lError) << "Sending message: "<<msgID<<" was unsuccesful"; 
     return false; 
    } 

    return true; 
} 

Der Versuch, diese aus rufen entweder die des Main OnShow oder OnCreate Ereignis nicht funktioniert, wie sie in jedem Fall die Application->MainForm->Handle noch NULL ist.

Meine Frage ist, in einer Startphase der VCL-Anwendung, wo kann man sicher sein, dass die Application->MainForm->Handle tatsächlich erstellt wird?

Derzeit treten ich einen Timer Überprüfung für einen gültigen Handle aus:

void __fastcall TMain::WaitForHandleTimerTimer(TObject *Sender) 
{ 
    if(Application->MainForm->Handle) 
    { 
     WaitForHandleTimer->Enabled = false; 

     //Send a message to main ui to update sequence shortcuts 
     if(sendAppMessage(abSequencerUpdate) != true) 
     { 
      Log(lDebug)<<"Sending sequencer update to UI was unsuccesful"; 
     } 
    } 
} 

Gibt es einen besseren Weg?

+1

[Diese Frage] (https://Stackoverflow.com/q/37614161/62576) und seine Kommentare (sowie die Antwort) können helfen. Während es mit Delphi markiert ist, ist die VCL vollständig in dieser Sprache geschrieben und es gelten die gleichen Informationen. Die Kommentare zu der Frage enthalten einige andere Links, die hier relevant sind und äußerst nützlich sein sollten. –

Antwort

1

Die Eigenschaft Getter erstellt eine neue HWND zum Zeitpunkt der Eigenschaft gelesen wird, wenn eine HWND noch nicht erstellt wurde. Wenn beim Erstellen der HWND ein Fehler auftritt, wird eine Ausnahme ausgelöst.

Also, Ihr !Handle Zustand wird immer falsch sein, weil die Handle Eigenschaft kann nie Rückkehr NULL (die WindowHandle Eigenschaft kann, obwohl).

bool sendAppMessage(ApplicationMessageEnum msgID, void* s) 
{ 
    if (!((Application) && (Application->MainForm))) 
    { 
     Log(lError) << "Failed to get a valid handle when trying to send application message"; 
     return false; 
    } 

    AppMessageStruct data; 
    data.mMessageEnum = msgID; 
    data.mData = s; 

    LRESULT res = SendStructMessage(Application->MainForm->Handle, UWM_MESSAGE, 0, &data); 
    if (res) 
    { 
     Log(lError) << "Sending message: " << msgID << " was unsuccesful"; 
     return false; 
    } 

    return true; 
} 

Wenn Sie überprüfen wollen, ob die Handle, ohne es wirklich zu schaffen erstellt wurde, verwenden Sie die HandleAllocated() Methode der Form:

bool sendAppMessage(ApplicationMessageEnum msgID, void* s) 
{ 
    if (!((Application) && (Application->MainForm) && (Application->MainForm->HandleAllocated()))) 
    { 
     Log(lError) << "Failed to get a valid handle when trying to send application message"; 
     return false; 
    } 

    AppMessageStruct data; 
    data.mMessageEnum = msgID; 
    data.mData = s; 

    LRESULT res = SendStructMessage(Application->MainForm->Handle, UWM_MESSAGE, 0, &data); 
    if (res) 
    { 
     Log(lError) << "Sending message: " << msgID << " was unsuccesful"; 
     return false; 
    } 

    return true; 
} 

Ansonsten verwenden überhaupt nicht SendMessage()/SendStructMessage(). Sie können die stattdessen Perform() Methode des Formulars aufrufen, die die Nachricht an das Formular zugewiesenen WindowProc direkt liefern jede HWND überhaupt, ohne dass:

bool sendAppMessage(ApplicationMessageEnum msgID, void* s) 
{ 
    if (!((Application) && (Application->MainForm)) 
    { 
     Log(lError) << "Failed to get a valid handle when trying to send application message"; 
     return false; 
    } 

    AppMessageStruct data; 
    data.mMessageEnum = msgID; 
    data.mData = s; 

    LRESULT res = Application->MainForm->Perform(UWM_MESSAGE, 0, (LPARAM)&data); 
    if (res) 
    { 
     Log(lError) << "Sending message: " << msgID << " was unsuccesful"; 
     return false; 
    } 

    return true; 
} 

Alternativ betrachten die MainForm Abhängigkeit von sendAppMessage() zu entfernen. Sie können stattdessen an Application->Handle senden und dann die MainForm eine Rückrufmethode registrieren, die Application->HookMainWindow() verwendet.

bool sendAppMessage(ApplicationMessageEnum msgID, void* s) 
{ 
    if (!((Application) && (Application->Handle)) 
    { 
     Log(lError) << "Failed to get a valid handle when trying to send application message"; 
     return false; 
    } 

    AppMessageStruct data; 
    data.mMessageEnum = msgID; 
    data.mData = s; 

    LRESULT res = SendStructMessage(Application->Handle, UWM_MESSAGE, 0, &data); 
    if (res) 
    { 
     Log(lError) << "Sending message: " << msgID << " was unsuccesful"; 
     return false; 
    } 

    return true; 
} 

__fastcall TMainForm::TMainForm(TComponent *Owner) 
    : TForm(Owner) 
{ 
    Application->HookMainWindow(&AppMessage); 
} 

__fastcall TMainForm::~TMainForm() 
{ 
    Application->UnhookMainWindow(&AppMessage); 
} 

bool __fastcall TMainForm::AppMessage(TMessage &Message) 
{ 
    if (Message.Msg == UWM_MESSAGE) 
    { 
     WindowProc(Message); 
     return true; 
    } 
    return false; 
} 
+0

Vorgeschlagene alternative Messaging-Mechanismen scheinen wirklich wertvoll zu sein! Vor allem die Perform-Methode. –

Verwandte Themen