如何做成象winamp一样的吸附窗口?(50分)

  • 主题发起人 主题发起人 tomol
  • 开始时间 开始时间
T

tomol

Unregistered / Unconfirmed
GUEST, unregistred user!
我想做一个象winamp一样的吸附(磁性)窗口,但总也做不好,我是在WM_MOVING消息处理<br>事件中加入<br>&nbsp; if form1.Top &lt; 5 then <br>&nbsp; &nbsp; form1.Top := 0;<br>这样做会有很大的晃动,请问该如何处理才能得到象winamp一样的窗口?<br>请不要给我贴诸如下列文字的东西,因为根本不能用!!!<br>++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++<br>winamp的用户都知道,winamp的播放列表或均衡器在被移动的时候,仿佛会受到一股磁力,<br>每当靠近主窗口时就一下子被“吸附”过去,自动沿边对齐。我想让我的winamp插件也具备<br>这种奇妙特性,于是琢磨出了一种“磁化”窗口的方法。该法适用于delphi的各个版本。为<br>了演示这种技术,请随我来制作一个会被winamp“吸引”的样板程序。<br>  先新建一应用程序项目,把主窗口form1适当改小些,并将borderstyle设为bsnone。放<br>一个按钮元件,双击它并在onclick事件中写“close;”。待会儿就按它来结束程序。现在<br>切换到代码编辑区,定义几个全局变量(未完)<br>++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++<br>
 
