辅助 TForm 是否可以在关闭时通知 MainForm?
Can a secondary TForm notify the MainForm when it is closing?
我正在使用 RAD Studio 10 开发 Windows VCL 应用程序。我有两个表单,Form1
(Unit1.cpp
中的 MainForm)和一个辅助 Form2
(Unit2.cpp
中)。我设法将 Form2
嵌入到 Form1
中。这只是一个说明问题的设置。我的真实项目有多个Form。
关闭Form2
时,VCL触发Form2::OnClose()
事件。知道 Form2
是在 Form1
(MainForm)中动态创建的,是否有一个 Form1
事件会在 Form2
关闭时触发?或者在 Form1
中知道 Form2
正在关闭?
- 我想定制一个像
OnChildFormClose
这样的事件处理程序,但我做不到。
- 当
Form2
在 public 函数中关闭时,我试图将我想在 Form1
上执行的代码包装起来,并在 Form2::OnClose()
事件中调用它,它在某种程度上起到了作用,但如果你有多个表单,这不是一个好方法。
//FROM THE unit1.cpp
#include <vcl.h>
#pragma hdrstop
#include "Unit1.h"
#include "Unit2.h"
//-----------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//-----------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
}
//-----------------------------------------------------------------------
void __fastcall TForm1::FormCreate(TObject *Sender)
{
TForm2 *form2 = new TForm2(this);
form2->ManualDock(container);
form2->Show();
}
//FROM unit2.cpp
#include <vcl.h>
#pragma hdrstop
#include "Unit2.h"
//-----------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm2 *Form2;
//-----------------------------------------------------------------------
__fastcall TForm2::TForm2(TComponent* Owner)
: TForm(Owner)
{
}
//-----------------------------------------------------------------------
void __fastcall TForm2::Button1Click(TObject *Sender)
{
Close();
}
//-----------------------------------------------------------------------
我可以在 Form1
中实现类似 OtherFormsonClose(*Sender)
事件的东西吗?我们可以动态转换以检查它是否是 Form2
,或者我可能是 Sender
错误的?我将不胜感激。
好的,阅读后我发现了一些有趣的东西 this, this, this, and this。
所以基本上,VCL Delphi/C++Builder 应用程序使用 Windows Form Messages 进行通信,我们可以覆盖虚函数 WndProc
来捕获特定消息,但它必须是一些独特的消息,因为 VCL 使用了很多消息,如果你不小心,事情可能会爆炸;这将转换为主窗体上的自定义事件处理程序。
所以我所做的是:
- 在构造函数中将 MainForm 句柄传递给 Form2,以保存在 Form2 私有变量中并仅用于消息传递。
- 生成我用来标记消息以使其脱颖而出的特定 ID
- 覆盖
WndProc
并过滤具有特定 ID 的消息,以便我们知道 Form2 正在关闭。
测试成功,也许有人有更好的主意。
//From unit2.h---------------------------------------------------------
class TForm2 : public TForm
{
__published: // IDE-managed Components
TButton *Button1;
void __fastcall Button1Click(TObject *Sender);
void __fastcall FormClose(TObject *Sender, TCloseAction &Action);
private: // User declarations
HWND mfhandle;
public: // User declarations
__fastcall TForm2(TComponent* Owner, HWND mainformhandle);
};
//From unit2.cpp---------------------------------------------------------
#include <vcl.h>
#pragma hdrstop
#include "Unit2.h"
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm2 *Form2;
const UINT uiMyCopyDataID = RegisterWindowMessage(TEXT("MyCopyDataID"));
__fastcall TForm2::TForm2(TComponent* Owner,HWND mainformhandle)
: TForm(Owner)
{
mfhandle = mainformhandle;
}
void __fastcall TForm2::Button1Click(TObject *Sender)
{
Close();
}
void __fastcall TForm2::FormClose(TObject *Sender, TCloseAction &Action)
{
//Notify the mainForm and say Hey I am closing now
PostMessage(mfhandle, uiMyCopyDataID, 0, 0);
}
//From unit1.h---------------------------------------------------------
class TForm1 : public TForm
{
__published: // IDE-managed Components
TPanel *container;
void __fastcall FormCreate(TObject *Sender);
void __fastcall FormUnDock(TObject *Sender, TControl *Client, TWinControl *NewTarget,
bool &Allow);
private: // User declarations
protected:
void __fastcall TForm1::WndProc(TMessage &Message); //Added THIS
public: // User declarations
__fastcall TForm1(TComponent* Owner);
};
//From unit1.cpp-------------------------------------------------------
const UINT uiMyCopyDataID = RegisterWindowMessage(TEXT("MyCopyDataID"));
void __fastcall TForm1::WndProc(TMessage &Message)
{
if (Message.Msg == uiMyCopyDataID)
{
//Do SomeThing here
ShowMessage("Form2 is closing");
}
TForm::WndProc(Message);
}
好的,到目前为止一切正常,自定义消息必须在 WM_USER (0x0400 - 0x7FFF) 范围内。
您可以声明类型为 TCloseEvent
的通用事件处理程序,例如OtherFormClose(TObject *Sender, TCloseAction &Action);
在主窗体中:
private: // User declarations
void __fastcall TForm1::OtherFormClose(TObject *Sender, TCloseAction &Action);
实施
void __fastcall TForm1::OtherFormClose(TObject *Sender, TCloseAction &Action)
{
Action = caFree;
TForm2 *f2 = dynamic_cast<TForm2 *>(Sender);
if (f2) {
ShowMessage(String("Form2 closing")); //Do stuff
}
}
(或使用Sender
检查哪个表格)
然后当您在代码中创建其他表单时,例如Form2
,你分配
TForm2 *form2 = new TForm2(this);
form2->OnClose = OtherFormClose;
// etc
我正在使用 RAD Studio 10 开发 Windows VCL 应用程序。我有两个表单,Form1
(Unit1.cpp
中的 MainForm)和一个辅助 Form2
(Unit2.cpp
中)。我设法将 Form2
嵌入到 Form1
中。这只是一个说明问题的设置。我的真实项目有多个Form。
关闭Form2
时,VCL触发Form2::OnClose()
事件。知道 Form2
是在 Form1
(MainForm)中动态创建的,是否有一个 Form1
事件会在 Form2
关闭时触发?或者在 Form1
中知道 Form2
正在关闭?
- 我想定制一个像
OnChildFormClose
这样的事件处理程序,但我做不到。 - 当
Form2
在 public 函数中关闭时,我试图将我想在Form1
上执行的代码包装起来,并在Form2::OnClose()
事件中调用它,它在某种程度上起到了作用,但如果你有多个表单,这不是一个好方法。
//FROM THE unit1.cpp
#include <vcl.h>
#pragma hdrstop
#include "Unit1.h"
#include "Unit2.h"
//-----------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//-----------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
}
//-----------------------------------------------------------------------
void __fastcall TForm1::FormCreate(TObject *Sender)
{
TForm2 *form2 = new TForm2(this);
form2->ManualDock(container);
form2->Show();
}
//FROM unit2.cpp
#include <vcl.h>
#pragma hdrstop
#include "Unit2.h"
//-----------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm2 *Form2;
//-----------------------------------------------------------------------
__fastcall TForm2::TForm2(TComponent* Owner)
: TForm(Owner)
{
}
//-----------------------------------------------------------------------
void __fastcall TForm2::Button1Click(TObject *Sender)
{
Close();
}
//-----------------------------------------------------------------------
我可以在 Form1
中实现类似 OtherFormsonClose(*Sender)
事件的东西吗?我们可以动态转换以检查它是否是 Form2
,或者我可能是 Sender
错误的?我将不胜感激。
好的,阅读后我发现了一些有趣的东西 this, this, this, and this。
所以基本上,VCL Delphi/C++Builder 应用程序使用 Windows Form Messages 进行通信,我们可以覆盖虚函数 WndProc
来捕获特定消息,但它必须是一些独特的消息,因为 VCL 使用了很多消息,如果你不小心,事情可能会爆炸;这将转换为主窗体上的自定义事件处理程序。
所以我所做的是:
- 在构造函数中将 MainForm 句柄传递给 Form2,以保存在 Form2 私有变量中并仅用于消息传递。
- 生成我用来标记消息以使其脱颖而出的特定 ID
- 覆盖
WndProc
并过滤具有特定 ID 的消息,以便我们知道 Form2 正在关闭。
测试成功,也许有人有更好的主意。
//From unit2.h---------------------------------------------------------
class TForm2 : public TForm
{
__published: // IDE-managed Components
TButton *Button1;
void __fastcall Button1Click(TObject *Sender);
void __fastcall FormClose(TObject *Sender, TCloseAction &Action);
private: // User declarations
HWND mfhandle;
public: // User declarations
__fastcall TForm2(TComponent* Owner, HWND mainformhandle);
};
//From unit2.cpp---------------------------------------------------------
#include <vcl.h>
#pragma hdrstop
#include "Unit2.h"
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm2 *Form2;
const UINT uiMyCopyDataID = RegisterWindowMessage(TEXT("MyCopyDataID"));
__fastcall TForm2::TForm2(TComponent* Owner,HWND mainformhandle)
: TForm(Owner)
{
mfhandle = mainformhandle;
}
void __fastcall TForm2::Button1Click(TObject *Sender)
{
Close();
}
void __fastcall TForm2::FormClose(TObject *Sender, TCloseAction &Action)
{
//Notify the mainForm and say Hey I am closing now
PostMessage(mfhandle, uiMyCopyDataID, 0, 0);
}
//From unit1.h---------------------------------------------------------
class TForm1 : public TForm
{
__published: // IDE-managed Components
TPanel *container;
void __fastcall FormCreate(TObject *Sender);
void __fastcall FormUnDock(TObject *Sender, TControl *Client, TWinControl *NewTarget,
bool &Allow);
private: // User declarations
protected:
void __fastcall TForm1::WndProc(TMessage &Message); //Added THIS
public: // User declarations
__fastcall TForm1(TComponent* Owner);
};
//From unit1.cpp-------------------------------------------------------
const UINT uiMyCopyDataID = RegisterWindowMessage(TEXT("MyCopyDataID"));
void __fastcall TForm1::WndProc(TMessage &Message)
{
if (Message.Msg == uiMyCopyDataID)
{
//Do SomeThing here
ShowMessage("Form2 is closing");
}
TForm::WndProc(Message);
}
好的,到目前为止一切正常,自定义消息必须在 WM_USER (0x0400 - 0x7FFF) 范围内。
您可以声明类型为 TCloseEvent
的通用事件处理程序,例如OtherFormClose(TObject *Sender, TCloseAction &Action);
在主窗体中:
private: // User declarations
void __fastcall TForm1::OtherFormClose(TObject *Sender, TCloseAction &Action);
实施
void __fastcall TForm1::OtherFormClose(TObject *Sender, TCloseAction &Action)
{
Action = caFree;
TForm2 *f2 = dynamic_cast<TForm2 *>(Sender);
if (f2) {
ShowMessage(String("Form2 closing")); //Do stuff
}
}
(或使用Sender
检查哪个表格)
然后当您在代码中创建其他表单时,例如Form2
,你分配
TForm2 *form2 = new TForm2(this);
form2->OnClose = OtherFormClose;
// etc