我的应用程序使用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的OnShow
或OnCreate
事件中调用此方法并不起作用,因为在任何一种情况下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";
}
}
}
有更好的方法吗?
答案 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;
}