【问题标题】:C++ Builder XE, Passing and handling user-defined messagesC++ Builder XE,传递和处理用户定义的消息
【发布时间】:2012-06-21 11:15:00
【问题描述】:

我正在尝试学习如何在 VCL 表单应用程序中传递和处理消息。 我在网上挖了一段时间,找到了this

假设我有一个我想使用消息更新的进度条(顺便说一句,如果有任何其他更好的方法,我很想听到它) 所以我做了一个简单的项目来测试这些东西,这就是我所拥有的(RECEIVER 是一个带有进度条的表单的名称,SENDER 是一个用于发送消息的按钮,updBar 是一个更新进度条的函数,123456 是一个消息我要使用的 ID): Unit1.cpp:

#include <vcl.h>
#pragma hdrstop

#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TRECIEVER *RECIEVER;
//---------------------------------------------------------------------------
__fastcall TRECIEVER::TRECIEVER(TComponent* Owner)
    : TForm(Owner)
{
}
void __fastcall TRECIEVER::barUPD(TMessage& msg){
    BAR->StepIt();
}
//---------------------------------------------------------------------------
void __fastcall TRECIEVER::SENDERClick(TObject *Sender)
{
//BAR->StepIt();
PostMessage(FindWindow(0,(wchar_t*)"RECIEVER"),123456,0,0);
}

Unit1.h:

#ifndef Unit1H
#define Unit1H
//---------------------------------------------------------------------------
#include <System.Classes.hpp>
#include <Vcl.Controls.hpp>
#include <Vcl.StdCtrls.hpp>
#include <Vcl.Forms.hpp>
#include <Vcl.ComCtrls.hpp>
//---------------------------------------------------------------------------
class TRECIEVER : public TForm
{
__published:    // IDE-managed Components
    TButton *SENDER;
    TProgressBar *BAR;
    void __fastcall SENDERClick(TObject *Sender);
private:    // User declarations
public:     // User declarations
    void __fastcall barUPD(TMessage& msg);
    __fastcall TRECIEVER(TComponent* Owner);
    BEGIN_MESSAGE_MAP
    MESSAGE_HANDLER(123456,TMessage,barUPD);
    END_MESSAGE_MAP(TForm)
};
//---------------------------------------------------------------------------
extern PACKAGE TRECIEVER *RECIEVER;
//---------------------------------------------------------------------------
#endif

如您所见,我已经为我的消息定义了处理函数和适当的消息处理程序。但是当我通过调试器查看它时(在使用按钮发送消息之后),执行点似乎既不去我的函数也不去处理程序行。 提前致谢

【问题讨论】:

  • 您是否检查过 FindWindow(0,(wchar_t*)"RECIEVER") 的返回值,看看它是否真的找到了什么?我确信有充分的理由,但为什么 wchar_t* 演员??
  • 在您的问题中添加 embarcadero 标签 - 您可能会得到更多回复
  • 感谢您的回复!奇怪的事情,也许是因为我的菜鸟,即使我调用 FindWindow 它实际上仍然调用 FindWindowW,它只接受 wchar_t。我有一种感觉,它是在项目属性的某个地方指定的。我无法理解... HWND aaa=FindWindow(0,(wchar_t*)"RECIEVER"); aaa 是 NULL,我做错了什么?
  • 我已将 Findwindow 调用更改为 HWND_BROADCAST 并且事情按预期工作。如何找到我的表格???
  • 项目选项中的“TCHAR 映射到”设置控制FindWindow() 是否映射到FindWindowA() 或FindWindowW()。但无论哪种方式,(wchar_t*)"RECEIVER" 都是完全错误的。您正在将char[] 类型转换为wchar_t*,这不会产生有效的字符串。您必须改用L"RECEIVER" 来生成有效的wchar_t[]。

标签: c++ c++builder-xe window-messages


【解决方案1】:

你的代码有两个问题:

1) 123456 (0x1E240) 不是有效的用户级消息 ID。高于 0xFFFF 的值由操作系统保留。自定义消息必须在 WM_USER (0x0400 - 0x7FFF)、WM_APP (0x8000 - 0xBFFF) 或 RegisterWindowMessage() (0xC000 - 0xFFFF) 范围内。

2) 您将错误的字符串指针传递给FindWindow()。您正在将 char[] 类型转换为 wchar_t*,这是无效的类型转换。要指定字符串文字应使用wchar_t 而不是char,您必须在文字前面加上L 说明符。或者更笼统地说,当使用任何TCHAR-senstive API(如FindWindow())时,请改用TEXT() 宏。

