VisualC網(wǎng)絡(luò)編程案例實(shí)戰(zhàn)之FTP客戶端實(shí)現(xiàn)之二_第1頁(yè)
VisualC網(wǎng)絡(luò)編程案例實(shí)戰(zhàn)之FTP客戶端實(shí)現(xiàn)之二_第2頁(yè)
VisualC網(wǎng)絡(luò)編程案例實(shí)戰(zhàn)之FTP客戶端實(shí)現(xiàn)之二_第3頁(yè)
VisualC網(wǎng)絡(luò)編程案例實(shí)戰(zhàn)之FTP客戶端實(shí)現(xiàn)之二_第4頁(yè)
VisualC網(wǎng)絡(luò)編程案例實(shí)戰(zhàn)之FTP客戶端實(shí)現(xiàn)之二_第5頁(yè)
已閱讀5頁(yè),還剩83頁(yè)未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

1、第5章 FTP客戶端實(shí)現(xiàn)之二 前面的章節(jié)4實(shí)現(xiàn)過(guò)一個(gè)FTP客戶端程序,那么為什么這里又要實(shí)現(xiàn)呢?區(qū)別有二,F(xiàn)TP客戶端所基于的應(yīng)用程序框架不同,第4章基于對(duì)話框,本章將基于SDI開(kāi)發(fā);開(kāi)發(fā)時(shí)的精力分配不同,第4章的精力主要集中在與FTP服務(wù)器的“交流”上,本章將把這種底層的工作交給MFC封裝的類(lèi)來(lái)實(shí)現(xiàn),主要精力會(huì)集中在界面的美化上。5.1 FTP客戶端簡(jiǎn)介 這節(jié)將會(huì)帶領(lǐng)大家快速了解下本章將要實(shí)現(xiàn)的FTP客戶端的各種功能。包括:以樹(shù)形視圖瀏覽本地文件夾資源、列表方式顯示FTP服務(wù)器上的文件資源、用過(guò)拖動(dòng)文件的方式實(shí)現(xiàn)文件的上傳和下載。5.1.1 樹(shù)形結(jié)構(gòu)的應(yīng)用 在主窗體的左側(cè)視圖中顯示選定本地文

2、件夾內(nèi)的所有文件資源,結(jié)構(gòu)為樹(shù)形,可以動(dòng)態(tài)的改變本地文件夾的選擇,如圖5.1所示。前方有加號(hào)說(shuō)明路徑中還有子路徑,單擊加號(hào)打開(kāi)此路徑,加號(hào)變減號(hào),子文件將顯示在子樹(shù)中。鼠標(biāo)移過(guò)此視圖時(shí)樹(shù)子項(xiàng)會(huì)加亮顯示。圖標(biāo)H表示文件夾、圖標(biāo)F表示文件。圖5.1. 本地文件夾資源顯示5.1.2 列表結(jié)構(gòu)的應(yīng)用 在主窗體的右側(cè)視圖中,將以列表圖標(biāo)的形式顯示FTP服務(wù)器下的所有文件資源,如圖5.2所示。圖5.2 FTP服務(wù)器上文件資源5.1.3 信息框的應(yīng)用 在主窗體的正中央有個(gè)信息的顯示框,是用于描述用戶的一些操作,如圖5.3所示。圖5.3 信息顯示框5.1.4 浮動(dòng)對(duì)話框的應(yīng)用 主程序的最頂端是用來(lái)填寫(xiě)本地文件

3、夾路徑和連接FTP服務(wù)器的浮動(dòng)對(duì)話框,如圖5.4所示。圖5.4 浮動(dòng)對(duì)話框 那么,最后來(lái)看一下本章FTP客戶端的全貌吧,如圖5.5所示。圖5.5 FTP客戶端全貌5.2 關(guān)鍵技術(shù)講解 這節(jié)主要介紹本章要用到的所有關(guān)鍵技術(shù),包括如何制作浮動(dòng)對(duì)話框,然后像工具欄一樣加到菜單之下;如何將客戶區(qū)分欄;如何實(shí)現(xiàn)對(duì)樹(shù)形和列表視圖項(xiàng)目的拖動(dòng)。 我們創(chuàng)建的工程是基于SDI的,命名為FtpClient。在向?qū)У牡?步,我們選擇CFtpClientView基于CListView類(lèi),如圖5.6所示。圖5.6 修改CFtpClientView的基類(lèi)5.2.1 制作、使用浮動(dòng)對(duì)話框 浮動(dòng)對(duì)話框,顧名思義就是可以浮動(dòng)在主

4、窗體之上。制作方法如下: (1)在資源視圖中插入對(duì)話框資源,修改ID為IDD_FLOAT_DLG,修改屬性:去掉對(duì)話框的邊緣,將style改為child,如圖5.7所示。圖5.7 對(duì)話框?qū)傩栽O(shè)置 (2)為對(duì)話框拖放控件,然后進(jìn)行設(shè)計(jì),怎么好看怎么擺放吧!我的設(shè)計(jì)如圖5.8所示。你們?cè)谇懊嬉?jiàn)過(guò)了,但還是想讓大家看看,因?yàn)槲以黾恿诵聝?nèi)容。圖5.8 浮動(dòng)對(duì)話框界面設(shè)計(jì) (3)在CMainFrame中添加一個(gè)浮動(dòng)對(duì)話框的變量m_myDlg。 在CMainFrame的OnCreate()成員函數(shù)中完成兩個(gè)任務(wù):去掉由向?qū)槲覀兲砑拥墓ぞ邫诤蜖顟B(tài)欄,它們影響到了我們程序的美觀;添加顯示我們剛才設(shè)計(jì)的對(duì)話框

5、的代碼。 程序中去掉了工具欄和狀態(tài)欄的功能,所以你可以將代表兩個(gè)工具的對(duì)象m_wndStatusBar、m_wndToolBar也注釋掉,它們就定義在類(lèi)CMainFrame的頭文件中,如下: 不注釋掉也并不會(huì)影響程序的編譯執(zhí)行,讀者可自由處理。通過(guò)調(diào)用類(lèi)CDialogBar的成員函數(shù)Create(),裝載我們?cè)O(shè)計(jì)的對(duì)話框資源模版、創(chuàng)建對(duì)話框窗口、設(shè)置它的樣式,最后關(guān)聯(lián)窗口到CDialogBar對(duì)象m_myDlg上。函數(shù)原型如下:virtual BOOL Create( CWnd* pParentWnd, UINT nIDTemplate, UINT nStyle, UINT nID );參數(shù)含

6、義如下:pParentWnd:指向裝載浮動(dòng)對(duì)話框的父窗口的指針,我們直接使用了this。其它成員函數(shù)如EnableDocking()的使用很簡(jiǎn)單,代碼中已經(jīng)加入了注釋?zhuān)筒蛔鲈斀庵v解了。 那么,編譯運(yùn)行程序就會(huì)發(fā)現(xiàn)工具欄、狀態(tài)欄消失了,取而代之的是我們自己設(shè)計(jì)的浮動(dòng)對(duì)話框,用鼠標(biāo)嘗試拖動(dòng)它,會(huì)有如圖5.9所示效果。圖5.9 拖動(dòng)浮動(dòng)對(duì)話框 你當(dāng)然可以任意移動(dòng)它,甚至是單擊它上面的關(guān)閉按鈕來(lái)關(guān)閉它,不過(guò)關(guān)閉了以后就比較麻煩了,因?yàn)槲覀冃枰匦聠?dòng)程序來(lái)讓它再次顯示。本程序沒(méi)有實(shí)現(xiàn)再次顯示浮動(dòng)窗口功能,讀者可以自己實(shí)現(xiàn)下。5.2.2 客戶區(qū)的分割 我們需要將整個(gè)客戶區(qū)分割為3個(gè)部分:用于顯示用戶操

7、作的信息窗口、用于顯示本地文件夾資源的樹(shù)形視圖窗口和用于顯示FTP服務(wù)器上文件資源的列表視圖窗口。效果如圖5.10所示。圖5.10 窗口分割效果圖 為類(lèi)CMainFrame添加兩個(gè)成員變量,如下: 類(lèi)CSplitterWnd提供了分割窗口的功能,就是一個(gè)窗口包含多個(gè)窗格。 為類(lèi)CMainFrame添加虛函數(shù)OnCreateClient()的實(shí)現(xiàn),程序編寫(xiě)如下: 調(diào)用類(lèi)CSplitterWnd的成員函數(shù)CreateStatic()創(chuàng)建靜態(tài)的分割窗口,函數(shù)原型如下: virtual BOOL CreateStatic( CWnd* pParentWnd, int nRows, int nCols,

8、 DWORD dwStyle = WS_CHILD | WS_VISIBLE, UINT nID = AFX_IDW_PANE_FIRST ); 參數(shù)含義如下: pParentWnd:分割窗口的父框架窗口。 第一次分割窗口時(shí),父窗口是框架CMainFrame,分割成2行1列。第二次分割窗口時(shí),是嵌入在第一次分割的窗口中的,所以父窗口為m_splitter1,分割為1行2列,嵌套的窗口ID通過(guò)類(lèi)CSplitterWnd的成員函數(shù)IdFromRowCol()獲得。 類(lèi)CSplitterWnd的成員函數(shù)CreateView()為靜態(tài)分割窗口創(chuàng)建窗格,原型如下: virtual BOOL Create

