在bcb裡實現像Winamp那樣具有吸附效果的磁性視窗 (轉)

worldblog發表於2008-01-06
在bcb裡實現像Winamp那樣具有吸附效果的磁性視窗 (轉)[@more@]

  相信大家都用過,一定會對她那種具有吸附效果的視窗感到很驚喜吧。其實要實現這樣的效果並不難,下面我就用bcb做出這樣的效果。為了將問題簡化,視窗只在螢幕頂端產生吸附效果。

  開啟bcb6.0,新建一工程,將Form1的BorderStyle的屬性改為bsNone,做成一個無標題欄,無邊框的窗體。正常情況下,我們是無法移動這樣的窗體的。我們必須自己給視窗傳送一個移動的訊息,在Form1的MouseDown的事件中新增如下程式碼:

  ReleaseCapture();

  SendMessage(this->Handle,WM_SYMMAND,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一樣呢?其實只要一個函式就搞定了,:),程式碼如下:

SystemParametersInfo(SPI_SETDRAGFULL,true,NULL,SPIF_SENDCHANGE);

  在視窗移動之前,透過上面的函式,就能達到Winamp一樣的效果了。關於SystemParametersInfo這個函式及引數的具體用法,請各位參見MSDN,再沒有比MSDN解釋的更清楚了。

  以上程式碼在 Professional+bcb6.0下測試透過。

 

  呼,總算寫完了,這是我第一次寫東西,請大家多多指教,:)

  讓板磚來得更猛烈一些吧!

 


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10752043/viewspace-996724/,如需轉載,請註明出處,否則將追究法律責任。

相關文章