C ++ Builder XE,传递和处理用户定义的消息 [英] C++ Builder XE, Passing and handling user-defined messages

查看:96
本文介绍了C ++ Builder XE,传递和处理用户定义的消息的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试学习如何在VCL表单应用程序中传递和处理消息. 我已经研究了一段时间,发现

I am trying to learn how to pass and handle messages in a VCL forms app. I've been digging the internet for some time and found this

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

Suppose I have a progress bar I want to update using messages (btw if there's any other better way, I am eager to hear it) So I made a simple project to test the stuff and here's what I have (RECEIVER is a name of a form with progress bar, SENDER is a button used to send messages, updBar is a function to update progress bar, and 123456 is a message ID I want to use): 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

如您所见,我已经为消息定义了处理功能和适当的消息处理程序.但是,当我通过调试器进行查看时(使用按钮发送消息后),执行点似乎永远都不会到达我的函数和处理程序行. 预先感谢

As you can see I have defined both the handling function and appropriate message handler for my message. But when I look it through via debugger (after sending the message using the button), the execution point never seems to go to neither my function nor the handler line. Thanks in advance

推荐答案

您的代码有两个问题:

1)123456(0x1E240)不是有效的用户级消息ID.大于0xFFFF的值由OS保留.自定义消息必须在WM_USER(0x0400-0x7FFF),WM_APP(0x8000-0xBFFF)或RegisterWindowMessage()(0xC000-0xFFFF)范围内.

1) 123456 (0x1E240) is not a valid user-level message ID. Values above 0xFFFF are reserved by the OS. Custom messages MUST be in the WM_USER (0x0400 - 0x7FFF), WM_APP (0x8000 - 0xBFFF), or RegisterWindowMessage() (0xC000 - 0xFFFF) ranges.

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

2) you are passing a bad string pointer to FindWindow(). You are type-casting a char[] to a wchar_t*, which is an invalid type-cast. To specify that the string literal should use wchar_t instead of char, you have to prefix the literal with the L specifier instead. Or more generically, when using any TCHAR-senstive API (like FindWindow()), use the TEXT() macro instead.

此外,尽管严格来讲不是错误,但应该使用VCL_MESSAGE_HANDLER()而不是MESSAGE_HANDLER(),仅是因为ATL对MESSAGE_HANDLER()的定义不同.如果您没有在项目中使用ATL,就不会遇到问题,但是最好使用VCL_MESSAGE_HANDLER()只是为了确保完全确定,并记录该代码正在使用VCL的MESSAGE_HANDLER()版本,并且不是其他版本.

In addition, although not strictly an error, you should ue VCL_MESSAGE_HANDLER() instead of MESSAGE_HANDLER(), only because MESSAGE_HANDLER() is defined differently by ATL. If you are not using ATL in your project, you won't run into a problem, but it is better to use VCL_MESSAGE_HANDLER() just to make absolutely sure, and to document that the code is using the VCL's version of MESSAGE_HANDLER() and not some other version.

尝试一下:

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:

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内部人员专用的消息,因此应保留在该位置:

With that said, since the message is private to the app, there is no need to use FindWindow() at all, use the TForm::Handle property instead. And I would even go a step further by getting rid of the MESSAGE_HANDLER() altogether. The message is private to the internals of TRECEIVER, so that is where it should stay:

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:

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,则可以公开一个公共方法:

If you want other pieces of your app to post messages to the Revceiver, you could expose a public method for that:

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:

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:

SomeOtherFile.cpp:

#include "Unit1.h"

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

这篇关于C ++ Builder XE,传递和处理用户定义的消息的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