




已阅读5页,还剩3页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
建立磁性窗体.txt爱人是路,朋友是树,人生只有一条路,一条路上多棵树,有钱的时候莫忘路,缺钱的时候靠靠树,幸福的时候别迷路,休息的时候靠靠树!建立磁性窗体 关键字:磁性窗体,吸附,WM_WINDOWPOSCHANGING,WM_MOVING,粘贴,行舟 作者:行舟 更新:2003-11-12 浏览:9083原始URL: /myarticle/showarticle.asp?classid=1&page=1&sort=&id=93源程序 : /myarticle/attachment/WndAttach.zip 一些著名的共享软件不但功能卓著,而且在程序界面的设计技巧上往往领导了一种时尚,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(i1i2) / 确保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 (i1Tag; if(MyStyle=NULL)return false; / 这个窗体不支持粘贴 /准备粘贴到的窗体的位置 RECT rMain; GetWindowRect(Form-Handle,&rMain); MyStyle-AttachTo=NULL; MyStyle-yPos=r-top; MyStyle-xPos=r-left; / 上下方向判断 MyStyle-YStyle=AS_NONE; if( Mid(rMain.left,r-left,rMain.right) | Mid(r-left,rMain.left,r-right) | (MyStyle-XStyle!=AS_NONE) if(DistanceIn(r-top,rMain.bottom,space) MyStyle-YStyle=AS_BOTTOM; MyStyle-yPos=rMain.bottom; else if(DistanceIn(r-top,rMain.top,space) MyStyle-YStyle=AS_TOP; MyStyle-yPos=rMain.top; else if(DistanceIn(r-bottom,rMain.top,space) MyStyle-YStyle=AS_T_TOP; MyStyle-yPos=rMain.top-(r-bottom-r-top); / 左右方向判断 MyStyle-XStyle=AS_NONE; if( Mid(rMain.top,r-top,rMain.bottom) | Mid(r-top,rMain.top,r-bottom) | (MyStyle-YStyle!=AS_NONE) if(DistanceIn(r-left,rMain.left,space) MyStyle-XStyle=AS_LEFT; MyStyle-xPos=rMain.left; else if(DistanceIn(r-left,rMain.right,space) MyStyle-XStyle=AS_RIGHT; MyStyle-xPos=rMain.right; else if(DistanceIn(r-right,rMain.left,space) MyStyle-XStyle=AS_L_LEFT; MyStyle-xPos=rMain.left-(r-right-r-left); My-Left=MyStyle-xPos; My-Top=MyStyle-yPos; if(MyStyle-XStyle!=AS_NONE | MyStyle-YStyle!=AS_NONE) / 粘贴成功/ 本文转自 C+Builder研究 - /article.asp?i=580&d=5wfrd7 MyStyle-AttachTo= Form-Handle; return bool(MyStyle-AttachTo); 函数Do_WM_MOVING在消息循环中处理WM_MOVING时调用,参数My为处理消息的窗体,Msg为消息参数。 / 处理WM_MOVING事件 void Do_WM_MOVING(TForm *My,TMessage &Msg) CFormAttachStyle *MyStyle=(CFormAttachStyle *)My-Tag; if(MyStyle & MyStyle-Enabled) MyStyle-Enabled=false; / 防止重复操作 RECT *r=(RECT *)Msg.LParam ; / 处理粘贴,这里只对粘贴到主窗体进行判断 TForm *FormApplication-MainForm; AttachToForm(My,r,12); / 检查是否可以粘贴窗体 MyStyle-Enabled=true; / 恢复操作状态 Msg.Result=0; / 通知系统,消息已经处理 实现窗体的关联移动 与处理窗体粘贴相比,关联窗体的难度小一些。但是从CSDN上的帖子看,采用的方法都单调而且不佳,我都不推荐。 比较直观的方法是使用窗体的MOUSEDOWN、MOUSEMOVE和MOUSEUP事件,先定义一个标志鼠标是否按下的变量: bool bMouseDown; 在MOUSEDOWN事件中设置: bMouseDown=true; 在MOUSEUP事件中设置: bMouseDown=false; 在MOUSEMOVE事件中作如下处理: if(bMouseDown) / 移动当前窗体 / 计算窗体移动的位移 int dx; int dy; / 计算出dx和dy / 移动其它粘贴到当前窗体的窗体 这个方法的最明显的问题有两个:1、鼠标在窗体上的控件上按下时,不能收到窗体的MOUSEDOWN和MOUSEUP事件,如果同时监控各个控件的事件,麻烦是相当大的。2、窗口标题栏的鼠标事件难以正常处理。 其实,同上一段落类似,处理窗体的WM_MOVING事件是比较好的方法。即在WM_MOVING事件中同步移动其它窗体。 移动其它窗体的方法也有多种,有人采用发送消息的方式,具体如下: / dx和dy是当前窗体移动的距离 / hMove是要移动的窗体 / WM_MOVEFORM是自定义的消息 PostMessage(hMove, WM_MOVEFORM,dx,dy); 被移动的窗体处理WM_MOVEFORM消息时,移动自己到新的位置。 如果是VB、Delphi一类的语言,可以直接设置其Left和Top属性。我采用的方法是使用API函数SetWindowPos,该函数重新设置指定窗口的位置。我的参考代码如下: / 移动被粘贴在一起的其它窗体 void UnionOtherForm(TForm *My,TForm *Form,int dx,int dy) if(Form=NULL)return; CFormAttachStyle *MyStyle=(CFormAttachStyle *)(Form-Tag); if(MyStyle) if(MyStyle-Enabled & MyStyle-AttachTo=My) MyStyle-Enabled=false; int X1=Form-Left; int Y1=Form-Top; SetWindowPos(Form-Handle,My-Handle, X1+dx,Y1+dy,Form-Width,Form-Height, SWP_NOSIZE|SWP_NOACTIVATE); MyStyle-Enabled=true; / 移动被粘贴在一起的其它窗体 void AdjuctFormPos(TForm *My,RECT *r) / 调整窗口位置 int dy=r-top-My-Top; int dx=r-left-My-Left; My-Top=r-top; My-Left=r-left; / 逐一检查创建的窗体 for(int i=0;iFormCount;i+) TForm *Form=Screen-Formsi; if(Form!=My) / 调整被吸附的窗口位置 UnionOtherForm(My,Form,dx,dy); / 处理WM_MOVE事件 void Do_WM_MOVE(TForm *My,TMessage &Msg) / 处理粘贴成功后的位置调整 CFormAttachStyle *MyStyle=(CFormAttachStyle *)My-Tag; if(MyStyle & MyStyle-Enabled) if(MyStyle-Enabled & MyStyle-AttachTo) / 粘贴成功 My-Left=MyStyle-xPos; My-Top=MyStyle-yPos; Msg.Result=0; / 通知系统,消息已经处理 在这里有一个C+ Builder编程的技巧,即使用Screen全局对象。如果在初使化需要使用粘贴功能的窗体时,把一个CFormAttachStyle实例的指针赋值给该窗体的Tag窗体,那么除了处理它的WM_MOVING和WM_MOVE事件外,其它的操作都可以省略了。关键的代码如下: / 注:应把这个函数的声明加到TForm1的类声明中 void _fastcall TForm1:WndProc(TMessage &Msg) TForm:WndPro
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2025年中国医药集团海外招聘考试题库及参考答案
- 2025年血液透析器项目合作计划书
- 2025年中文信息处理平台项目合作计划书
- 2025年飞机用石英玻璃管合作协议书
- 抢救车物品管理课件
- 2025-2026学年北师大版(2024)小学数学三年级上册《看一看(一)》教学设计
- 2025年配电或电器控制设备项目发展计划
- 2025年微型电动手持式牙科钻机项目合作计划书
- 抗美援朝战役课件
- 第三单元毫米、分米和千米单元测试卷(含答案) 2025-2026学年人教版三年级数学上册
- 护理疑难病例讨论课件
- 塑料成型工艺课件
- 《西餐烹调基础》 课件 第六章 基础汤、基础少司和配菜制作
- 中金公司校园招聘笔试题
- 新课标人教版六年级数学上册教材分析课件
- 传奇类手游运营计划书
- 大学美育(第二版) 课件 第二单元:文学艺术
- 2024年云南文山交通运输集团公司招聘笔试参考题库含答案解析
- 新视野商务英语视听说(第三版)(下) Unit 1-电子教案
- 100个红色经典故事【十八篇】
- 《化验室安全管理》课件
评论
0/150
提交评论