荔园在线

荔园之美,在春之萌芽,在夏之绽放,在秋之收获,在冬之沉淀

[回到开始] [上一篇][下一篇]


发信人: georgehill (佐治·希尔【多情网虫无情网】), 信区: Program
标  题: “磁性”窗口
发信站: BBS 荔园晨风站 (Sun Mar 12 02:07:27 2000), 转信

资料整理·中国程序员网站


“磁性”窗口

  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; //记录新位置的+ 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.R獺eight)-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;
  怎么样?运行后效果不错吧!
  我设计的一个卡拉OK插件就应用了这种技术,你可以到http://www.lotof.com/
lyrics去下载它作为参考。
--
        那你可不可以教我,
        有什么办法可以不去喜欢一个人呢?

                -- Bye 赤明莉香 --
 我是来自大富翁的小美!^_^

※ 来源:·BBS 荔园晨风站 bbs.szu.edu.cn·[FROM: 192.168.1.115]


[回到开始] [上一篇][下一篇]

荔园在线首页 友情链接:深圳大学 深大招生 荔园晨风BBS S-Term软件 网络书店