数学建模社区-数学中国

标题: C++BUILDER非可视组件的消息处理技巧 [打印本页]

作者: 韩冰    时间: 2005-1-26 12:24
标题: C++BUILDER非可视组件的消息处理技巧
<>  一个非可视的组件必须对Windows操作系统或用户定义的消息作出响应。然而,由于一个非可视组件没有窗口,因此它也没有窗口句柄,自然它也不能接收到消息,为了解决这一问题,我们的思路是创建一个隐藏的窗口,使非可视组件能够接收到消息。 </P>
" E) v8 T3 j1 ?<>  为了给你的非可视组件创建一个隐藏的窗口,需要有以下: </P>
  F- Y- \  |( u9 b1 I3 [7 `<>  1.一个私有变量型(Private Variable)的HWnd来取得窗口句柄。 </P>
2 d  Q: E$ m; G0 d7 k2 X<>  2.一个用来捕捉窗口发送给组件的函数(a WndProc)。 </P>
5 U5 ~' A! T/ @4 ?$ H0 t$ W, K<>  3.对AllcolateHwnd的调用使之创建窗口句柄并设置WndProc。 </P>
* ^8 W) h* S! E+ Y<>  为了清楚的解释上述思路和展示创建过程,下面我们将以一个具体的实例来说明。 8 g* j% x6 p# `& j) J2 \) w
  首先我们先创建一个新的组件,在C++Builder中,选择FILE|NEW...双击组件图标显示一个新的组件对话框改变Ancestor Type为Tcomponent和Class name为TTest并设置完毕。
