在bcb里完成像Winamp那樣具有吸附效果的磁性窗口
發表時間:2023-08-18 來源:明輝站整理相關軟件相關文章人氣:
[摘要]相信大家都用過Winamp,一定會對她那種具有吸附效果的窗口感到很驚喜吧。其實要實現這樣的效果并不難,下面我就用bcb做出這樣的效果。為了將問題簡化,窗口只在屏幕頂端產生吸附效果。 打開...
相信大家都用過Winamp,一定會對她那種具有吸附效果的窗口感到很驚喜吧。其實要實現這樣的效果并不難,下面我就用bcb做出這樣的效果。為了將問題簡化,窗口只在屏幕頂端產生吸附效果。
打開bcb6.0,新建一工程,將Form1的BorderStyle的屬性改為bsNone,做成一個無標題欄,無邊框的窗體。正常情況下,我們是無法移動這樣的窗體的。我們必須自己給窗口發送一個移動的消息,在Form1的MouseDown的事件中添加如下代碼:
ReleaseCapture();
SendMessage(this->Handle,WM_SYSCOMMAND,SC_MOVE+HTCAPTION,0);
其實道理很簡單,相信大家都會這個,我也就不多說了,:)
為了窗口在接近屏幕頂端的時候有一種磁性效果,我們必須在窗口的移動之前做一個判斷,判斷窗口將要到達的新位置的Top值是否小于一定范圍(這個范圍我稱之為磁性距離,大小可由自己定義,為方便起見,我在這里定為20)。但是bcb里面并沒有窗體移動事件,我們必須自己在程序里面攔截窗體移動消息,為此,我們要重載WndProc這個函數:
void __fastcall TForm1::WndProc(TMessage& Message)
{
switch(Message.Msg)
{
/*在窗口移動之前,判斷窗口新位置的Top值是不是在磁性范
圍內,如果在,讓它歸0,表示不產生窗體移動,避免在磁性
范圍內移動窗口的時候窗口過于閃爍*/
case WM_WINDOWPOSCHANGING:
if ((LPWINDOWPOS(Message.LParam))->y<20)
(LPWINDOWPOS(Message.LParam))->y=0;
break;
default:
break;
}
TForm::WndProc(Message); //自己處理完消息后再讓系統做剩下的事情
}
OK,代碼就這么多,是不是很簡單?運行一下程序,看是不是果真如此呢?:)
也許有人會問為什么不是攔截WM_MOVE這個消息,其實只要你試一下就知道了,如果攔截這個消息,窗口在磁性范圍內移動的時候會很閃爍。原因很簡單,WM_WINDOWPOSCHANGING是在窗口移動之前就做出了判斷,如果窗口將要在磁性范圍內移動(此時尚未移動),則不讓窗口移動。而WM_MOVE在窗口移動以后才做判斷,這樣的結果就是不斷讓Top復位成0,當然會造成窗口閃爍了。
另外,大家都知道,根據系統本身的設置不同,窗口在移動的過程中,有兩種顯示效果,一種是顯示虛線框,一種是顯示窗口內容。細心的朋友可能已經發現,在Winamp中,不管系統的設置是如何,移動Winamp的窗口的過程中總是會顯示窗口內容。其實這樣做的道理很簡單,因為在顯示虛線框的時候,磁性窗口的吸附效果不怎么好,大家可以親手試試。
那如何也做成和Winamp一樣呢?其實只要一個API函數就搞定了,:),代碼如下:
SystemParametersInfo(SPI_SETDRAGFULLWINDOWS,true,NULL,SPIF_SENDCHANGE);
在窗口移動之前,通過調用上面的函數,就能達到Winamp一樣的效果了。關于SystemParametersInfo這個函數及參數的具體用法,請各位參見MSDN,再沒有比MSDN解釋的更清楚了。
以上代碼在Win2k Professional+bcb6.0下測試通過。