1

我正在尝试学习如何在 VCL 表单应用程序中传递和处理消息。我已经在互联网上挖掘了一段时间,发现了这个

假设我有一个进度条,我想使用消息更新(顺便说一句,如果有任何其他更好的方法,我很想听到它)所以我做了一个简单的项目来测试这些东西,这就是我所拥有的(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);
}

单元1.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

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

4

1 回答 1

3

您的代码有两个问题:

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

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

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

尝试这个:

单元1.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 

单元1.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,因此它应该保留在其中:

单元1.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 

单元1.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 发布消息,您可以为此公开一个公共方法:

单元1.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 

单元1.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(); 
}
于 2012-06-21T22:18:57.327 回答