利用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/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 編寫更具有描述性的 RESTful APIRESTAPI
- 編寫具有描述性的 RESTful API (一): WorkflowRESTAPI
- 資料視覺化可以利用的工具有哪些?視覺化
- 編寫具有描述性的 RESTful API (四): 通知系統RESTAPI
- C# winForm 視窗跳轉後關閉上一個視窗的方法C#ORM
- 寫爬蟲時常見的五種字串編碼特徵爬蟲字串編碼特徵
- rust druid編寫第一個窗體RustUI
- 編寫具有描述性的 RESTful API (二): 推薦與 ObserverRESTAPIServer
- 編寫具有描述性的 RESTful API (三): 使用者行為RESTAPI
- 測開---編寫測試工具有什麼好的方法論嗎
- 演算法~利用zset實現滑動視窗限流演算法
- 利用 Powershell 編寫簡單的瀏覽器指令碼瀏覽器指令碼
- Flink的滾動視窗、會話視窗、滑動視窗及其應用會話
- mysql視窗函式中的滑動視窗MySql函式
- 利用sklearn進行字典&文字的特徵提取特徵
- SQL KEEP 視窗函式等價改寫案例SQL函式
- win10怎麼使用快捷鍵換視窗_win10利用快捷鍵快速切換視窗步驟Win10
- 視窗
- 特徵工程:基於梯度提升的模型的特徵編碼效果測試特徵工程梯度模型
- 視窗程式的框架框架
- C# 介面跳轉-登陸之後跳轉至主視窗C#
- Go Qt5 建立空白視窗、視窗居中及關閉視窗事件GoQT事件
- Windows API視窗程式設計 - 空白視窗WindowsAPI程式設計
- Ace Editor 擴充套件編寫初步(轉)套件
- 拆分視窗
- 聊天視窗
- 視窗事件事件
- vim學習筆記——多檔案、多視窗編輯筆記
- plsql developer 視窗的使用SQLDeveloper
- 用js寫一個繫結事件檢測視窗大小JS事件
- [Go語言寫介面]三、使用介面設計器設計視窗,在程式碼中呼叫,背景編輯器的使用Go
- dotnet 如何從 Gtk 3 的視窗到對應的 X11 視窗
- python(django(管路頁面、概況、編寫檢視佔位、編寫一個真正的檢視、丟擲錯誤、檢視使用模板系統、去除硬編碼url、為url新增命名開空間、編寫表單))PythonDjango
- 在Ubuntu上利用vim進行程式編寫及執行Ubuntu行程
- 如何利用Typora編寫部落格,快速釋出到多平臺?
- [譯] 利用 Immutability(不可變性)編寫更為簡潔高效的程式碼
- 關於父視窗獲取跨域iframe子視窗中的元素跨域
- (轉)leetcode:Find All Anagrams in a String 滑動視窗方法總結LeetCode
- 如何視覺化編寫和編排你的 K8s 任務視覺化K8S