9、View( int row, int col, CRuntimeClass* pViewClass, SIZE sizeInit, CCreateContext* pContext ); 參數(shù)含義如下: row:指定放置新視圖的窗口行。調(diào)用類(lèi)CSplitterWnd的成員函數(shù)SetRowInfo()和SetColumnInfo()分別設(shè)置分割窗口的行高取值范圍、列寬取值范圍。函數(shù)原型如下:void SetRowInfo( int row, int cyIdeal, int cyMin );void SetColumnInfo( int col, int cxIdeal, int cxMin )

10、;參數(shù)含義如下:row、col:指定分割窗口的行、列,用于定位。 在函數(shù)OnCreateClient()中,我們將3個(gè)視圖CMsgShow、CFileTree和CFtpClientView指定到相應(yīng)的分割窗格中。前兩個(gè)是我們利用類(lèi)向?qū)砑拥男骂?lèi),分別基于類(lèi)CEditView和CTreeView,最后一個(gè)是我們創(chuàng)建工程時(shí)由向?qū)槲覀儎?chuàng)建的視圖類(lèi),基于類(lèi)CListView。至此客戶區(qū)分割的操作代碼填加完畢。5.2.3 樹(shù)形視圖項(xiàng)目拖動(dòng)效果 我們可以通過(guò)捕獲3個(gè)事件來(lái)添加拖動(dòng)效果的代碼,他們是:鼠標(biāo)左鍵選中項(xiàng)目并且開(kāi)始拖動(dòng)、鼠標(biāo)移動(dòng)和鼠標(biāo)左鍵抬起。1.選中視圖項(xiàng) 我們需要用類(lèi)向?qū)砑右粋€(gè)新類(lèi)CFil

11、eTree,基于CTreeView,如圖5.11所示。圖5.11 添加新類(lèi)CFileTree 在類(lèi)CFileTree的實(shí)現(xiàn)文件,添加文件包含指令如下: #include MainFrm.h #include FtpClientView.h 在利用類(lèi)向?qū)樗砑雍瘮?shù)OnBegindrag(),如圖5.12所示。圖5.12 為類(lèi)CFileTree添加消息響應(yīng)為函數(shù)OnBegindrag()添加代碼,如下:函數(shù)OnBegindrag()中的變量是類(lèi)CFileTree的公有成員變量,定義如下:成員變量在類(lèi)CFreeTree的構(gòu)造函數(shù)初始化如下: 類(lèi)CTreeCtrl的成員函數(shù)GetTreeCtrl()

12、返回樹(shù)視圖控件的引用。函數(shù)OnBegindrag()中結(jié)構(gòu)NM_TREEVIEW定義如下: typedef struct _NM_TREEVIEW NMHDR hdr; UINT action; TV_ITEM itemOld; TV_ITEM itemNew; POINT ptDrag; NM_TREEVIEW; 參數(shù)含義如下: hdr:另一個(gè)包含通知消息信息的結(jié)構(gòu)NMHDR。 我們要從這個(gè)結(jié)構(gòu)中獲取兩個(gè)信息:itemNew.hItem和ptDrag。前者是個(gè)結(jié)構(gòu)TV_ITEM,用來(lái)指定或返回樹(shù)視圖項(xiàng)的屬性。結(jié)構(gòu)TV_ITEM的字段hItem放的是這個(gè)結(jié)構(gòu)指向樹(shù)視圖項(xiàng)的句柄HTREEITEM

13、,被保存在了m_hItemDragS變量中。 然后用到類(lèi)CTreeCtrl的1個(gè)成員函數(shù)和CImageList的2個(gè)成員函數(shù)完成圖像拖動(dòng)的準(zhǔn)備工作,它們是:CreateDragImage()用來(lái)為指定的樹(shù)視圖項(xiàng)創(chuàng)建拖動(dòng)時(shí)的位圖、BeginDrag()標(biāo)志拖動(dòng)位圖操作的開(kāi)始、DragEnter()用來(lái)在拖動(dòng)操作期間在指定的位置顯示位圖和鎖定更新。 函數(shù)BeginDrag()的原型如下: BOOL BeginDrag( int nImage, CPoint ptHotSpot ); 參數(shù)含義如下: nImage:索引號(hào)從0開(kāi)始的位圖號(hào),用來(lái)指定位圖。 函數(shù)DragEnter()的原型如下: sta

14、tic BOOL PASCAL DragEnter( CWnd* pWndLock, CPoint point ); 參數(shù)含義如下: pWndLock:指向擁有拖動(dòng)圖像的窗口指針。若參數(shù)賦值為NULL,這個(gè)函數(shù)拖動(dòng)圖像的坐標(biāo)是相對(duì)于桌面窗口的,即屏幕坐標(biāo)的左上角。 所以我們?cè)谑褂煤瘮?shù)DragEnter()的時(shí)候,用到類(lèi)CWnd的成員函數(shù)ClientToScreen(),將給定的客戶區(qū)點(diǎn)坐標(biāo)轉(zhuǎn)換為屏幕點(diǎn)坐標(biāo)。最后我們同樣調(diào)用類(lèi)CWnd的成員函數(shù)SetCapture(),以后不管鼠標(biāo)的位置在哪里,所有的鼠標(biāo)后續(xù)輸入都會(huì)被送到當(dāng)前的窗口處理。 至此,鼠標(biāo)左鍵選中項(xiàng)目并且開(kāi)始拖動(dòng)事件的捕捉和處理代碼填

