频道直达 - 专题 - 新闻 - 技巧 - 组网 - 开发 - 安全 - web编程 - 图像 - 操作系统 - 数据库 - 教育 - 旅游 - 健康 - 时尚 - 驱动 - 软件 - 游戏 - 多媒体 - ERP - 讨论组

Delphi制作的“磁性”窗口

来源: 作者: 出处:巧巧读书 2006-10-05 进入讨论组

  Winamp的用户都知道,Winamp的播放列表或均衡器在被移动的时候,仿佛会受到一股磁力,每当靠近主窗口时就一下子被“吸附”过去,自动沿边对齐。我想让我的Winamp插件也具备这种奇妙特性,于是琢磨出了一种“磁化”窗口的方法。该法适用于Delphi的各个版本。
为了演示这种技术,请随我来制作一个会被Winamp“吸引”的样板程序。

    先新建一应用程序项目,把主窗口Form1适当改小些,并将BorderStyle设为bsNone。放一个按钮元件,双击它并在OnClick事件中写“Close;”。待会儿就按它来结束程序。现在切换到代码编辑区,定义几个全局变量。

    var

     Form1: TForm1; //“磁性”窗口

     LastX, LastY: Integer; //记录前一次的坐标

     WinampRect:Trect; //保存Winamp窗口的矩形区域

     hwnd_Winamp:HWND; //Winamp窗口的控制句柄

    接着编写Form1的OnMouseDown和OnMouseMove事件。

    procedure TForm1.FormMouseDown(Sender: Tobject; Button: TMouseButton;

     Shift: TShiftState; X, Y: Integer);

    const

     ClassName=‘Winamp v1.x’; //Winamp主窗口的类名

     //如果改成ClassName=‘TAppBuilder’,你就会发现连Delphi也有引力啦!

    begin

    //记录当前坐标

    LastX := X;

    LastY := Y;

    //查找Winamp

    hwnd_Winamp := FindWindow(ClassName,nil);

    if hwnd_Winamp>0 then //找到的话,记录其窗口区域

    GetWindowRect(hwnd_Winamp, WinampRect);

    end;

    procedure TForm1.FormMouseMove(Sender: Tobject; Shift: TShiftState; X,

     Y: Integer);

    var

     nLeft,nTop:integer; //记录新位置的临时变量

    begin

    //检查鼠标左键是否按下

     if HiWord(GetAsyncKeyState(VK_LBUTTON)) > 0 then

     begin

     //计算新坐标

     nleft := Left + X - LastX;

     nTop := Top + Y - LastY;

     //如果找到Winamp,就修正以上坐标,产生“磁化”效果

     if hwnd_Winamp>0 then

     Magnetize(nleft,ntop);

     //重设窗口位置

     SetBounds(nLeft,nTop,width,height);

     end;

    end;

    别急着,看Magnetize()过程,先来了解一下修正坐标的原理。根据对Winamp实现效果的观察,我斗胆给所谓“磁化”下一个简单的定义,就是“在原窗口与目标窗口接近到某种预定程度,通过修正原窗口的坐标,使两窗口处于同一平面且具有公共边的过程”。依此定义,我设计了以下的“磁化”步骤。第一步,判断目标窗口(即Winamp)和我们的Form1在水平及垂直方向上的投影线是否重叠。“某方向投影线有重叠”是“需要进行坐标修正”的必要非充分条件。判断依据是两投影线段最右与最左边界的差减去它们宽度和的值的正负。第二步,判断两窗口对应边界是否靠得足够近了。肯定的话就让它们合拢。

    好了,下面便是“神秘”的Magnetize过程了……

    procedure TForm1.Magnetize(var nl,nt:integer);

     //内嵌两个比大小的函数

     function Min(a,b:integer):integer;

     begin

     if a>b then result:=b else result:=a;

     end;

     function Max(a,b:integer):integer;

     begin

     if a    end;

    var

     H_Overlapped,V_Overlapped:boolean; //记录投影线是否重叠

     tw,ww,wh:integer; //临时变量

    const

     MagneticForce:integer=50; //“磁力”的大小。

     //准确的说,就是控制窗口边缘至多相距多少像素时需要修正坐标

     //为了演示,这里用一个比较夸张的数字——50。

     //一般可以用20左右,那样比较接近Winamp的效果

    begin

    //判断水平方向是否有重叠投影

    ww := WinampRect.Right-WinampRect.Left;

    tw := Max(WinampRect.Right,nl+Width)-Min(WinampRect.Left,nl);

    H_Overlapped := tw<=(Width+ww);

    //再判断垂直方向

    wh := WinampRect.Bottom-WinampRect.Top;

    tw := Max(WinampRect.Bottom,nt+Height)-Min(WinampRect.Top,nt);

    V_Overlapped := tw<=(Height+wh);

    //足够接近的话就调整坐标

    if H_Overlapped then

     begin

     if Abs(WinampRect.Bottom-nt)   

  else if Abs(nt+Height-WinampRect.Top)   

  end;

    if V_Overlapped then

     begin

     if Abs(WinampRect.Right-nl)   

  else if Abs(nl+Width-WinampRect.Left)   

  end;

    end;

  怎么样?运行后效果不错吧!巧 巧 读 书:http://www.qqread.com/delphi/q215432.html进入讨论组讨论。
收藏此文】【 】【打印】【关闭
相关图文阅读
频道图文推荐
健 康 咨 询
时 尚 咨 询
巧巧读书宗旨
相关专题
最新论坛文章
站内各频道最新更新文档
站内最新制作专题
热门关键字导读
Photoshop教 程照片处理 照片制作 PS快捷键 抠图
计 算 机 故 障XP系统修复
艺 术 与 设 计设计 流媒体 设计欣赏 边框
计 算 机 安 全ARP
站内频道文章精选
巧巧电脑频道编辑信箱  告诉我们您想看的专题或文章