1)Add the window to the clipboard viewer chain.

    通过SetClipboardViewer()传入窗口句柄,所有监视剪贴板的窗口句柄会组成一个链表(后来者靠前)。这样当剪贴板内容发生变化时,Windows系统给这些窗口发生消息。剪贴板是系统的一个功能。每个系统功能都有一个消息链。用户程序想要使用某个系统功能,首先是把自己的程序窗口注册到指定功能的消息链上。如果把一个系统功能理解一个设备,就象Windows对文件或者设备都用处理函数。系统中的每个设备都有自己相应的功能。每一个系统的行为都要告诉给需要这个设备的程序。谁需要知道这个知道的行为呢?想要知道这个设备当前行为或者状态的程序容器就要先将自己登记到这个设备的消息链表中。

   每个设备只给已经登记在自己的消息链表中的程序窗口发送消息,表明设备当前的状态或者行为。消息只发给自己消息链中的程序,这个很好理解。把自身行为状态的消息发给不关心这个设备的程序窗口,显然没有任何的意义。从这里可以知道。Windows消息必然有两种,一种是发给指定对象,一种是发给全体所有。从用户的角度来说,就是发给所有需要的用户,或者发给全部的用户。

2)Remove the window from the clipboard viewer chain before itis destroyed.

   首先是登记,将用户的程序窗口登记到某个功能或者设备的消息链表中。与登记对应的操作就是注销。程序窗口已经不需要了解设备或者功能的行为状态时,就要将自己从设备的消息链中删除。与登记过程SetClipboardViewer()对应的注销过程ChangeClipboardChain()。需要了解某个系统功能或者设备的时候,就要将自己的程序窗口登记到设备的消息链中。不再需要知道设备的行为状态时,就要从设备的消息链中把自己的程序窗口删除掉。

3)互动

  为什么要登记?因为想要了解系统某个功能或者设备的行为状态。为什么要注销,因为不再关心指定设备或者某个系统功能的行为状态。在登记与注销的过程之间也就是响应。登记是为了掌握系统设备的某个状态或者行为,并在自己的程序窗口对其做出反映。也就是说当系统设备达到某个状态时,用户的程序窗口要有一些行为或者动作与之发生互动。实际上对于消息的发送与接收,就是发送者与接收者之间的互动。首先是彼此建立联系,然后在某一个特定的时间或者行为或者状态下进行交流,最后结束联系恢复到初始的状态。这样说来初始的状态是没有联系的吗?也不是。初始的状态并非完全的没有联系。

  所谓初始的状态是具有联系机制,也即消息发送与接收,消息链的登记与注销,这些做为联系的机制或者方法或者原则已经建立起来了。做为用户的程序窗口什么时候使用这些机制实现具体的功能,这就要由用户自身来决定。不同的程序开发环境必然提供了不同的方法与系统的消息互动。不过,做为编程环境会有万千的变化,做为系统确只有一定之规。

4)消息链

   用户的程序窗口在将自身登记到消息链中时,是不需要关注消息链的结构变化。这个过程是由系统来完成。问题在于当用户的程序窗口从消息链中退出的时候。每一个程序窗口从消息链退出的时候,消息链的结构都要发生变化。这个时候维护消息链的工作就要有谁来完成呢?一方面是系统自己维护消息链的增减变化,一方面由用户的程序窗口维护消息链的退出行为。那么维护消息链的工作究竟是由系统来完成,还是由用户自己的程序窗口来完成?具体的系统功能或者设备,提供的消息与服务都是不同的,这就要根据实际情况具体的分析。

 

//以下内容在C++Builder编程环境下可用

 1  class TForm1 : public TForm
 2 {
 3    public:        // User declarations
 5       HWND NextViewerHandle;
 6     void __fastcall OnWMDrawClipboard(TMessage &Msg);
 7       void __fastcall OnWMChagecbchain(TMessage &Msg);
 8       BEGIN_MESSAGE_MAP
 9           VCL_MESSAGE_HANDLER(WM_DRAWCLIPBOARD,TMessage,OnWMDrawClipboard);
10           VCL_MESSAGE_HANDLER(WM_CHANGECBCHAIN,TMessage,OnWMChagecbchain);
11       END_MESSAGE_MAP(TForm)
12 }
13 
14 //1)登记消息链
15 void __fastcall TForm1::FormCreate(TObject *Sender)
16 {
17    NextViewerHandle = SetClipboardViewer(Handle);        
18 }
19 //2)注销消息链 20 void __fastcall TForm1::FormDestroy(TObject *Sender) 21 { 22 ChangeClipboardChain (Handle, NextViewerHandle); 23 }
24 //3)消息处理 25 void __fastcall TForm1::OnWMDrawClipboard(TMessage &Msg) 26 { 27 if(NextViewerHandle != NULL ) 28 { 29 SendMessage(NextViewerHandle,Msg.Msg,0,0); 30 } 31 //{写入用户自己的代码} 32 } 33
//4)维护消息链的结构 34 void __fastcall TForm1::OnWMChagecbchain(TMessage &Msg) 35 { 36 if((HWND) Msg.WParam == NextViewerHandle) 37 { 38 NextViewerHandle = (HWND)Msg.LParam; 39 } 40 else if(NextViewerHandle != NULL) 41 { 42 SendMessage(NextViewerHandle, Msg.Msg, Msg.WParam, Msg.LParam); 43 } 44 }