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
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
There are two problems with your code:
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), orRegisterWindowMessage()
(0xC000 - 0xFFFF) ranges.2) you are passing a bad string pointer to
FindWindow()
. You are type-casting achar[]
to awchar_t*
, which is an invalid type-cast. To specify that the string literal should usewchar_t
instead ofchar
, you have to prefix the literal with theL
specifier instead. Or more generically, when using anyTCHAR
-senstive API (likeFindWindow()
), use theTEXT()
macro instead.In addition, although not strictly an error, you should ue
VCL_MESSAGE_HANDLER()
instead ofMESSAGE_HANDLER()
, only becauseMESSAGE_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 useVCL_MESSAGE_HANDLER()
just to make absolutely sure, and to document that the code is using the VCL's version ofMESSAGE_HANDLER()
and not some other version.Try this:
Unit1.h:
Unit1.cpp:
With that said, since the message is private to the app, there is no need to use
FindWindow()
at all, use theTForm::Handle
property instead. And I would even go a step further by getting rid of theMESSAGE_HANDLER()
altogether. The message is private to the internals ofTRECEIVER
, so that is where it should stay:Unit1.h:
Unit1.cpp:
If you want other pieces of your app to post messages to the Revceiver, you could expose a public method for that:
Unit1.h:
Unit1.cpp:
SomeOtherFile.cpp: