| WINDOWS應(yīng)用程序窗口一般包括兩種:普通窗口和常居頂層的無標(biāo)題條高級(jí)窗口。前者是由WINDOWS內(nèi)部功能定制的,它具有WINDOWS應(yīng)用程序 窗口的所有普通特性:具有標(biāo)題條、窗口邊框、最大化按鈕、最小化按鈕和系統(tǒng)默認(rèn)的快捷鍵及鼠標(biāo)支持功能等,利用鼠標(biāo)左鍵拖動(dòng)該種窗口的標(biāo)題條可以在屏幕上 任意移動(dòng)窗口,當(dāng)鼠標(biāo)光標(biāo)停在窗口邊框上時(shí)可以改變窗口大小;后者是一種定制的高級(jí)窗口,它不具有普通窗口的任何屬性,整個(gè)窗口的控制必須由編程者來一一 確定,使用這種窗口的典型實(shí)例有WINDOWS中的IME輸入法應(yīng)用程序、UCWIN4.0平臺(tái)、各種浮動(dòng)工具箱、OFFICE中的桌面工具欄和第三方開 發(fā)的漢字輸入平臺(tái)等。 WINDOWS 這種無標(biāo)題條常居頂層高級(jí)窗口的一個(gè)顯著特點(diǎn)是,不需改變窗口大小但必須具有窗口的客戶區(qū)域拖動(dòng)功能。由于普通窗口的拖動(dòng)功能是由系統(tǒng)來完成的,編制普通 的應(yīng)用程序根據(jù)無須考慮客戶區(qū)域拖動(dòng)問題,因此一般編程人員很難遇到這個(gè)問題,更談不上如何實(shí)現(xiàn)這一功能了。開發(fā)者往往希望自己開發(fā)出來的軟件具有經(jīng)典軟 件中的窗口客戶區(qū)域拖動(dòng)功能,筆者曾經(jīng)利用模仿系統(tǒng)鼠標(biāo)點(diǎn)擊標(biāo)題條拖動(dòng)窗口和WINDOWS系統(tǒng)內(nèi)部提供的API發(fā)送函數(shù)發(fā)送內(nèi)部拖動(dòng)命令來實(shí)現(xiàn)無標(biāo)題常 居頂層高級(jí)窗口的客戶拖動(dòng)功能,結(jié)果都不理想。后來只好在窗口函數(shù)中通過直接處理WM_LBUTTONDOWN、WM_MOUSEMOVE和 WM_LBUTTONUP消息,自行控制窗口拖動(dòng)的客戶命令區(qū)、拖動(dòng)開始、窗口移動(dòng)、拖動(dòng)虛框繪制、虛框移動(dòng)和拖動(dòng)結(jié)束等過程,來實(shí)現(xiàn)高級(jí)頂層窗口的客戶 區(qū)域拖動(dòng)方案。下面就自己實(shí)踐經(jīng)驗(yàn)詳細(xì)介紹實(shí)現(xiàn)該方案的具體方法和主要技巧。 一、WINDOWS檢測(cè)客戶拖動(dòng)命令及鼠標(biāo)光標(biāo)動(dòng)態(tài)提示的實(shí)現(xiàn)方法 WINDOWS 無標(biāo)題條常居頂層高級(jí)窗口的客戶區(qū)域一般分為兩種:特定客戶命令區(qū)域和非特定客戶命令區(qū)域。特定客戶命令區(qū)域是指利用"RECT"定義的特定子矩形區(qū)域, 窗口函數(shù)對(duì)發(fā)生在該區(qū)域內(nèi)的鼠標(biāo)命令進(jìn)行檢測(cè)并處理;非特定客戶命令區(qū)域是指沒有明確定義的窗口客戶區(qū)域部分,即所有特定客戶命令區(qū)域之外的部分,窗口函 數(shù)根據(jù)實(shí)際需要來確定是否對(duì)該區(qū)域內(nèi)發(fā)生的鼠標(biāo)命令進(jìn)行處理。實(shí)現(xiàn)常居頂層高級(jí)窗口拖動(dòng)功能的首要問題,是如何檢測(cè)和處理特定客戶命令區(qū)域和非特定客戶命 令區(qū)域內(nèi)的鼠標(biāo)命令,以及如何利用鼠標(biāo)光標(biāo)來動(dòng)態(tài)提示用戶此時(shí)可以進(jìn)行窗口的拖動(dòng)操作。 1、在特定客戶區(qū)域檢測(cè)鼠標(biāo)命令的方法 當(dāng)窗口中設(shè)置了實(shí)現(xiàn)拖動(dòng)功能的圖標(biāo)命令按鈕時(shí),就必須在資源文件中定義命令按鈕的特定客戶區(qū)域,該區(qū)域一般也就是顯示命令 按鈕中圖標(biāo)的矩形區(qū)域,這個(gè)區(qū)域的定義方法為"RECT DragRT",其中DragRT為定義的檢測(cè)鼠標(biāo)命令矩形區(qū)域,它用DragRT.LEFT、DragRT.TOP、DragRT.RIGHT和 DragRT.BOTTOM四個(gè)參數(shù)來描述矩形區(qū)域相對(duì)于窗口客戶區(qū)域左上角的相對(duì)坐標(biāo)值,這四個(gè)參數(shù)必須事先定義具體的數(shù)值,也可以利 用"SETRECT"函數(shù)直接填充。 窗口函數(shù)在處理鼠標(biāo)消息WM_LBUTTONDOWN時(shí),在接收系統(tǒng)傳遞的鼠標(biāo)位置參數(shù)lParam后,通過 MAKEPOINT( )函數(shù)將其轉(zhuǎn)換為窗口坐標(biāo)值,利用判斷某坐標(biāo)點(diǎn)是否位于特定矩形區(qū)域內(nèi)的函數(shù)PtInRect(),就可以判斷鼠標(biāo)指針是否點(diǎn)擊在拖動(dòng)命令按鈕之內(nèi),從而 完成窗口拖動(dòng)功能的啟動(dòng)任務(wù)。其描述性功能代碼示例如下: | case WM_LBUTTONDOWN://鼠標(biāo)光標(biāo)點(diǎn)擊處理 POINT pt;//鼠標(biāo)在屏幕上位置指針,包括pt.X和pt.Y兩個(gè)參數(shù), //該指針值利用MAKEPOINT通過lParam參數(shù)轉(zhuǎn)換而來 pt=MAKEPOINT(lParam); //獲取鼠標(biāo)當(dāng)前屏幕位置指針 if(PtInRect(&DragRT,pt)){//判斷鼠標(biāo)是否點(diǎn)擊在拖動(dòng)按鈕內(nèi) //實(shí)現(xiàn)鼠標(biāo)拖動(dòng)窗口方案的啟動(dòng)功能 } else { //進(jìn)行其它特定或非特定命令客戶區(qū)域判斷處理 } break; |
2、在非特定客戶區(qū)域檢測(cè)鼠標(biāo)命令的方法 當(dāng)窗口應(yīng)用程序中采取了非特定客戶區(qū)域拖動(dòng)方法時(shí),必須在資源文件中事先確定各個(gè)特定客戶區(qū)域的矩形坐標(biāo),這時(shí)非特定客戶 區(qū)域是不規(guī)則的區(qū)域,它需要根據(jù)實(shí)際的應(yīng)用程序窗口及各個(gè)命令按鈕矩形區(qū)域來確定,也就是各個(gè)命令按鈕相對(duì)于窗口矩形區(qū)域的“非”子集。窗口函數(shù)在處理鼠 標(biāo)消息WM_LBUTTONDOWN時(shí),首先利用函數(shù)PtInRect()判斷當(dāng)前鼠標(biāo)指針是否點(diǎn)擊在各個(gè)命令按鈕矩形區(qū)域內(nèi),如果未點(diǎn)擊在任何命令按鈕 區(qū)域內(nèi),則可確定鼠標(biāo)點(diǎn)擊在非特定客戶區(qū)域內(nèi),從而實(shí)現(xiàn)窗口拖動(dòng)功能的啟動(dòng)。其描述性功能代碼示例如下: | case WM_LBUTTONDOWN: //鼠標(biāo)光標(biāo)點(diǎn)擊處理 POINT pt; //定義鼠標(biāo)在屏幕上的位置指針 pt=MAKEPOINT(lParam); //取得鼠標(biāo)光標(biāo)當(dāng)前位置指針 for(I=0;I if(PtInRect(&DragRT[I],pt)){//DragRT[I]為按鈕矩形數(shù)組 break; //鼠標(biāo)點(diǎn)擊在其它按鈕上中斷 } } if(I //鼠標(biāo)點(diǎn)擊在其它特定客戶區(qū)域內(nèi)則處理其它按鈕功能 }else{ //鼠標(biāo)點(diǎn)擊在非客戶區(qū)域內(nèi)則完成窗口拖動(dòng)方案的啟動(dòng) } break; |
3、窗口拖動(dòng)功能的鼠標(biāo)光標(biāo)動(dòng)態(tài)提示方法 在無標(biāo)題條常居頂層高級(jí)窗口應(yīng)用程序中,既可以采用將特定客戶區(qū)域作為拖動(dòng)命令按鈕的方法,也可以采取在非特定客戶區(qū)域檢 測(cè)窗口拖動(dòng)命令的方法,或者兩種方法兼顧使用。在使用第一種方法時(shí),可以在命令按鈕中用特定的圖標(biāo)或文字來提示用戶該命令按鈕的功能,而后一種方法由于矩 形區(qū)域無法確定不可能用圖標(biāo)或文字來提示,或根本無法顯示圖標(biāo)和文字(如非特定客戶區(qū)域?yàn)榇翱谶吔鐓^(qū)域等),用戶根本無法知道非特定客戶區(qū)域具有拖動(dòng)窗口 功能,這時(shí)唯有充分利用鼠標(biāo)光標(biāo)的動(dòng)態(tài)提示功能,就象WINDOWS 普通窗口中鼠標(biāo)光標(biāo)停在窗口邊框上時(shí)鼠標(biāo)光標(biāo)變成雙箭頭形狀來提示用戶此時(shí)可以改變窗口大小那樣,這個(gè)功能在高級(jí)窗口界面設(shè)計(jì)中非常重要。 實(shí)現(xiàn)鼠標(biāo)光標(biāo)動(dòng)態(tài)提示功能前需要定制鼠標(biāo)光標(biāo)形狀,窗口拖動(dòng)功能的動(dòng)態(tài)提示光標(biāo)形狀一般為四箭頭圖案,這可以利用微軟公司 的SDK、FPT3.0和VC++4.1等高級(jí)開發(fā)軟件中的資源編輯器"IMAGE EDIT"等來實(shí)現(xiàn)。光標(biāo)資源文件一般為32X32的2色或16色.CUR圖形文件,可根據(jù)實(shí)現(xiàn)的功能來具體確定光標(biāo)圖案或直接使用WINDOWS 系統(tǒng)中提供的光標(biāo)資源文件,當(dāng)自己利用資源編輯器繪制光標(biāo)圖案后,還需要利用DEBUG. EXE程序修改光標(biāo)資源文件中的鼠標(biāo)光標(biāo)顯示偏移坐標(biāo),以便光標(biāo)圖案能象WINDOWS 系統(tǒng)中的動(dòng)態(tài)提示光標(biāo)一樣,動(dòng)態(tài)提示時(shí)光標(biāo)圖案中心點(diǎn)正好處于屏幕的當(dāng)前位置。這個(gè)偏移坐標(biāo)值位于光示資源文件中的10和12處的雙字節(jié)位置,如動(dòng)態(tài)提示 光標(biāo)資源文件名為MOUSEM.CUR,要使32X32(2色)的光標(biāo)圖形顯示時(shí)圖案的中心點(diǎn)正好處于當(dāng)前屏幕位置,其修改方法如下: | C>DEBUG MOUSEM.CUR -E 10A XXXX:10A 00.10 00.00 00.10 00.00 -W |
建立起自己的鼠標(biāo)光標(biāo)資源文件后,首先需要在應(yīng)用程序的資源文件中定義鼠標(biāo)光標(biāo),資源文件中的定義方法為: | imecurm CURSOR mousem.cur |
鼠標(biāo)光標(biāo)資源文件只有在定義之后,才能在應(yīng)用程序中利用LoadCursor()函數(shù)調(diào)入內(nèi)存使用,其調(diào)用方法為: | HCURSOR hCurm;//將鼠標(biāo)光標(biāo)資源文件數(shù)據(jù)調(diào)入內(nèi)存 hCurm=LoadCursor(hInstance,"imecurm"); |
當(dāng)需要?jiǎng)討B(tài)改變鼠標(biāo)光標(biāo)形狀的客戶區(qū)域?yàn)檎麄€(gè)窗口或某個(gè)子窗口的全部客戶區(qū)域時(shí),在注冊(cè)客戶應(yīng)用程序窗口類時(shí)定義相應(yīng)的鼠 標(biāo)光標(biāo)資源句柄,當(dāng)鼠標(biāo)光標(biāo)移到相應(yīng)窗口內(nèi)時(shí)立刻變成定制的光標(biāo)形狀,移出相應(yīng)窗口時(shí)自動(dòng)恢復(fù)原來光標(biāo)形狀。實(shí)現(xiàn)鼠標(biāo)光標(biāo)這一動(dòng)態(tài)提示功能的定義方法如 下: 當(dāng)鼠標(biāo)光標(biāo)需要在窗口的特定客戶命令按鈕區(qū)域內(nèi)或非特定客戶命令區(qū)域內(nèi)進(jìn)行動(dòng)態(tài)提示時(shí),就不能使用上述定義方法,必須在窗 口函數(shù)處理WM_MOUSEMOVE消息時(shí)進(jìn)行特殊處理:首先判斷鼠標(biāo)光標(biāo)指針當(dāng)前位置是否在拖動(dòng)命令按鈕或非特定客戶區(qū)域內(nèi)移動(dòng),如果鼠標(biāo)指針位置滿足 拖動(dòng)窗口功能區(qū)域的要求,則利用API函數(shù)SETCURSOR()改變鼠標(biāo)光標(biāo)圖案,提示用戶此時(shí)可以進(jìn)行窗口拖動(dòng)操作,并將鼠標(biāo)輸入控制權(quán)交給當(dāng)前窗 口,同時(shí)設(shè)置改變鼠標(biāo)光標(biāo)標(biāo)志;當(dāng)鼠標(biāo)指針移出拖動(dòng)窗口啟動(dòng)命令區(qū)域時(shí),恢復(fù)原來鼠標(biāo)光標(biāo)圖案同時(shí)釋放鼠標(biāo)輸入焦點(diǎn)控制權(quán),并清除鼠標(biāo)光標(biāo)動(dòng)態(tài)提示標(biāo)志單 元。其功能性代碼描述如下: | BOOL DragFlag; //動(dòng)態(tài)提示光標(biāo)標(biāo)志 case WM_MOUSEMOVE: //鼠標(biāo)光標(biāo)移動(dòng)處理 pt=MAKEPOINT(lParam); //鼠標(biāo)光標(biāo)當(dāng)前位置指針 if(PtInRect(&DragRT,pt)){//鼠標(biāo)指針在拖動(dòng)命令區(qū)域內(nèi)則 SetCursor(hCurm); //動(dòng)態(tài)改變鼠標(biāo)光標(biāo)形狀 SetCapture(hWnd); //將鼠標(biāo)輸入控制權(quán)交當(dāng)前窗口 iFlag=TRUE; //設(shè)置鼠標(biāo)光標(biāo)形狀改變標(biāo)志 } else if(iFlag==TRUE){ //鼠標(biāo)指針未在拖動(dòng)命令區(qū)域內(nèi) SetCursor(LoadCursor(NULL,IDC_ARROW));//恢復(fù)原形狀 ReleaseCapture() //釋放鼠標(biāo)輸入控制權(quán) iFlag=FALSE; //恢復(fù)鼠標(biāo)光標(biāo)形狀改變標(biāo)志 } break; |
二、WINDOWS高級(jí)窗口拖動(dòng)方案中拖動(dòng)框的客戶定制方法 以上介紹了窗口拖動(dòng)前鼠標(biāo)光標(biāo)位置檢測(cè)及客戶命令區(qū)域內(nèi)拖動(dòng)功能的鼠標(biāo)光標(biāo)動(dòng)態(tài)提示方法,當(dāng)用戶通過鼠標(biāo)光標(biāo)動(dòng)態(tài)提示功能 取得滿足拖動(dòng)窗口條件時(shí),通過點(diǎn)擊鼠標(biāo)左鍵來啟動(dòng)拖動(dòng)方案,這時(shí)最關(guān)鍵的技術(shù)問題是鼠標(biāo)拖動(dòng)窗口移動(dòng)過程中的拖動(dòng)框顯示與擦除功能實(shí)現(xiàn)。窗口拖動(dòng)虛框就是 在WINDOWS 整個(gè)屏幕區(qū)域內(nèi)顯示描述被拖動(dòng)窗口大小的線框,它的大小需要根據(jù)被拖動(dòng)窗口的矩形區(qū)域大小和實(shí)際需要來具體確定,一般情況下為被拖動(dòng)窗口的矩形區(qū)域大小。 WINDOWS 系統(tǒng)中的繪圖方法是通過顯示設(shè)備描述表實(shí)現(xiàn)的,繪圖操作需要占用一定的GDI 資源,系統(tǒng)為窗口、菜單、對(duì)話框、字體和各種繪圖函數(shù)分配足夠的GDI資源,WINDOWS 95中的GDI資源要比WINDOWS3.X中的GDI資源大得多。WINDOWS中有兩種使用顯示設(shè)備描述符表的方法:更新窗口顯示客戶區(qū)域和直接操作 窗口顯示客戶區(qū)域。更新窗口顯示客戶區(qū)域是直接針對(duì)應(yīng)用程序窗口矩形區(qū)域而言的,在窗口函數(shù)響應(yīng)WM_PAINT消息時(shí)利用圖形操作命令進(jìn)行窗口更新處 理: | InvalidateRect(hWnd,&WinRECT,TRUE);//WinRECT為要更新區(qū)域 UpdateWindow(hWnd); |
窗口初始建立時(shí)默認(rèn)更新窗口的全部區(qū)域,當(dāng)要更新的矩形區(qū)域?yàn)镹ULL時(shí)表示更新窗口所有矩形區(qū)域。函數(shù) UpdateWindow()通知系統(tǒng)向要更新矩形區(qū)域的窗口發(fā)送WM_PAINT消息,窗口函數(shù)接收到WM_PAINT消息后首先利用 BeginPaint()函數(shù)取得設(shè)備描述符表,然后利用圖形命令直接對(duì)顯示設(shè)備進(jìn)行更新操作,最后利用EndPaint()函數(shù)通知系統(tǒng)更新操作結(jié)束。 其描述性功能代碼如下: | case WM_PAINT: PAINTSTRUCT ps; hdc=BeginPaint(hWnd,&ps);//取得設(shè)備描述符表 SetBkMode(hdc,OPAQUE); //設(shè)備更新方式 SetBkColor(hdc,0x00c0c0c0); //更新矩形區(qū)域內(nèi)圖形操作 EndPaint(hWnd,&ps); //結(jié)束更新操作 break; |
更新窗口矩形區(qū)域直接使用窗口類中定義的屏幕畫刷,即使利用SelectObject()函數(shù)選擇相應(yīng)屏幕畫刷也無效,而 且更新矩形區(qū)域范圍是通過InvalidateRect()函數(shù)累加的,由UpdateWindow()函數(shù)通知系統(tǒng)開始進(jìn)行窗口更新操作,整個(gè)過程是由 系統(tǒng)來調(diào)度的,因此使用這種方法無法實(shí)現(xiàn)窗口的拖動(dòng)虛框繪制和實(shí)時(shí)操作。 直接操作窗口客戶區(qū)域的方法是利用GetDC( )函數(shù)直接取得顯示設(shè)備句柄,利用各種圖形操作命令直接對(duì)顯示設(shè)備進(jìn)行繪圖,它使用屏幕當(dāng)前設(shè)置的畫筆和畫刷來實(shí)現(xiàn)各種圖形繪制操作,無須系統(tǒng)任何消息應(yīng) 用程序就可以實(shí)時(shí)地對(duì)屏幕窗口進(jìn)行更新和繪圖操作。其操作過程是首先取得顯示設(shè)備描述符句柄: | HDC hDC; hDC=GetDC(hWnd);//取得hWnd窗口設(shè)備描述符表句柄 |
當(dāng)hWnd參數(shù)為NULL時(shí)取得的是整個(gè)屏幕的設(shè)備描述符表句柄,然后利用SelectObject()函數(shù)設(shè)置當(dāng)前屏幕 的畫筆和畫刷,就可以利用各種畫圖函數(shù)完成屏幕的繪圖操作,最后利用ReleaseDC( )函數(shù)釋放獲取的顯示設(shè)備描述表。由于這種方法可以直接控制當(dāng)前屏幕的畫筆和畫刷,并且無需系統(tǒng)調(diào)度就可以直接對(duì)屏幕設(shè)備進(jìn)行操作,因此利用這種方法完全 可以實(shí)現(xiàn)窗口的拖動(dòng)虛框。窗口的拖動(dòng)虛框是用來描述要移動(dòng)窗口大小的虛線框和實(shí)線框,當(dāng)矩形拖動(dòng)框?yàn)樘摼€時(shí),需要利用畫點(diǎn)或畫線函數(shù)經(jīng)過一定算法來實(shí)現(xiàn), 這就需要設(shè)置當(dāng)前的屏幕畫筆;當(dāng)窗口的拖動(dòng)框?yàn)閷?shí)線框時(shí),如果利用畫線函數(shù)只需設(shè)置屏幕畫筆即可,如果利用畫矩形函數(shù)Rectangle( )在設(shè)置當(dāng)前屏幕畫筆的同時(shí)必須使用SelectObject(hDC,GetStockObject(NULL_BRUSH))屏蔽掉任何屏幕畫刷,否 則WINDOWS程序會(huì)很快吞筮掉所有GDI資源,相當(dāng)于在屏幕設(shè)備資源中增加了無數(shù)矩形區(qū)域。 對(duì)于窗口拖動(dòng)框的擦除操作,只需在拖動(dòng)框繪制函數(shù)中將屏幕的圖形畫筆操作方式設(shè)置為R2_XORPEN異或方式,即 SetROP2(hDC2,R2_XORPEN),在拖動(dòng)框繪制結(jié)束時(shí)注意恢復(fù),然后在窗口拖動(dòng)框移動(dòng)到下一個(gè)位置前,在原屏幕位置重新調(diào)用繪制函數(shù)一次 將原來拖動(dòng)框擦除。下面給出筆者利用畫矩形、畫線和畫點(diǎn)函數(shù)實(shí)現(xiàn)的拖動(dòng)框函數(shù),用戶在使用時(shí)可選擇自己喜歡的實(shí)線或虛線拖動(dòng)框函數(shù)。 函數(shù)1為利用畫矩形函數(shù)實(shí)現(xiàn)的拖動(dòng)實(shí)框,其特點(diǎn)是函數(shù)的效果高,拖動(dòng)框作圖速度快;函數(shù)2為利用畫線函數(shù)實(shí)現(xiàn)的拖動(dòng)框,其 特點(diǎn)是通過設(shè)置不同的畫線類型可以畫虛框也可以畫實(shí)框;函數(shù)3為利用畫線函數(shù)實(shí)現(xiàn)的拖動(dòng)虛框函數(shù),特點(diǎn)是拖動(dòng)虛框圖案變化靈活,不足是函數(shù)效率低作圖速度 慢。函數(shù)通過參數(shù)可選擇不同的拖動(dòng)虛框圖案或密度。函數(shù)3參數(shù)XY為1時(shí)與WINDOWS 3.X窗口拖動(dòng)缺省虛框相同為單虛線框,如果XY參數(shù)為2 則拖動(dòng)虛框?yàn)榫佚X形邊框。也可以根據(jù)需要選擇不同的拖動(dòng)虛框圖案和相應(yīng)畫筆和畫刷以達(dá)到不同的效果。 | //函數(shù)1:利用畫矩形函數(shù)實(shí)現(xiàn)拖動(dòng)實(shí)框 void DrawMoveRect(int xx1,int yy1,int xx2,int yy2,int xy) { HDC hDC; int oldrop2,m,k; hDC = GetDC(NULL); //取得全屏幕設(shè)備描述句柄 oldrop2= GetROP2(hDC); //取得原來屏幕畫圖方式 SetROP2(hDC,R2_XORPEN); //設(shè)置異或屏幕畫圖方式 SelectObject(hDC,GetStockObject(NULL_BRUSH));//屏蔽畫刷 SelectObject(hDC2,GetStockObject(WHITE_PEN));//選擇畫筆 for (k=0;k xx1-=1; xx2+=1; yy1-=1; yy2+=1; Rectangle(hDC2,xx1,yy1,xx2,yy2); } SetROP2(hDC2,oldrop2); //恢復(fù)原來作圖方式 ReleaseDC(NULL,hDC2); //釋放設(shè)備描述符表 } //函數(shù)2:利用畫線函數(shù)實(shí)現(xiàn)拖動(dòng)實(shí)框或虛框 void DrawMoveRect(int xx1,int yy1,int xx2,int yy2,int xy) { HDC hDC2; int oldrop2,m,k; hDC = GetDC(NULL); //取得全屏幕設(shè)備描述句柄 oldrop2= GetROP2(hDC); //取得原來屏幕畫圖方式 SetROP2(hDC,R2_XORPEN); //設(shè)置異或屏幕畫圖方式 SelectObject(hDC,GetStockObject(NULL_BRUSH));//屏蔽畫刷 SelectObject(hDC2,GetStockObject(WHITE_PEN));//選擇畫筆 for (k=0;k xx1-=1; xx2+=1; yy1-=1; yy2+=1; MoveTo(hDC2,xx1,yy1); LineTo(hDC2,xx2,yy1); MoveTo(hDC2,xx1,yy1); LineTo(hDC2,xx2,yy1); } SetROP2(hDC2,oldrop2); //恢復(fù)原來作圖方式 ReleaseDC(NULL,hDC2); //釋放設(shè)備描述符表 } //函數(shù)3:利用畫點(diǎn)函數(shù)實(shí)現(xiàn)不同圖案的拖動(dòng)虛框 void DrawMoveRect(int xx1,int yy1,int xx2,int yy2,int xy) { HDC hDC2; int oldrop2,I,j,x1,x2,y1,y2; hDC = GetDC(NULL); //取得全屏幕設(shè)備描述句柄 oldrop2= GetROP2(hDC); //取得原來屏幕畫圖方式 SetROP2(hDC,R2_XORPEN); //設(shè)置異或屏幕畫圖方式 SelectObject(hDC,GetStockObject(NULL_BRUSH));//屏蔽畫刷 SelectObject(hDC2,GetStockObject(WHITE_PEN));//選擇畫筆 for (j=0;j x1=xx1-j; //帶注釋部分為另一圖案 x2=xx2+j; y1=yy1-j; y2=yy2+j; for (I=x1;I SetPixel(hdc,I,y1,RGB(255,0,0)); //if (I for (I=y1;I SetPixel(hdc,x2,I,RGB(255,0,0)); //if (I for (I=x2;I>x1;I-=2) SetPixel(hdc,I,y2,RGB(255,0,0)); //if (I>x1+2) SetPixel(hdc,I-1,y2-1,RGB(255,0,0));} for (I=y2;I>y1;I-=2) SetPixel(hdc,x1,I,RGB(255,0,0)); //if (I>y1+2) SetPixel(hdc,x1+1,I-1,RGB(255,0,0));} } SetROP2(hDC2,oldrop2); //恢復(fù)原來作圖方式 ReleaseDC(NULL,hDC2); //釋放設(shè)備描述符表 } ? |
三、WINDOWS高級(jí)窗口客戶區(qū)域拖動(dòng)技術(shù)實(shí)現(xiàn)的“三步曲” WINDOWS 高級(jí)窗口的客戶區(qū)域拖動(dòng)命令判斷、拖動(dòng)功能的鼠標(biāo)光標(biāo)動(dòng)態(tài)提示和定制窗口拖動(dòng)框函數(shù)之后,就需要實(shí)現(xiàn)整個(gè)拖動(dòng)方案中的拖動(dòng)過程啟動(dòng)、窗口拖動(dòng)框移動(dòng)和拖動(dòng) 結(jié)束處理的三步曲過程。于是必須在窗口函數(shù)中直接處理WM_LBUTTONDOWN、WM_MOUSEMOVE和WM_LBUTTONUP消息,來具體處 理上述三個(gè)步驟中的細(xì)節(jié)問題。 第一步,在窗口函數(shù)中對(duì)鼠標(biāo)點(diǎn)擊消息WM_LBUTTONDOWN進(jìn)行判斷處理,以處理用戶通過鼠標(biāo)光標(biāo)動(dòng)態(tài)提示功能獲取滿足窗口拖動(dòng)條件時(shí),按下鼠標(biāo)左鍵產(chǎn)生的啟動(dòng)拖動(dòng)過程消息,其功能性代碼如下: | POINT pt; BOOL MoveFlag=FALSE; case WM_LBUTTONDOWN: pt = MAKEPOINT(lParam); //獲取鼠標(biāo)光標(biāo)指針 if(PtInRect(&DragRT,pt)){//DragRT為拖動(dòng)命令區(qū)域 DragBegin((LPRECT)&WinRT,lParam,hWnd,2); //啟動(dòng)窗口拖動(dòng)過程 } else {進(jìn)行其它處理} break; |
? 上述DragBegin( )函數(shù)為筆者開發(fā)的窗口拖動(dòng)啟動(dòng)函數(shù),由于一個(gè)高級(jí)窗口應(yīng)用程序中往往存在很多窗口,所以將其作為一個(gè)單獨(dú)函數(shù)處理。其中WinRT 為高級(jí)窗口矩形區(qū)域,這里作為拖動(dòng)框矩形區(qū)域參數(shù)來傳遞,lParam為鼠標(biāo)光標(biāo)指針長(zhǎng)整數(shù),hWnd為當(dāng)前被拖動(dòng)窗口的句柄,2 為拖動(dòng)框?qū)挾取M瑫r(shí)需要將鼠標(biāo)控制權(quán)交給當(dāng)前被拖動(dòng)窗口、設(shè)置拖動(dòng)窗口標(biāo)志單元、保存當(dāng)前鼠標(biāo)在屏幕上的位置并顯示被拖動(dòng)窗口的拖動(dòng)框。拖動(dòng)功能啟動(dòng)函數(shù) 的原形代碼如下: | void DragBegin( LPRECT WinRect, //拖動(dòng)框的矩形區(qū)域 LPARAM lParam, //鼠標(biāo)光標(biāo)當(dāng)前指針 HWND hwnd, //當(dāng)前窗口句柄 unsigned int kk) //拖動(dòng)框顯示的寬度 { SetCapture(hwnd); //拖動(dòng)時(shí)窗口必須具有鼠標(biāo)輸入權(quán) MoveFlag=TRUE; //設(shè)置拖動(dòng)標(biāo)志 oldmx=LOWORD(lParam);//記錄 |
|