15、寫(xiě)和解釋完畢。2.圖像隨鼠標(biāo)移動(dòng) 利用類(lèi)向?qū)轭?lèi)CFileTree添加下一個(gè)事件:鼠標(biāo)移動(dòng)。如圖5.13所示。圖5.13 添加鼠標(biāo)移動(dòng)事件為函數(shù)OnMouseMove()添加代碼,如下:函數(shù)OnMouseMove()首先調(diào)用AfxGetMainWnd(),獲取指向當(dāng)前程序主框架CMainFrame的指針,保存在變量mFrm中,通過(guò)此變量調(diào)用其成員變量m_splitter2的成員函數(shù),既類(lèi)CSplitterWnd的成員函數(shù)GetPane(),得到指定行列窗格的指針。這里獲取的是列表視圖窗格的指針,保存在變量pEView中。 我們要在類(lèi)CFileTree中添加一個(gè)自定義的成員函數(shù)GetCtrlRe

16、ct(),如圖5.14所示。圖5.14 添加自定義的成員函數(shù)添加如下很簡(jiǎn)單的一段代碼就行:簡(jiǎn)單的封裝了兩個(gè)函數(shù),分別完成功能:獲取樹(shù)視圖窗口的矩形大小,即窗口大小。然后將坐標(biāo)轉(zhuǎn)換為相對(duì)屏幕的坐標(biāo)值。同樣需要在類(lèi)CFtpClientView中添加這樣一個(gè)自定義的函數(shù)GetCtrlRect(),代碼一樣,功能當(dāng)然也一樣,如下:函數(shù)OnMouseMove()接下來(lái)完成的功能是:創(chuàng)建兩個(gè)“區(qū)域”。實(shí)例化兩個(gè)類(lèi)CRgn的對(duì)象listRgn和treeRgn,調(diào)用類(lèi)CRgn的成員函數(shù)CreateRectRgn()創(chuàng)建兩個(gè)矩形區(qū)域,分別覆蓋了樹(shù)形結(jié)構(gòu)視圖、列表結(jié)構(gòu)視圖。 函數(shù)CreateRectRgn()的原

17、型如下: BOOL CreateRectRgn( int x1, int y1, int x2, int y2 ); 參數(shù)含義如下: x1、y1:指定矩形區(qū)域左上角點(diǎn)的坐標(biāo)位置。 函數(shù)OnMouseMove()最后會(huì)判斷:鼠標(biāo)是否處于拖動(dòng)的狀態(tài),是在樹(shù)形結(jié)構(gòu)視圖區(qū)域或者列表結(jié)構(gòu)視圖區(qū)域中嗎.通過(guò)類(lèi)CRgn的成員函數(shù)PtInRegion()判斷指定的點(diǎn)是否在指定的區(qū)域范圍內(nèi)。 在指定的區(qū)域范圍內(nèi),并且當(dāng)前正處在拖動(dòng)的狀態(tài)下時(shí),就該調(diào)用拖動(dòng)操作的第4個(gè)函數(shù)了,它是類(lèi)CImageList的成員函數(shù)DragMove(),原型如下: static BOOL PASCAL DragMove( CPoint

18、 pt ); pt是拖動(dòng)操作時(shí),鼠標(biāo)新的位置點(diǎn)。這個(gè)函數(shù)移動(dòng)圖像到指定的新的坐標(biāo)點(diǎn),也就是圖像會(huì)隨著鼠標(biāo)移動(dòng)效果的展現(xiàn)。 若是不滿足剛才的判斷條件呢?是不是就什么都不做了?當(dāng)然不是,還有另一個(gè)有趣的效果需要實(shí)現(xiàn)。我們通過(guò)類(lèi)CTreeCtrl的成員函數(shù)HitTest()判斷:鼠標(biāo)點(diǎn)相對(duì)樹(shù)視圖控件的位置,若是在控件內(nèi)部的話,會(huì)返回指定位置樹(shù)視圖項(xiàng)的句柄,當(dāng)指定位置不在在任何一個(gè)樹(shù)視圖項(xiàng)上,則返回NULL。 即我們的鼠標(biāo)在樹(shù)視圖窗口上“劃過(guò)”,相應(yīng)的樹(shù)視圖項(xiàng)就會(huì)有“被選中”的效果。通過(guò)調(diào)用類(lèi)CTreeCtrl的成員函數(shù)SelectDropTarget(),重繪樹(shù)視圖相應(yīng)項(xiàng),以一種表明樹(shù)視圖項(xiàng)被選中的