, w4 c$ H% Z) g. M( K  然后,切换到新组件的头文件,在类的私有部分(private section)加入以下声明: </P>' c- D) b& f) ^' {8 A) f
<>  HWnd FHandle; 6 W, K  ~8 c9 X( f: E; N
  void—fastcall WndProc(TMessage& Msg); </P>& u0 p: C) [8 a: e  X. X4 d$ t# V6 k
<>  第一行声明了一个调用Fhandle的HWnd变量,这个变量将用于窗口创建后捕获窗口句柄。第二行声明了一个用于接收消息的WndProc函数。这个函数的声明必须加以标识,以便限定它是一个WndProc,然后在类声明Public(公有)部分构造以下声明: </P>5 V2 ^: L3 d' V4 m2 z
<>  Viod DoIt( ); </P>
, H. f7 p$ s- w<>  这个公有函数将被我们用来测试组件,类声明应如下: </P>; ~4 ?) T+ z7 D2 ~9 }- u3 a& z& d
<>  class PACKAGE TTest : public </P>
1 q; [% z- ~3 v3 Y! J<>    TComponent 4 v5 [" {) p# v2 H* Z8 F
  {
; Z2 O4 Y! l* ?6 z" X% F4 e9 A+ m   private: </P>& T' S* W5 H+ ]* i' l
<>   HWnd FHandle; 1 F. f. o# _% \6 D1 e: K7 |
   void—fastcall WndProc(TMessage& Msg); </P>- B3 N/ v9 u& [
<>   protected: </P>
6 z) z2 N2 ~1 k# T9 V" e3 N, s<>   public: </P>+ _0 s# ]% m+ i8 m! H! `8 |
<>      —fastcall TTest(TComponent* Owner); </P>3 ^; g* ?% j1 @. Q/ s- s' y) u
<>     void DoIt( );
$ D! H% C# h# b+ T  
' H2 v$ c) e  t& p+ J" |   —published: </P>- F0 i- Z% E3 T, m$ ]
<>  }; </P>
. N+ }: R3 D, Q& |<>  现在切换到组件的代码单元,将下面一行加入到单元的顶部(在函数上也许是不错的地方) </P>! j& {9 X  W& O( ~4 k  j- G
<>  #define MY—Message.WM_USER+1 </P>! a# x; E# b+ Z4 }2 P
<>  这一行声明了一个在DoIt函数被调用时,组件将发送给它自己的用户自定义消息。此时我们必须为组件分配一个窗口句柄。这个句柄将提供一个隐藏的窗口使我们可以捕捉组件中的消息。找到组件构造代码,加入下面代码: </P>
. M( m1 G9 J9 T" {" B4 F<>  —fastcall Test::Test(TComponent* Owner): TComponent(Owner)
9 h2 l2 S4 p# R) C  _  {   i: x" E9 F3 Y0 F) a, p
  FHandle=AllocateHWnd(WndProc);
$ Q4 S$ ~- h5 J+ R! V( t" e0 p  } </P>
+ P3 x2 E" h: Q7 I( c<>  好,重要的一步已完成,AllocateHWnd函数创建了一个隐藏窗口并且返回它的句柄,注意这里我们为了使Windows知道哪里发来了消息,传递WndProc的地址; </P>
% i: k' q# n5 y<>  现在我们来创建WndProc的函数部分。在源文件中加入: </P>
$ S5 j0 a: W' H' [3 M4 M<>  void—fastcall TTest::WndProc(TMessage& Msg)
! M7 ?/ E* {* B( p! R, t3 `4 g: j  { " c2 j. h, {5 A7 G5 \2 @/ q$ ]
   if (Msg.Msg == MY_MESSAGE)
! `4 l9 e- z% {    MessageBox(0, ″Got here!″, ″Message″, 0);
9 E! m) q" T" k, b- w' Y& I   try {
* g5 ]. A5 u6 q& B4 a         Dispatch(&Msg); 4 c7 R1 G% r0 ?0 K2 O9 p5 X
       } 6 e! |# r9 C/ c% U/ p0 r
   catch (...) { </P>
, T, G- @4 X/ D$ D$ O<>   Application-〉HandleException(this); </P>
9 q5 r! D2 y+ C1 ?+ i. h" {<>   } </P>3 m) I0 T* h8 w! V) @' C
<>  } </P>
* ^0 i! h* j9 T) U1 Q, L) \<>  无论何时Windows发送消息给组件,Windows都会调用这个函数。这部分代码完成了两件事。首先,它检查被接收的消息是否是我们用户自定义的消息。如果是,一个消息框将被显示,你可以看到实际上我们接收到的消息。其次,这段代码传送了系统(或VCL)处理过程中的消息,try/catch块用来保证,如果异常出现,它将成为缺省风格下的句柄。 </P>) F6 d* c* t9 d1 `$ }3 u4 K
<>  概括地说,WndProc函数在为缺省句柄传递所有其他消息,监控了所有客户消息。现在我们创建DoIt函数,完成我们的组件,加入我们创建DoIt函数,完成我们的组件,加入代码: </P>
- c. l! N7 R* ^<P>  void TTest:oIt() </P>
! P6 s* {% y! l- b<P>  { </P>+ E3 M  `. ?; A* q9 C# p
<P>  PostMessage(FHandle, MY—MESSAGE, 0, 0); </P>
* [5 j$ x- J. \: a$ M<P>  } </P>
/ ~6 [) ^+ X4 _' Z0 T2 k' M<P>  这个函数发送一个消息组件的窗口句柄(记住,这个窗口句柄是以前存入到Fhandle数据成品中的)。现在我们已经完成了创建组件选择,用SelectFile|ColseAll来保存我们的工作测试组件。 </P>8 w; V* Q6 k6 E  C/ F8 W
<P>  下一步将测试组件。如果你使用BCB3,那么你必须把组件加入到“包”(Packege)中,然后用Componet|install(可以使用DCLSTD35 Packege来快速测试)。再选择你刚存的TestBCB.Cpp,一旦你安装完成组件后,它将出现在组件板上。双击按钮,为按钮的OnClick事件创建以下代码: </P>' ]+ d) }1 t8 z% I0 I, w* E/ c
<P>   Test1-〉 DoIt( ); </P>9 r! b( E) x" n3 Q  f5 F$ M% p
<P>  现在运行程序,当你点击按钮时,将看到一个消息框显示“Got here". </P>; m) J; C) c, b  T& ]
<P>  ListingA和B包含了头文件和源代码以下列出。 </P>
$ M6 h) ^% d' Z- V<P>  总结:一个可以响应Windows消息的非可视组件有许多用途。最显而易见的就是用来封装某些方面的WindowsAPI。例如:TAPI和WinSock发送消息给事件的指定用户。如果你写的组件封装了一个这样的API。你将需要捕捉Windows发送的消息。而在你的组件中加入隐藏窗口将很好的帮你做到这一点。 </P>
$ h9 Q+ G+ W- E7 A1 ^<P>  以上程序在C++ BUILDER 3.0中调试通过。 </P>
4 d# E" w! W; O7 C+ @+ i<P>
( t2 Y3 H: V* [7 h- \</P>




欢迎光临 数学建模社区-数学中国 (http://www.madio.net/) Powered by Discuz! X2.5