VCL 应用程序何时获取其应用程序>主窗体>句柄?

When does a VCL application get its Application->MainForm->Handle?

本文关键字:gt 应用程序 窗体 句柄 获取 VCL 何时      更新时间:2023-10-16

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

SendStructMessage()需要一个有效的窗口句柄才能发送到。

我将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

目前,我启动一个计时器,检查有效的句柄:

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

有没有更好的方法?

如果尚未创建HWND,则TWinControl::Handle属性 getter 会在读取属性时创建新HWND。 如果在创建HWND时发生错误,将引发异常。

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

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而未实际创建它,请使用 Form 的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;
}

或者,考虑从sendAppMessage()中删除MainForm依赖项。 您可以改为发送到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;
}