VCL 应用程序何时获取其 Application->MainForm->Handle?
When does a VCL application get its Application->MainForm->Handle?
我的应用程序使用 Message.hpp
中的 SendStructMessage()
函数通过传入消息填充某些面板。
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
?
目前我启动了一个计时器来检查有效句柄:
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";
}
}
}
有没有更好的方法?
TWinControl::Handle
属性 getter 在读取 属性 时创建一个新的 HWND
,如果 HWND
没有尚未创建。如果在创建 HWND
时发生错误,将抛出异常。
所以,你的!Handle
条件总是为假,因为Handle
属性永远不会 return 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;
}
或者,考虑从 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;
}
我的应用程序使用 Message.hpp
中的 SendStructMessage()
函数通过传入消息填充某些面板。
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
?
目前我启动了一个计时器来检查有效句柄:
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";
}
}
}
有没有更好的方法?
TWinControl::Handle
属性 getter 在读取 属性 时创建一个新的 HWND
,如果 HWND
没有尚未创建。如果在创建 HWND
时发生错误,将抛出异常。
所以,你的!Handle
条件总是为假,因为Handle
属性永远不会 return 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;
}
或者,考虑从 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;
}