建立磁性窗体

时间:2010-05-07 12:20:41  来源:第二电脑网  作者:第二电脑网

  第二电脑网导读:靠近到一定距离以内时会互相粘在一起,或者说相互吸附在一起,然后在拖动主窗体时,粘在其上的其它窗体也一起跟着移动,好像变成了一个窗体。国内的MP3播放器新秀CDOK也实现了这种技巧,而且更绝,把几个窗体粘在一起后,窗体没有主从之分,拖动其中任意一个窗体都会使其它的窗体一起移动。在CSDN上有关怎样设计磁性窗体的帖子非常多,说明这个技巧深得广大程序员的青睐。本文先把几位...
  正文: 一些著名的共享软件不但功能卓著,而且在程序界面的设计技巧上往往领导了一种时尚,WinAmp就是其中的一个代表。WinAmp有两个绝活,一是可以更换窗体的外观,也就是现在俗称的给软件换“皮肤”;另一个即是磁性窗体技巧。
  磁性窗体即若干窗体靠近到一定距离以内时会互相粘在一起,或者说相互吸附在一起,然后在拖动主窗体时,粘在其上的其它窗体也一起跟着移动,好像变成了一个窗体。国内的MP3播放器新秀CDOK也实现了这种技巧,而且更绝,把几个窗体粘在一起后,窗体没有主从之分,拖动其中任意一个窗体都会使其它的窗体一起移动。在CSDN上有关怎样设计磁性窗体的帖子非常多,说明这个技巧深得广大程序员的青睐。
本文先把几位网友的方法略加分析,然后给出我认为比较可行的实现方法和源代码
实现磁性窗体基础上分为两步,第一步是实现当两个窗体靠近到一定距离以内时实现窗体间的粘贴操作,第二步是移动窗体时,同时移动与它粘在一起的其它窗体。

实现窗体的粘贴
  实现粘贴的难点在于什么时候进行这个操作,假设有两个窗体Form1和Form2,移动Form2向Form1靠近,当Form2与Form1的最近距离小于distance时粘贴在一起。显然,应该在移动Form2的过程中进行判断,问题是在程序的什么位置插入判断代码呢?
  CSDN上有人认为可以使用定时器,每隔一定的时间检查各个窗体的位置。这种方法有着明显的弊病,不说定时器要无谓地浪费系统资源,单单它的即时性就难以保证。如果缩短计时值,浪费的CPU资源就更多了,所以我也就不多说了。
合理的方法是利用系统产生的消息,但是利用什么消息呢?窗体在移动时会产生WM_WINDOWPOSCHANGING和WM_MOVING消息,移动结束后会产生WM_WINDOWPOSCHANGED和WM_MOVE消息。WM_WINDOWPOSCHANGING和WM_WINDOWPOSCHANGED消息的参数lParam是结构WINDOWPOS的指针,WINDOWPOS定义如下:
  typedef struct _WINDOWPOS {
   HWND hwnd; // 窗口句炳
   HWND hwndInsertAfter; // 窗口的Z顺序
   int x; // 窗口x坐标
   int y; // 窗口的y坐标
   int cx; // 窗口的宽度
   int cy; // 窗口的高度
   UINT flags; // 标志位,根据它设定窗口的位置
  } WINDOWPOS;
  可以看出,WM_WINDOWPOSCHANGED消息不仅仅在窗口移动时产生,而且在它的Z顺序发生变化时也会产生,包括窗口的显示和隐藏。所以我认为这个消息不是最佳选择。
WM_MOVING和WM_MOVE消息的参数lParam是一个RECT结构指针,与WM_WINDOWPOSCHANGED消息相比较为单纯,我采用的即是这个消息。下面我给出用C++ Builder写的示例程序。
  为了方便程序的阅读,先定义了一个枚举数据类型,表示窗体的粘贴状态。同时定义了一个类,封装了窗体粘贴相关的数据,其中的Enable是为了防止重复进行操作,方法是操作时设置Enable为否,操作结束时恢复为真,而在操作前检查这个标志是否为否,否则直接返回。

图2 窗体的粘贴状态示例

  // 窗体粘贴状态,含义见图2
  enum enumAttachStyle
  {
   AS_NONE, // 没有粘贴
   AS_TOP,
   AS_BOTTOM,
   AS_T_TOP,
   AS_LEFT,
   AS_RIGHT,
   AS_L_LEFT
  };
  // 处理窗体粘贴的类,为了简化,采用了public声明
  class CFormAttachStyle
  {
   public:
   bool Enabled; // 防止重复进行粘贴相关的操作
   HWND AttachTo; // 被粘贴到哪个窗口
   int XStyle; // 左右方向的粘贴状态
   int YStyle; // 上下方向的粘贴状态
   int xPos; // 粘贴到的x坐标
   int yPos; // 粘贴到的y坐标
   CFormAttachStyle() // 初使化数据
   {
     XStyle =AS_NONE;
     YStyle =AS_NONE;
     Enabled=true;
     hAttachTo=NULL;
   }
  };
  函数DistanceIn用于判断两个整数的距离是否在指定范围内:
  // 整数i1和i2的差的绝对值小于i3
  bool DistanceIn(unsigned int i1,unsigned int i2,unsigned int i3)
  {
   if(i1>i2)
   { // 确保i2>=i1;
   int t=i1;
   i1=i2;
   i2=t;
   }
   return i2-i1<=i3;
  }
  //---------------------------------------------------------------------------
  // i1<=i2   bool Mid(unsigned int i1,unsigned int i2,unsigned int i3)
  {
   return ((i1<=i2) && (i2   }
  //---------------------------------------------------------------------------
建立磁性窗体》由第二电脑网原创提供,转载请注明:http://www.002pc.com/master/College/Language/VC/2010-05-07/13901.html

 1/4    1 2 3 4 下一页 尾页


关键字:

关于《建立磁性窗体》文章的评论

站内搜索: 高级搜索

热门搜索:关键字 键盘  Windows PHP CPU style 系统 Google td tr IP function