19、樣式,參數(shù)是樹(shù)視圖項(xiàng)的句柄就行。 那么,鼠標(biāo)移動(dòng)圖像的代碼也填寫(xiě)和解釋完畢了。3.鼠標(biāo)圖像釋放 利用類(lèi)向?qū)轭?lèi)CFileTree添加最后一個(gè)事件:鼠標(biāo)左鍵彈起。如圖5.15所示。圖5.15 添加鼠標(biāo)左鍵彈起事件 為函數(shù)OnLButtonUp()添加代碼,如下: 函數(shù)OnLButtonUp()會(huì)調(diào)用AfxGetMainWnd()獲取本程序主框架的指針,并保存在變量mFrm中,用mFrm通過(guò)其數(shù)據(jù)成員m_splitter2獲取列表視圖窗格的指針。 當(dāng)確定鼠標(biāo)是在拖動(dòng)圖像的時(shí)候左鍵才彈起的,即m_bDragging為true時(shí),我們用最后2個(gè)函數(shù)來(lái)完成拖動(dòng)操作。它們是類(lèi)CImageList的成員函數(shù)

20、:DragLeave()用來(lái)解鎖參數(shù)指定的窗口、隱藏圖像、允許窗口更新;EndDrag()用來(lái)結(jié)束拖動(dòng)操作。函數(shù)原型如下: static BOOL PASCAL DragLeave( CWnd* pWndLock ); static void PASCAL EndDrag( ); 通過(guò)函數(shù)ReleaseCapture()釋放鼠標(biāo)的捕獲。然后就是我們應(yīng)該很熟悉的操作了,獲取列表視圖矩形大小、創(chuàng)建覆蓋列表視圖的區(qū)域、判斷鼠標(biāo)點(diǎn)移動(dòng)到了創(chuàng)建的區(qū)域范圍之內(nèi)時(shí),添加任意的操作。5.2.4 列表視圖項(xiàng)目拖動(dòng)效果 與樹(shù)形視圖項(xiàng)目拖動(dòng)效果類(lèi)似,我們可以通過(guò)捕獲3個(gè)事件來(lái)添加拖動(dòng)效果的代碼,他們是:鼠標(biāo)左鍵選中

21、項(xiàng)目并且開(kāi)始拖動(dòng)、鼠標(biāo)移動(dòng)和鼠標(biāo)左鍵抬起。 首先需要在類(lèi)CFtpClientView的實(shí)現(xiàn)文件頭部添加文件包含指令如下: #include MainFrm.h #include FileTree.h 在類(lèi)CFtpClientView的頭文件添加類(lèi)的聲明,代碼如下: class CFtpClientDoc;1.選中視圖項(xiàng) 利用類(lèi)向?qū)轭?lèi)CFtpClientView添加函數(shù)OnBegindrag(),如圖5.16所示。圖5.16 為類(lèi)CFileTree添加消息響應(yīng)為函數(shù)OnBegindrag()添加代碼,如下:函數(shù)OnBegindrag()中的變量是類(lèi)CFtpClientView的公有成員變量,定

22、義如下:成員變量在類(lèi)CFtpClientView的構(gòu)造函數(shù)初始化如下:函數(shù)OnBegindrag()會(huì)調(diào)用類(lèi)CListCtrl的2個(gè)成員函數(shù):GetNextItem()和CreateDragImage()。 GetNextItem()用來(lái)檢索滿足指定條件的列表項(xiàng),函數(shù)原型如下: int GetNextItem( int nItem, int nFlags ) const; 參數(shù)含義如下: nItem:開(kāi)始檢索時(shí)起始列表項(xiàng)的索引,若為-1將會(huì)匹配滿足nFlags所指條件的第一個(gè)列表項(xiàng),所指定的列表項(xiàng)不會(huì)被檢索。 CreateDragImage()用來(lái)為指定的列表項(xiàng)創(chuàng)建拖動(dòng)圖像,函數(shù)原型如下: C

23、ImageList* CreateDragImage( int nItem, LPPOINT lpPoint ); 參數(shù)含義如下: nItem:要?jiǎng)?chuàng)建拖動(dòng)圖像的列表項(xiàng)的索引。 函數(shù)OnBegindrag()剩下的操作,我們應(yīng)該很熟悉了才對(duì),包括:調(diào)用類(lèi)CImageList的成員函數(shù)BeginDrag(),標(biāo)志開(kāi)始拖動(dòng)圖像;調(diào)用類(lèi)CImageList的成員函數(shù)DragEnter(),鎖定視圖的更新;調(diào)用類(lèi)CWnd的成員函數(shù)SetCapture()捕獲鼠標(biāo)后續(xù)的所有事件。2.圖像隨鼠標(biāo)移動(dòng) 利用類(lèi)向?qū)轭?lèi)CFtpClientView添加下一個(gè)事件:鼠標(biāo)移動(dòng)。如圖5.17所示。圖5.17 添加鼠標(biāo)移

