就是磁性窗体的代码:
不要网上的那个,要你得却调试成功的,谢谢

解决方案 »

  1.   

    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;
      怎么样?运行后效果不错吧!
      

  2.   

    楼上的:nt,nl是什么?你测试通过了吗?
    这个帖子我也有!
      

  3.   

    unit Unit1;interfaceuses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, StdCtrls;type
      TForm1 = class(TForm)
        Button1: TButton;
        Button2: TButton;
        procedure FormMouseMove(Sender: TObject; Shift: TShiftState; X,
          Y: Integer);
        procedure Button1Click(Sender: TObject);
        procedure FormMouseDown(Sender: TObject; Button: TMouseButton;
          Shift: TShiftState; X, Y: Integer);
     private
        LastX,LastY:Integer;
        WinMapRect:TRect;
        WinMap_HWND:HWND;
        procedure ReSize(ALeft,ATop:Integer);
        { Private declarations }
      public
        { Public declarations }
      end;var
      Form1: TForm1;implementation{$R *.dfm}procedure TForm1.FormMouseMove(Sender: TObject; Shift: TShiftState; X,
      Y: Integer);
    const
       ClassName='TAppBulider';begin
       LastX:=X;                   //X:是鼠标相对与form的位置
       LastY:=Y;                   //left:是form相对Screen的位置
       WinMap_HWND:=Windows.FindWindow(ClassName,nil);
       if WinMap_HWND<>0 then
       begin
          GetWindowRect(WinMap_HWND,WinMapRect);
          MessageBeep(0);
       end;
       //showmessage(inttostr(LastX)+'A1');
      // showmessage(inttostr(lasty)+'A2');
      // showmessage(inttostr(self.Left)+'A3');
      // showmessage(inttostr(self.Top)+'A4');end;procedure TForm1.Button1Click(Sender: TObject);
    var
      S:integer;
    begin
       Self.Close;
    end;procedure TForm1.FormMouseDown(Sender: TObject; Button: TMouseButton;
      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);
      end;
      if WinMap_HWND<>0 then
        ReSize(nLeft,nTop);
      Self.SetBounds(nLeft,nTop,Width,Height);
    end;procedure TForm1.ReSize(ALeft, ATop: 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>B then
      result:=A
      else
      result:=B;
    end;
    var
      H_,V:Boolean;
      tw,ww,wh:integer;
    const
      Forse:integer=50;
    begin
      ww:=WinMapRect.Right-WinMapRect.Left;
      tw:=MAx(WinMapRect.Right,nl+Width)-Min(WinMapRect.Left,nl)end;end.