VCL应用程序何时获得其Application-> MainForm-> Handle?

时间:2017-08-15 20:43:45

标签: c++ c++builder vcl

我的应用程序使用SendStructMessage()中的Message.hpp函数通过传入消息填充一些面板。

SendStructMessage()需要有效的Windows句柄才能发送给。

我已将SendStrucMessage()封装在一个函数中,如下所示:

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;
}

尝试从MainForm的OnShowOnCreate事件中调用此方法并不起作用,因为在任何一种情况下Application->MainForm->Handle仍为NULL。

我的问题是,在VCL应用程序的启动阶段,哪里可以确定实际创建了Application->MainForm->Handle

目前我开始使用Timer来检查有效句​​柄:

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";
        }
    }
}

有更好的方法吗?

1 个答案:

答案 0 :(得分:1)

TWinControl::Handle属性获取器在读取属性时创建新的HWND,如果尚未创建HWND。如果在创建HWND时发生错误,则会抛出异常。

因此,您的!Handle条件始终为false,因为Handle属性永远不会返回NULL(WindowHandle但财产可以。)

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;
}

如果您想检查Handle是否已创建而未实际创建,请使用表单的HandleAllocated()方法:

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;
}

否则,根本不要使用SendMessage() / SendStructMessage()。您可以改为使用表单的Perform()方法,该方法会将消息直接发送到已分配给WindowProc的表单,而不需要任何HWND

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;
}

或者,请考虑从MainForm中删除sendAppMessage()依赖项。您可以发送至Application->Handle,然后让MainForm使用Application->HookMainWindow()注册回调方法。

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;
}