24、動(dòng)事件為函數(shù)OnMouseMove()添加代碼,如下:函數(shù)OnMouseMove()的實(shí)現(xiàn)過(guò)程同樣包括:獲取樹(shù)形視圖、列表視圖窗口矩形大小,創(chuàng)建覆蓋樹(shù)形視圖、列表視圖窗口的區(qū)域,檢測(cè)鼠標(biāo)處于拖動(dòng)圖像狀態(tài),而且在樹(shù)形視圖或列表視圖的區(qū)域范圍內(nèi),調(diào)用類(lèi)CImageList的成員函數(shù)DragMove()拖動(dòng)圖像。3.鼠標(biāo)圖像釋放 利用類(lèi)向?qū)轭?lèi)CFtpClientView添加最后一個(gè)事件:鼠標(biāo)左鍵彈起。如圖5.18所示。圖5.18 添加鼠標(biāo)左鍵彈起事件為函數(shù)OnLButtonUp()添加代碼,如下:函數(shù)OnLButtonUp()實(shí)現(xiàn)的功能包括:解鎖拖動(dòng)窗口、結(jié)束拖動(dòng)操作、釋放鼠標(biāo)的捕獲、獲取樹(shù)視圖矩

25、形大小、創(chuàng)建覆蓋樹(shù)視圖的區(qū)域、判定鼠標(biāo)點(diǎn)在樹(shù)視圖區(qū)域之內(nèi)。5.3 實(shí)現(xiàn)FTP客戶端 這個(gè)實(shí)例是通過(guò)WinInet API來(lái)實(shí)現(xiàn)FTP客戶端的,因此無(wú)需考慮底層的通信協(xié)議和數(shù)據(jù)傳輸工作,所以我們把近一半的精力用在了華麗的程序界面上。5.3.1 WinInet類(lèi)介紹 MFC提供的WinInet類(lèi)是對(duì)WinInet API的封裝,為我們提供了更加方便的編程接口。主要用到兩個(gè)類(lèi):CInternetSession和CFtpConnection。1.CInternetSession類(lèi) 用來(lái)創(chuàng)建或者初始化一個(gè)或多個(gè)同步的網(wǎng)絡(luò)會(huì)話。它的構(gòu)造函數(shù)原型如下: CInternetSession( LPCTSTR p

26、strAgent = NULL, DWORD_PTR dwContext = 1, DWORD dwAccessType = PRE_CONFIG_INTERNET_ACCESS, LPCTSTR pstrProxyName = NULL, LPCTSTR pstrProxyBypass = NULL, DWORD dwFlags = 0 ); 我們的實(shí)例程序直接使用了所有的默認(rèn)參數(shù)值。當(dāng)我們要在服務(wù)器上執(zhí)行指定的服務(wù),如FTP服務(wù),必須要先建立連接,用到的成員函數(shù)是GetFtpConnection()。函數(shù)原型如下:CFtpConnection* GetFtpConnection( LPCT

27、STR pstrServer, LPCTSTR pstrUserName = NULL, LPCTSTR pstrPassword = NULL, INTERNET_PORT nPort = INTERNET_INVALID_PORT_NUMBER, BOOL bPassive = FALSE );參數(shù)含義如下:pstrServer:包含F(xiàn)TP服務(wù)器IP地址的字符串。bPassive:為這個(gè)會(huì)話指定被動(dòng)或主動(dòng)的模式,默認(rèn)為主動(dòng)模式。返回一個(gè)指向類(lèi)CFtpConnection的指針。2.CFtpConnection類(lèi) 此類(lèi)主要用于管理FTP服務(wù)連接,并允許用戶直接操作服務(wù)器目錄和文件。我們主要用

28、到了此類(lèi)的2個(gè)成員函數(shù):PutFile()用來(lái)上傳文件,GetFile()用來(lái)下載文件。函數(shù)原型如下: BOOL PutFile( LPCTSTR pstrLocalFile, LPCTSTR pstrRemoteFile, DWORD dwFlags = FTP_TRANSFER_TYPE_BINARY, DWORD_PTR dwContext = 1 ); 參數(shù)含義如下: pstrLocalFile:包含要上傳文件路徑的字符串。依據(jù)返回值判定上傳操作是否成功。函數(shù)GetFile()的原型如下:BOOL GetFile( LPCTSTR pstrRemoteFile, LPCTSTR pst

29、rLocalFile, BOOL bFailIfExists = TRUE, DWORD dwAttributes = FILE_ATTRIBUTE_NORMAL, DWORD dwFlags = FTP_TRANSFER_TYPE_BINARY, DWORD_PTR dwContext = 1 );參數(shù)含義如下:pstrRemoteFile:包含要接收FTP服務(wù)器上文件路徑的字符串。讀者可以依據(jù)函數(shù)GetFile()的返回值來(lái)判定下載操作是否成功。5.3.2 FTP服務(wù)器操作 通過(guò)浮動(dòng)對(duì)話框獲取用戶輸入的信息,調(diào)用類(lèi)的成員連接、登錄FTP服務(wù)器,最后將FTP服務(wù)器根目錄下的所有文件顯示在列表

