利用BCB編寫具有"磁性"特徵的視窗 (轉)
利用BCB編寫具有"磁性"特徵的視窗
黑龍江省五大連池市馬明臣
一些著名的共享不但功能卓著,而且在介面的設計技巧上往往領導了一種時尚,就是其中的一個代表。WinAmp有兩個絕活,一是可以更換窗體的外觀,也就是現在俗稱的給軟體換“皮膚”;另一個是及時磁性窗體技巧。
那麼什麼是磁性窗體呢?用過Winamp的都知道,Winamp的列表或均衡器在被移動的時候,彷彿會受到一股磁力,每當靠近主視窗時就一下子被“吸附”過去,自動沿邊對齊。這就是磁性窗體,那麼我們如何在自己的程式中實現這種奇妙的特性呢?經過筆者摸索琢磨出了實現這種“磁化”視窗的方法。該法適用於C++ builder的各個版本。下面筆者給大家介紹一下該技術。
實現貼上的難點在於什麼時候進行這個操作,假設有兩個窗體Form1和Form2,移動Form2向Form1靠近,當Form2與Form1的最近距離小於一個給定值時貼上在一起。顯然,應該在移動Form2的過程中進行判斷,問題是在程式的什麼位置插入判斷程式碼呢?
合理的方法是利用產生的訊息,我們知道窗體在移動時會產生WM_WINDOWPOSCHANGING和WM_MOVING訊息,移動結束後會產生WM_WINDOWPOSCHANGED和WM_MOVE訊息。我們這裡使用WM_WINDOWPOSCHANGING訊息來實現這一功能。
下面筆者就把實現磁性窗體的方法介紹如下:
先新建一應用程式專案,把主視窗Form1適當放小些,放一個按鈕,修改該按鈕元件的Caption屬性為“建立磁性視窗”雙擊它並在OnClick事件中寫入如下程式碼:
void __fastcall TForm1::Button1Click(T *Sender)
{
Form2= new TForm2(Application);
Form2->Show();//顯示磁性視窗
}
選擇“File”—>“New Form”建立一個新視窗Form2,在Form2上加入一個Edit元件Edit1和一個按鈕元件Button1,修改Edit的TEXT屬性為50(該值為當Form2靠近Form1時距離為50畫素時進行吸附,一般設為20左右即可,這裡為了效果明顯所以設為50畫素),修改按鈕的Caption屬性為“磁距”,接著在這個新視窗的unit2.h中的private:下面加入如下變數定義:
HWND snapwin;//定義Form2吸附到哪一個視窗的控制程式碼
RECT work_area;
bool snapped;//是否吸附標誌
bool winprocthing;
int thresh;//距離多遠開始吸附
void __fastcall SettingChanged(TMessage &msg);//改變視窗大小時產生
void __fastcall WMWindowPosChanging(TWMWindowPosChanging &msg);//移動視窗時產生
void __fastcall UpdateWorkArea();重新整理視窗
接著在public: // User declarations下加入如下訊息:
BEGIN_MESSAGE_MAP
MESSAGE_HANDLER(WM_WINDOWPOSCHANGING,TWMWindowPosChanging,WMWindowPosChanging);//定義訊息當視窗移動時WMWindowPosChanging
MESSAGE_HANDLER(WM_SETTINGCHANGE,TMessage,SettingChanged);
END_MESSAGE_MAP(TForm); //當視窗改變大小時呼叫SettingChanged
在Form2的單元檔案unit.cpp中加入如下程式碼:
void __fastcall TForm2::SettingChanged(TMessage &msg)
{
UpdateWorkArea();
}
//---------------------------------------------------------------------------
void __fastcall TForm2::WMWindowPosChanging(TWMWindowPosChanging &msg)
{
RECT sr;
snapped=false;//設為不吸附
//test window
snapwin = Form1->Handle;//定義Form2吸附到Form1上這裡如改為別的軟體的視窗控制程式碼還可以吸附到別的軟體視窗上
if (snapwin && IsWindowVisible(snapwin))
/*該段得到視窗Form1的當前位置,當Form2移動時該判斷Form2與Form1在上下左右方向上是否距離小於50,如小於50則自動改變Form2的位置,自動吸附到Form1上*/
{
if (GetWindowRect(snapwin,&sr))//得到Form1的位置
{
if ( (msg.WindowPos->x <= (sr.right+thresh)) &&
(msg.WindowPos->x >= (sr.right-thresh)) ) {
if ((msg.WindowPos->y > sr.top) && (msg.WindowPos->y < sr.bottom)) {
snapped=true;
msg.WindowPos->x = sr.right;
}
}
else if ((msg.WindowPos->x + msg.WindowPos->cx) >= (sr.left-thresh) &&
(msg.WindowPos->x + msg.WindowPos->cx) <= (sr.left+thresh)) {
if ((msg.WindowPos->y > sr.top) && (msg.WindowPos->y < sr.bottom)) {
snapped=true;
msg.WindowPos->x = sr.left-msg.WindowPos->cx;
}
}
if ( (msg.WindowPos->y <= (sr.bottom+thresh)) &&
(msg.WindowPos->y >= (sr.bottom-thresh)) ) {
if ((msg.WindowPos->x > sr.left) && (msg.WindowPos->x < sr.right)) {
snapped=true;
msg.WindowPos->y = sr.bottom;
}
}
else if ((msg.WindowPos->y + msg.WindowPos->cy) <= (sr.top+thresh) &&
(msg.WindowPos->y + msg.WindowPos->cy) >= (sr.top-thresh)) {
if ((msg.WindowPos->x > sr.left) && (msg.WindowPos->x < sr.right)) {
snapped=true;
msg.WindowPos->y = sr.top-msg.WindowPos->cy;
}
}
}
}
//測試螢幕
sr = work_area;
if (abs(msg.WindowPos->x) <= (sr.left+thresh)) {
snapped=true;
msg.WindowPos->x = sr.left;
}
else if ((msg.WindowPos->x + msg.WindowPos->cx) >= (sr.right-thresh) &&
(msg.WindowPos->x + msg.WindowPos->cx) <= (sr.right+thresh)) {
snapped=true;
msg.WindowPos->x = sr.right-msg.WindowPos->cx;
}
if (abs(msg.WindowPos->y) <= (sr.top+thresh)) {
snapped=true;
msg.WindowPos->y = sr.top;
}
else if ((msg.WindowPos->y+msg.WindowPos->cy) >= (sr.bottom-thresh) &&
(msg.WindowPos->y+msg.WindowPos->cy) <= (sr.bottom+thresh)) {
snapped=true;
msg.WindowPos->y = sr.bottom-msg.WindowPos->cy;
}
}
//---------------------------------------------------------------------------
void __fastcall TForm2::UpdateWorkArea()
{
SystemParametersInfo(SPI_GETWORKAREA, 0, &work_area, 0);
}
雙擊“磁距”按鈕加入如下程式碼:
void __fastcall TForm2::Button1Click(TObject *Sender)
{
thresh = StrToInt(Edit1->Text);//設定磁性視窗距Form1為edit1中的數值時開始吸附
}
在窗體Form2的OnCreate事件中加入如下程式碼:
void __fastcall TForm2::FormCreate(TObject *Sender)
{
snapped=false;//設定為不吸附
UpdateWorkArea();
thresh = StrToInt(Edit1->Text);
snapwin = Form1->Handle;
}
該程式在c++ builder 5.0、98系統下透過。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10752043/viewspace-993837/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 在bcb裡實現像Winamp那樣具有吸附效果的磁性視窗 (轉)
- JavaScript視窗功能指南之發揮視窗特徵 (轉)JavaScript特徵
- 用BCB編寫身份證號識別程式 (轉)
- BCB 窗體透明控制元件 (轉)控制元件
- Win32彙編教程四 編寫一個簡單的視窗 (轉)Win32
- 如何編寫簡單的應用window視窗程式
- JavaScript視窗功能指南之在視窗中書寫內容 (轉)JavaScript
- 利用DELPHI編寫WINDOWS外殼 (轉)Windows
- 利用Delphi編寫IE擴充套件 (轉)套件
- 編寫更具有描述性的 RESTful APIRESTAPI
- 利用VB編寫螢幕保護程式 (轉)
- 利用Java編寫HTML檔案分析程式(轉)JavaHTML
- Delphi(BCB)中編譯器版本宏定義 (轉)編譯
- 利用OnHelp( )在BCB中實現上下文敏感的html help (轉)HTML
- 編寫具有描述性的 RESTful API (一): WorkflowRESTAPI
- C++ Builder 高手進階 (五)用BCB編寫多執行緒應用程式 (轉)C++UI執行緒
- 資料視覺化可以利用的工具有哪些?視覺化
- 利用Dephi5編寫控制皮膚程式 (轉)
- 利用Delphi編寫Windows外殼擴充套件 (轉)Windows套件
- 用BCB寫一個最簡單的多執行緒 (轉)執行緒
- 使資料視窗中的被選中行具有更好的外觀
- 一個用delphi寫的整合彙編與api的簡單的視窗程式API
- 工作列視窗以及其子視窗結構 (轉)
- JavaScript視窗功能指南之操縱視窗 (轉)JavaScript
- 編寫具有描述性的 RESTful API (四): 通知系統RESTAPI
- 玩轉BCB的IDE,體驗ToolsAPI (轉)IDEAPI
- JavaScript視窗功能指南之命名視窗和框架 (轉)JavaScript框架
- JavaScript視窗功能指南之定製新視窗 (轉)JavaScript
- JavaScript視窗功能指南之建立彈出視窗 (轉)JavaScript
- 寫爬蟲時常見的五種字串編碼特徵爬蟲字串編碼特徵
- 編寫具有描述性的 RESTful API (二): 推薦與 ObserverRESTAPIServer
- Effective BCB Form Program(1) ——窗體事件驅動鏈引發程式錯誤分析 (轉)ORM事件
- Effective BCB Form Program(2) ——窗體事件驅動鏈引發程式錯誤分析 (轉)ORM事件
- C# winForm 視窗跳轉後關閉上一個視窗的方法C#ORM
- js具有跟隨彈性效果的網頁右下角視窗程式碼JS網頁
- 關於視窗的操作詳談 (轉)
- 利用Delphi編寫IE擴充套件套件
- 子視窗控制元件(轉)控制元件