久久―日本道色综合久久,亚洲欧美精品在线,狼狼色丁香久久婷婷综合五月,香蕉人人超,日本网站黄,国产在线观看不卡免费高清,无遮挡的毛片免费

2023信創(chuàng)獨角獸企業(yè)100強
全世界各行各業(yè)聯(lián)合起來,internet一定要實現(xiàn)!

Delphi制作的“磁性”窗口

2004-02-14 eNet&Ciweek

  Winamp的用戶都知道,Winamp的播放列表或均衡器在被移動的時候,仿佛會受到一股磁力,每當靠近主窗口時就一下子被“吸附”過去,自動沿邊對齊。我想讓我的Winamp插件也具備這種奇妙特性,于是琢磨出了一種“磁化”窗口的方法。該法適用于Delphi的各個版本。為了演示這種技術,請隨我來制作一個會被Winamp“吸引”的樣板程序。

    先新建一應用程序項目,把主窗口Form1適當改小些,并將BorderStyle設為bsNone。放一個按鈕元件,雙擊它并在OnClick事件中寫“Close;”。待會兒就按它來結(jié)束程序。現(xiàn)在切換到代碼編輯區(qū),定義幾個全局變量。

    var

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

     LastX, LastY: Integer; //記錄前一次的坐標

     WinampRect:Trect; //保存Winamp窗口的矩形區(qū)域

     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’,你就會發(fā)現(xiàn)連Delphi也有引力啦!

    begin

    //記錄當前坐標

    LastX := X;

    LastY := Y;

    //查找Winamp

    hwnd_Winamp := FindWindow(ClassName,nil);

    if hwnd_Winamp>0 then //找到的話,記錄其窗口區(qū)域

    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,就修正以上坐標,產(chǎn)生“磁化”效果

     if hwnd_Winamp>0 then

     Magnetize(nleft,ntop);

     //重設窗口位置

     SetBounds(nLeft,nTop,width,height);

     end;

    end;

    別急著,看Magnetize()過程,先來了解一下修正坐標的原理。根據(jù)對Winamp實現(xiàn)效果的觀察,我斗膽給所謂“磁化”下一個簡單的定義,就是“在原窗口與目標窗口接近到某種預定程度,通過修正原窗口的坐標,使兩窗口處于同一平面且具有公共邊的過程”。依此定義,我設計了以下的“磁化”步驟。第一步,判斷目標窗口(即Winamp)和我們的Form1在水平及垂直方向上的投影線是否重疊。“某方向投影線有重疊”是“需要進行坐標修正”的必要非充分條件。判斷依據(jù)是兩投影線段最右與最左邊界的差減去它們寬度和的值的正負。第二步,判斷兩窗口對應邊界是否靠得足夠近了??隙ǖ脑捑妥屗鼈兒蠑n。

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

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

     //內(nèi)嵌兩個比大小的函數(shù)

     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; //“磁力”的大小。

     //準確的說,就是控制窗口邊緣至多相距多少像素時需要修正坐標

     //為了演示,這里用一個比較夸張的數(shù)字——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);

    //足夠接近的話就調(diào)整坐標

    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;

  怎么樣?運行后效果不錯吧!

相關頻道: eNews

您對本文或本站有任何意見,請在下方提交,謝謝!

投稿信箱:tougao@enet16.com