2012-06-21 48 views
1

我想了解如何传递和处理VCL表单应用程序中的消息。 我已经挖上网一段时间后,发现thisC++ Builder XE,传递和处理用户定义的消息

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

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

+0

您是否检查过FindWindow(0,(wchar_t *)“RECIEVER”)的返回值以查看它是否真的找到了什么?我确信有一个很好的理由,但为什么wchar_t * cast? – mathematician1975

+0

同时在您的问题中添加embarcadero标签 - 您可能会得到更多回复 – mathematician1975

+0

感谢您的回复! 奇怪的是,也许是因为即使我调用FindWindow时它仍然会调用FindWindowW,它只接受wchar_t。我有一种感觉,它是在项目属性中的某处指定的。 我无法理解... HWND aaa = FindWindow(0,(wchar_t *)“RECIEVER”);和aaa是NULL,我做错了什么? – Gear54rus

回答

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敏感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 

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,你会暴露为一个公共方法:

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 

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(); 
} 
+0

非常感谢,这是明确的和信息性的 – Gear54rus

+0

我还有一个问题:我已经创建了一个表单作为我的程序中的多个操作表单的模型(他们将创建一个新的操作已经开始,并将运行这个新的操作)。我创建它们是这样的: TOpWindow * newOp = new TOpWindow(newOp); newOp-> Show(); 然而,当它们被创建时,我无法以任何方式将主要表单回到前面......它获得焦点,控件可用,但它总是在后面,在所有这些新形式的后面......如何解决这个问题?这与父母有关系吗? – Gear54rus

+0

顺便说一下,所有动态创建的表单都具有相同的优先级,我可以选择它们,它们来到前面,不像总是在后面的主表单 – Gear54rus