30、視圖中。浮動(dòng)對(duì)話框如圖5.19所示。圖5.19 浮動(dòng)對(duì)話框 我們需要在類(lèi)CMainFrame中手動(dòng)添加“連接服務(wù)器”和“確定”按鈕的消息響應(yīng)函數(shù)OnConnect()和OnChooseDisc(),步驟如下: (1)在類(lèi)CMainFrame頭文件添加文件包含指令,用來(lái)支持WinInet類(lèi),如下: #include /為了使用CFtpConnect CInternetSession 在類(lèi)中添加成員變量和成員函數(shù),如下: (2)在類(lèi)CMainFrame的實(shí)現(xiàn)文件添加文件包含指令,用來(lái)支持3個(gè)分割窗口視圖,如下: #include MsgShow.h/3個(gè)窗體的頭文件 #include FileTr

31、ee.h #include FtpClientView.h 添加消息映射,即控件ID與處理事件函數(shù)建立聯(lián)系,如下: 添加了2個(gè)按鈕單擊事件的消息映射。類(lèi)CMainFrame的構(gòu)造函數(shù)如下: 可以看到,構(gòu)造函數(shù)只是初始化了一些成員變量。1.連接FTP服務(wù)器 編寫(xiě)按鈕“連接服務(wù)器”按鈕的消息響應(yīng)函數(shù)OnConnect(),如下: 響應(yīng)函數(shù)OnConnect()功能的實(shí)現(xiàn)步驟包括:獲取浮動(dòng)對(duì)話框上由用戶填寫(xiě)的登錄信息,保存在3個(gè)字符串變量中,他們是strHost、strName和strPass,調(diào)用類(lèi)CInternetSession的成員函數(shù)GetFtpConnection()連接FTP服務(wù)器,代碼

32、中對(duì)異常的情況做了一些處理,代碼包含在try和catch的語(yǔ)句塊中。 為類(lèi)CFtpClientView添加成員函數(shù)BrowseDir(),用來(lái)遍歷服務(wù)器根目錄下的所有文件,代碼編寫(xiě)如下: 函數(shù)BrowseDir()使用了類(lèi)CFtpFileFind,用來(lái)輔助FTP服務(wù)器上網(wǎng)絡(luò)文件的檢索。主要調(diào)用了此類(lèi)的5個(gè)成員函數(shù): FindFile()用來(lái)查找FTP服務(wù)器上指定的文件。 通過(guò)while循環(huán)將滿足條件的文件全部插入到列表視圖中。用類(lèi)CListCtrl的成員函數(shù)InsertItem()實(shí)現(xiàn),原型如下: int InsertItem( int nItem, LPCTSTR lpszItem, int

33、 nImage ); 參數(shù)含義如下: nItem:要將列表項(xiàng)插入索引視圖的位置。 類(lèi)CMsgShow我們提到過(guò),是我們自己新建的基于CEditView的類(lèi)。為此類(lèi)添加成員函數(shù)ShowMsg(),用來(lái)將指定的字符串顯示在信息顯示窗格中,代碼如下: 函數(shù)ShowMsg()中的m_editView是類(lèi)CMsgShow的成員變量,在類(lèi)CMsgShow的構(gòu)造函數(shù)中被初始化,代碼如下: 構(gòu)造函數(shù)調(diào)用了類(lèi)CEditView的成員函數(shù)GetEditCtrl(),用來(lái)獲取指向編輯視圖的指針,然后保存在成員變量m_editView中。 函數(shù)ShowMsg()的功能實(shí)現(xiàn)過(guò)程:獲取當(dāng)前編輯視圖窗格的文本內(nèi)容,依據(jù)之前

34、的內(nèi)容再添加新的文本信息。函數(shù)ShowMsg()還使用到類(lèi)CEditView繼承自類(lèi)CWnd的2個(gè)成員函數(shù): GetWindowText():獲取窗口的文本,并保存在傳入的參數(shù)字符串中。 用于連接服務(wù)器的函數(shù)OnConnect(),在連接到服務(wù)器以后會(huì):改變自身按鈕的文本為“斷開(kāi)連接”、將浮動(dòng)對(duì)話框上的文本框設(shè)置為禁用。2.斷開(kāi)連接 當(dāng)程序與FTP服務(wù)器處于連接狀態(tài)時(shí),我們?cè)俅螁螕簟皵嚅_(kāi)連接”按鈕時(shí),將關(guān)閉與服務(wù)器的連接,如下: 函數(shù)OnConnect()調(diào)用到了列表視圖的成員函數(shù)deleteItem(),用來(lái)清空列表視圖的所有列表項(xiàng),函數(shù)deleteItem()的實(shí)現(xiàn)如下: 很簡(jiǎn)單的函數(shù)封裝

