国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發設計 > 正文

制作類似WinAmp一樣的“磁性”窗口

2019-11-18 18:48:21
字體:
來源:轉載
供稿:網友
摘 要:Winamp的用戶都知道,Winamp的播放列表或均衡器在被移動的時候,仿佛會受到一股磁力,每當靠近主窗口時就一下子被“吸附”過去,自動沿邊對齊。
關鍵字:“磁性”窗口
類 別:用戶界面

CoDelphi.com版權所有,未經允許,不得進行任何形式轉載


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;
  怎么樣?運行后效果不錯吧!

我設計的一個卡拉OK插件就應用了這種技術,你可以到http://www.lotof.com/lyrics去下載它作為參考

上一篇:kmp模式匹配算法的pascal實現

下一篇:COM/DCOM中如何傳遞數組:

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
學習交流
熱門圖片

新聞熱點

疑難解答

圖片精選

網友關注

主站蜘蛛池模板: 神池县| 吕梁市| 宜章县| 乌兰浩特市| 宜黄县| 中方县| 安平县| 舒兰市| 泰顺县| 松滋市| 丹阳市| 绵阳市| 台安县| 乳源| 石棉县| 台前县| 东丽区| 蕉岭县| 隆尧县| 惠来县| 昌都县| 泰兴市| 林口县| 河西区| 诏安县| 灌南县| 蚌埠市| 唐河县| 涞水县| 临沧市| 揭阳市| 苏尼特右旗| 肃南| 岐山县| 滦南县| 福海县| 太白县| 广南县| 青川县| 新乡市| 永登县|