此外,虽然不是严格意义上的错误,但您应该使用VCL_MESSAGE_HANDLER() 而不是MESSAGE_HANDLER(),只是因为MESSAGE_HANDLER() 由ATL 定义不同。如果您的项目中没有使用 ATL,则不会遇到问题,但最好使用 VCL_MESSAGE_HANDLER() 以确保绝对确定,并记录代码使用的是 VCL 版本的 MESSAGE_HANDLER() 和不是其他版本。

试试这个:

Unit1.h:

#ifndef Unit1H 
#define Unit1H 
//--------------------------------------------------------------------------- 
#include <System.Classes.hpp> 
#include <Vcl.Controls.hpp> 
#include <Vcl.StdCtrls.hpp> 
#include <Vcl.Forms.hpp> 
#include <Vcl.ComCtrls.hpp> 
//--------------------------------------------------------------------------- 
#define WM_BAR_STEP_IT  (WM_USER+1)
//--------------------------------------------------------------------------- 
class TRECIEVER : public TForm 
{ 
__published:    // IDE-managed Components 
    TButton *SENDER; 
    TProgressBar *BAR; 
    void __fastcall SENDERClick(TObject *Sender); 
private:    // User declarations 
    void __fastcall barUPD(TMessage&); 
public:     // User declarations 
    __fastcall TRECIEVER(TComponent* Owner); 
    BEGIN_MESSAGE_MAP 
      VCL_MESSAGE_HANDLER(WM_BAR_STEP_IT, TMessage, barUPD); 
    END_MESSAGE_MAP(TForm) 
}; 
//--------------------------------------------------------------------------- 
extern PACKAGE TRECIEVER *RECIEVER; 
//--------------------------------------------------------------------------- 
#endif 

Unit1.cpp:

#include <vcl.h> 
#pragma hdrstop 

#include "Unit1.h" 
//--------------------------------------------------------------------------- 
#pragma package(smart_init) 
#pragma resource "*.dfm" 
TRECIEVER *RECIEVER; 
//--------------------------------------------------------------------------- 
__fastcall TRECIEVER::TRECIEVER(TComponent* Owner) 
    : TForm(Owner) 
{ 
} 
//--------------------------------------------------------------------------- 
void __fastcall TRECIEVER::barUPD(TMessage&)
{ 
    BAR->StepIt(); 
} 
//--------------------------------------------------------------------------- 
void __fastcall TRECIEVER::SENDERClick(TObject *Sender) 
{ 
    // this assumes the Form's Caption is set to "RECEIVER"
    // also specifying the class type for good measure...
    PostMessage(FindWindow(TEXT("TRECEIVER"), TEXT("RECIEVER")), WM_BAR_STEP_IT, 0, 0); 

    //Alternatively:
    //PostMessage(FindWindowW(ClassName().c_str(), Caption.c_str()), WM_BAR_STEP_IT, 0, 0); 
} 
//--------------------------------------------------------------------------- 

话虽如此,由于消息对应用程序是私有的,因此根本不需要使用FindWindow(),而是使用TForm::Handle 属性。我什至会更进一步,完全摆脱MESSAGE_HANDLER()。该消息对TRECEIVER 的内部来说是私有的,所以它应该保留在那里:

Unit1.h:

#ifndef Unit1H 
#define Unit1H 
//--------------------------------------------------------------------------- 
#include <System.Classes.hpp> 
#include <Vcl.Controls.hpp> 
#include <Vcl.StdCtrls.hpp> 
#include <Vcl.Forms.hpp> 
#include <Vcl.ComCtrls.hpp> 
//--------------------------------------------------------------------------- 
class TRECIEVER : public TForm 
{ 
__published:    // IDE-managed Components 
    TButton *SENDER; 
    TProgressBar *BAR; 
    void __fastcall SENDERClick(TObject *Sender); 
private:    // User declarations 
protected:
    void __fastcall WndProc(TMessage& Message); 
public:     // User declarations 
    __fastcall TRECIEVER(TComponent* Owner); 
}; 
//--------------------------------------------------------------------------- 
extern PACKAGE TRECIEVER *RECIEVER; 
//--------------------------------------------------------------------------- 
#endif 

Unit1.cpp:

#include <vcl.h> 
#pragma hdrstop 