35、,只是調(diào)用了類(lèi)CListCtrl的成員函數(shù)DeleteAllItems(),甚至連參數(shù)都不需要。 函數(shù)OnConnect()的后續(xù)操作包括:調(diào)用類(lèi)CFtpConnection的成員函數(shù)Close()關(guān)閉與FTP的連接,在信息顯示框中顯示文本信息“斷開(kāi)與服務(wù)器的連接”,改變“斷開(kāi)連接”按鈕的文本為“連接服務(wù)器”,最后將浮動(dòng)對(duì)話框中被禁用的文本框設(shè)置為可用。5.3.3 遍歷本地文件夾資源 用戶需要手動(dòng)填寫(xiě)“文件夾路徑”文本框,在單擊“確定”按鈕,樹(shù)結(jié)構(gòu)視圖中將會(huì)顯示出該文件夾下的所有文件資源。 為浮動(dòng)對(duì)話框的按鈕“確定”添加消息響應(yīng)函數(shù)OnChooseDisc(),功能代碼編寫(xiě)如下: 函數(shù)OnCh

36、ooseDisc()中,調(diào)用到類(lèi)CFileTree的成員函數(shù)deleteItem(),用來(lái)清除樹(shù)結(jié)構(gòu)視圖中的所有項(xiàng),實(shí)現(xiàn)如下: 同樣是很簡(jiǎn)單的函數(shù)封裝,只是調(diào)用了類(lèi)CTreeCtrl的成員函數(shù)DeleteAllItems(),甚至連參數(shù)都不需要。 類(lèi)CFileTree的成員函數(shù)BrowseDir(),用來(lái)實(shí)現(xiàn)遍歷文件夾中文件資源,并按結(jié)構(gòu)插入到樹(shù)中,實(shí)現(xiàn)代碼如下: 函數(shù)BrowseDir()的功能實(shí)現(xiàn)過(guò)程:構(gòu)造遍歷文件的字符串,調(diào)用類(lèi)CFileFind的6個(gè)成員函數(shù): FindFile()用來(lái)查找本地指定路徑下的文件資源。 IsDots()用來(lái)確定找到的文件的文件名是否包含“.”或“.”,它們

37、其實(shí)就是目錄。 IsDirectory()用來(lái)確定找到的文件是否是目錄。 類(lèi)CTreeCtrl的成員函數(shù)InsertItem()用來(lái)向樹(shù)結(jié)構(gòu)視圖中添加項(xiàng),函數(shù)原型如下: HTREEITEM InsertItem( LPCTSTR lpszItem, int nImage, int nSelectedImage, HTREEITEM hParent = TVI_ROOT, HTREEITEM hInsertAfter = TVI_LAST ); 參數(shù)含義如下: lpszItem:插入項(xiàng)的文本指針。 樹(shù)結(jié)構(gòu)視圖CFileTree關(guān)聯(lián)的圖像列表是在函數(shù)OnInitialUpdate()中確定的,代碼

38、如下: 我們當(dāng)然得先在資源編輯器中插入2個(gè)圖標(biāo)資源,一個(gè)用來(lái)表示文件,一個(gè)用來(lái)表示文件夾,如圖5.20所示。圖5.20 自己制作的小圖標(biāo) 類(lèi)CWinApp的成員函數(shù)LoadIcon(),將加載指定ID的圖標(biāo)資源,返回圖標(biāo)的句柄。創(chuàng)建圖標(biāo)列表調(diào)用到類(lèi)CImageList的成員函數(shù)Create(),函數(shù)原型如下: BOOL Create( int cx, int cy, UINT nFlags, int nInitial, int nGrow ); 參數(shù)含義如下: cx、cy:圖像的長(zhǎng)寬值,以像素為單位。 調(diào)用類(lèi)CImageList的成員函數(shù)Add(),將指定的圖標(biāo)句柄加入到圖像列表中,調(diào)用類(lèi)CTreeCtrl的成員函數(shù)SetImageList(),用來(lái)關(guān)聯(lián)樹(shù)結(jié)構(gòu)視圖與圖像列表,函數(shù)原型如下: CImageList* SetImageList( CImageList *pImageList, int nImageListType ); 參數(shù)含義如下: pImageList:指向圖像列表的指針。若為NUL

溫馨提示

  • 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

最新文檔

評(píng)論

0/150

提交評(píng)論