1

我正在使用 RAD Studio 10 处理 Windows VCL 应用程序。我有两个表单,Form1(MainForm in Unit1.cpp)和一个辅助表单Form2(in Unit2.cpp)。我设法嵌入Form2Form1. 这只是说明问题的设置。我的真实项目有多个表格。

关闭时Form2,VCL 触发Form2::OnClose()事件。知道这Form2是在Form1(MainForm)中动态创建的,是否有一个Form1事件会在Form2关闭时触发?或者内部Form1知道Form2正在关闭的东西?

  • 我正在考虑自定义一个事件处理程序,OnChildFormClose但我做不到。
  • 我尝试将要在关闭Form1时执行的代码包装Form2在公共函数中并在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();
}
//-----------------------------------------------------------------------

我可以用一个我们可以动态转换来检查它是否是的OtherFormsonClose(*Sender)事件,或者我错了?我会很感激一些指导。Form1SenderForm2

4

2 回答 2

3

您可以声明一个类型为 的通用事件处理程序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
于 2019-06-10T16:12:28.957 回答
1

好的,我在阅读了这个这个这个这个之后发现了一些有趣的东西。

所以基本上,VCL Delphi/C++Builder 应用程序使用 Windows 窗体消息进行通信,我们可以重写虚函数WndProc来捕获特定消息,但它必须是一些独特的消息,因为 VCL 使用很多消息,如果你不不小心,事情可能会爆炸;这将转换为主窗体上的自定义事件处理程序。

所以我所做的是:

  • 将 MainForm 句柄传递给构造函数中的 Form2,以保存在 Form2 私有 var 上并仅用于消息传递。
  • 生成我用来标记消息以使其突出的特定 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) 范围内。

于 2019-06-10T15:32:04.270 回答