#include "Unit1.h" 
//--------------------------------------------------------------------------- 
#pragma package(smart_init) 
#pragma resource "*.dfm" 
TRECIEVER *RECIEVER; 
#define WM_BAR_STEP_IT  (WM_USER+1)
//--------------------------------------------------------------------------- 
__fastcall TRECIEVER::TRECIEVER(TComponent* Owner) 
    : TForm(Owner) 
{ 
} 
//--------------------------------------------------------------------------- 
void __fastcall TRECIEVER::WndProc(TMessage& Message)
{ 
    if (Message.Msg == WM_BAR_STEP_IT)
        BAR->StepIt(); 
    else
        TForm::WndProc(Message);
} 
//--------------------------------------------------------------------------- 
void __fastcall TRECIEVER::SENDERClick(TObject *Sender) 
{ 
    PostMessage(Handle, WM_BAR_STEP_IT, 0, 0); 
} 
//--------------------------------------------------------------------------- 

如果您希望应用程序的其他部分向 Revceiver 发布消息,您可以为此公开一个公共方法:

Unit1.h:

#ifndef Unit1H 
#define Unit1H 
//--------------------------------------------------------------------------- 
#include <System.Classes.hpp> 
#include <Vcl.Controls.hpp> 
#include <Vcl.StdCtrls.hpp> 
#include <Vcl.Forms.hpp> 
#include <Vcl.ComCtrls.hpp> 
//--------------------------------------------------------------------------- 
class TRECIEVER : public TForm 
{ 
__published:    // IDE-managed Components 
    TButton *SENDER; 
    TProgressBar *BAR; 
    void __fastcall SENDERClick(TObject *Sender); 
private:    // User declarations 
protected:
    void __fastcall WndProc(TMessage& Message); 
public:     // User declarations 
    __fastcall TRECIEVER(TComponent* Owner); 
    void __fastcall PostBarStepIt();
}; 
//--------------------------------------------------------------------------- 
extern PACKAGE TRECIEVER *RECIEVER; 
//--------------------------------------------------------------------------- 
#endif 

Unit1.cpp:

#include <vcl.h> 
#pragma hdrstop 

#include "Unit1.h" 
//--------------------------------------------------------------------------- 
#pragma package(smart_init) 
#pragma resource "*.dfm" 
TRECIEVER *RECIEVER; 
#define WM_BAR_STEP_IT  (WM_USER+1)
//--------------------------------------------------------------------------- 
__fastcall TRECIEVER::TRECIEVER(TComponent* Owner) 
    : TForm(Owner) 
{ 
} 
//--------------------------------------------------------------------------- 
void __fastcall TRECIEVER::WndProc(TMessage& Message)
{ 
    if (Message.Msg == WM_BAR_STEP_IT)
        BAR->StepIt(); 
    else
        TForm::WndProc(Message);
} 
//--------------------------------------------------------------------------- 
void __fastcall TRECIEVER::SENDERClick(TObject *Sender) 
{ 
    PostBarStepIt(); 
} 
//--------------------------------------------------------------------------- 
void __fastcall TRECIEVER::PostBarStepIt() 
{ 
    PostMessage(Handle, WM_BAR_STEP_IT, 0, 0); 
} 
//--------------------------------------------------------------------------- 

SomeOtherFile.cpp:

#include "Unit1.h"

void __fastcall TSomeOtherClass::SomeMethod()
{
    RECIEVER->PostBarStepIt(); 
}

【讨论】:

  • 我还有一个问题:我已经创建了一个表单来作为我程序中多个操作表单的模型(它们将在新操作开始时自行创建并单独运行这个新操作)。我像这样创建它们: TOpWindow* newOp = new TOpWindow(newOp);新操作->显示();但是,当它们被创建时,我无法以任何方式将主窗体带回前面...它获得焦点,控件可用,但它总是在后面,在所有这些新窗体后面...我该如何解决这个问题?跟父母有关系吗?
  • 顺便说一下,所有动态创建的表单都具有相同的优先级,我可以选择它们并将它们放在前面,而不像主表单总是在后面
  • 听起来您将 MainForm 设置为操作表单的PopupParent。阅读文档中的 PopupParent 和 PopupMode 属性。
  • 谢谢,现在都阅读了,问题是这两种形式的 PopupParent 都是空值,而 PopupMode 是 pmNone,而不是 Explicit 或 Auto。是的,情况本身看起来像 pmExplicit 设置在第二种形式上,但它不是。还有什么 pre-Delphi8 行为是什么意思?
  • 在 D8 之前的版本中,表单不处理彼此相关的 z 排序,因此模态表单可能落后于非模态表单,从而使应用程序看起来像挂起,因为用户无法将输入定向到隐藏的模态表单。在 D8 中添加了 PopupParent 属性来解决这个问题。
猜你喜欢
  • 2012-05-24
  • 1970-01-01
  • 2023-04-07
  • 1970-01-01
  • 2019-11-07
  • 1970-01-01
  • 2020-10-19
  • 2017-02-22
  • 2010-11-29
相关资源
最近更新 更多