呵呵,以前我都问过的。<br>winamp的用户都知道,winamp的播放列表或均衡器在被移动的时候,仿佛会受到一股磁力,<br>每当靠近主窗口时就一下子被“吸附”过去,自动沿边对齐。我想让我的winamp插件也具备<br>这种奇妙特性,于是琢磨出了一种“磁化”窗口的方法。该法适用于delphi的各个版本。为<br>了演示这种技术,请随我来制作一个会被winamp“吸引”的样板程序。<br>  先新建一应用程序项目,把主窗口form1适当改小些,并将borderstyle设为bsnone。放<br>一个按钮元件,双击它并在onclick事件中写“close;”。待会儿就按它来结束程序。现在<br>切换到代码编辑区,定义几个全局变量<br>var<br>&nbsp; form1: tform1; //“磁性”窗口<br>&nbsp; lastx, lasty: integer; //记录前一次的坐标<br>&nbsp; winamprect:trect; //保存winamp窗口的矩形区域<br>&nbsp; hwnd_winamp:hwnd; //winamp窗口的控制句柄<br>&nbsp; <br>&nbsp; 接着编写form1的onmousedown和onmousemove事件。<br>procedure tform1.formmousedown(sender: tobject; button:tmousebutton;<br>&nbsp; shift: tshiftstate; x, y: integer);<br>const<br>&nbsp; classname = 'winamp v1.x'; //winamp主窗口的类名<br>&nbsp; //如果改成classname=‘tappbuilder’,你就会发现连delphi也有引力啦!<br>begin<br>&nbsp; //记录当前坐标<br>&nbsp; lastx := x;<br>&nbsp; lasty := y;<br>&nbsp; //查找winamp<br>&nbsp; hwnd_winamp := findwindow(classname,nil);<br>&nbsp; if hwnd_winamp&gt;0 then //找到的话,记录其窗口区域<br>&nbsp; &nbsp; getwindowrect(hwnd_winamp, winamprect);<br>end;<br><br>procedure tform1.formmousemove(sender: tobject; shift: <br>&nbsp; tshiftstate; x, y: integer);<br>var<br>&nbsp; nleft,ntop:integer; //记录新位置的临时变量<br>begin<br>&nbsp; //检查鼠标左键是否按下<br>&nbsp; if hiword(getasynckeystate(vk_lbutton)) &gt; 0 then<br>&nbsp; begin<br>&nbsp; &nbsp; //计算新坐标<br>&nbsp; &nbsp; nleft := left + x - lastx;<br>&nbsp; &nbsp; ntop := top + y - lasty;<br>&nbsp; &nbsp; //如果找到winamp,就修正以上坐标,产生“磁化”效果<br>&nbsp; &nbsp; if hwnd_winamp&gt;0 then<br>&nbsp; &nbsp; &nbsp; magnetize(nleft,ntop);<br>&nbsp; &nbsp; &nbsp; //重设窗口位置<br>&nbsp; &nbsp; &nbsp; setbounds(nleft,ntop,width,height);<br>&nbsp; end;<br>end;<br>别急着,看magnetize()过程,先来了解一下修正坐标的原理。根据对winamp实现效果的观<br>察,我斗胆给所谓“磁化”下一个简单的定义,就是“在原窗口与目标窗口接近到某种预定<br>程度,通过修正原窗口的坐标,使两窗口处于同一平面且具有公共边的过程”。依此定义,<br>我设计了以下的“磁化”步骤。第一步,判断目标窗口(即winamp)和我们的form1在水平及<br>垂直方向上的投影线是否重叠。“某方向投影线有重叠”是“需要进行坐标修正”的必要<br>非充分条件。判断依据是两投影线段最右与最左边界的差减去它们宽度和的值的正负。第<br>二步,判断两窗口对应边界是否靠得足够近了。肯定的话就让它们合拢。<br>好了,下面便是“神秘”的magnetize过程了……<br><br>procedure tform1.magnetize(var nl,nt:integer);<br>&nbsp; //内嵌两个比大小的函数<br>&nbsp; function min(a,b:integer):integer;<br>&nbsp; begin<br>&nbsp; &nbsp; if a &gt; b then result:=b else result:=a;<br>&nbsp; end;<br>&nbsp; function max(a,b:integer):integer;<br>&nbsp; begin<br>&nbsp; &nbsp; if a &lt; b then result:=b else result:=a; <br>&nbsp; end;<br>var<br>&nbsp; h_overlapped,v_overlapped:boolean; //记录投影线是否重叠<br>&nbsp; tw,ww,wh:integer; //临时变量<br>const<br>&nbsp; magneticforce:integer=50; //“磁力”的大小。<br>&nbsp; //准确的说,就是控制窗口边缘至多相距多少像素时需要修正坐标<br>&nbsp; //为了演示,这里用一个比较夸张的数字——50。<br>&nbsp; //一般可以用20左右,那样比较接近winamp的效果<br>begin<br>&nbsp; //判断水平方向是否有重叠投影<br>&nbsp; ww := winamprect.right - winamprect.left;<br>&nbsp; tw := max(winamprect.right,nl+width) - min(winamprect.left,nl);<br>&nbsp; h_overlapped := tw&lt;=(width+ww);<br>&nbsp; //再判断垂直方向<br>&nbsp; wh := winamprect.bottom - winamprect.top;<br>&nbsp; tw := max(winamprect.bottom,nt + height) - min(winamprect.top,nt);<br>&nbsp; v_overlapped := tw&lt;=(height + wh);<br>&nbsp; //足够接近的话就调整坐标<br>&nbsp; if h_overlapped then<br>&nbsp; begin<br>&nbsp; &nbsp; if abs(winamprect.bottom - nt)    <br>&nbsp; &nbsp; else if abs(nt + height - winamprect.top)    <br>&nbsp; end;<br>&nbsp; if v_overlapped then<br>&nbsp; begin<br>&nbsp; &nbsp; if abs(winamprect.right - nl)    <br>&nbsp; &nbsp; else if abs(nl + width - winamprect.left)    <br>&nbsp; end;<br>end;<br>
 
to Chenlili:<br>拜托,请自己运行一下你贴上去的代码,看能不能用!!!反正我是不能用!
 
思路就这样了,能不能运行肯定自己要自己改改了。
 
TMagnetic控件 (DELPHI盒子版主作品)<br>主要功能: <br>①提供类是WINAMP的磁性粘贴功能: <br>选项包括粘贴屏幕、 <br>任务栏(可关闭) 、 <br>资源管理器(可关闭)、 <br>自定义如WINAMP(可关闭)。 <br>②提供没有标题栏的移动, <br>没有标题栏的改变大小。 <br>包括全部源代码,中英文说明,完整事例。 <br>http://mantousoft.51.net/softm/3_tmagnetic.zip<br>
 
后退
顶部