c++1.doc_第1頁
c++1.doc_第2頁
c++1.doc_第3頁
c++1.doc_第4頁
c++1.doc_第5頁
已閱讀5頁,還剩20頁未讀 繼續免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領

文檔簡介

CRect類介紹注意:這個類是從tagRECT結構派生而來的。(tagRECT是RECT結構的不太常用的別名。)這意味著RECT結構的數據成員(left,top,right,和bottom)也是CRect的可訪問數據成員。 一個CRect包含用于定義矩形的左上角和右下角點的成員變量。 當指定一個CRect時,必須謹慎地構造它,以使它符合規范也就是說,使其左坐標值小于右坐標值,使頂坐標值小于底坐標值。例如,左上角為(10,10),右下角為(20,20)就定義了一個符合規范的矩形,但是左上角為(20,20)而右下角為(10,10)的值就定義了一個不符合規范的矩形。如果矩形是不符合規范的,則CRect的許多成員函數都會符合不正確的結果。(參見CRect:NormalizeRect可以得到這些函數的列表。)在你調用一個要求符合規范的矩形的函數之前,你可以通過調用NormalizeRect函數來使不符合規范的矩形成為符合規范的矩形。 當用成員函數CDC:DPtoLP和CDC:LPtoDP來處理CRect時要小心。如果顯示環境的映射模式y-extent是負的,就像在MM_LOENGLISH中一樣,則CDC:DPtoLP將轉換CRect,以使它的頂部坐標大于底部坐標。然后像Height和Size這樣的函數將返回負值作為轉換后的矩形的高度,則此矩形將是不符合規范的。 當使用重載的CRect操作符時,第一個操作數必須是一個CRect;第二個操作數可以是一個RECT結構或一個CRect對象。CRect類介紹及GetClientRect函數功能該函數獲取窗口客戶區的坐標。客戶區坐標指定客戶區的左上角和右下角。由于客戶區坐標是相對窗口客戶區的左上角而言的,因此左上角坐標為(0,0) 函數原型 在Win32 SDK, 該API函數原型為 BOOL GetClientRect( HWND hWnd, / 窗口句柄 LPRECT lpRect / 客戶區坐標 ); 在MFC中,該函數的原型為void GetClientRect(LPRECT lpRect) const; 參數 hWnd:是程序窗口的句柄。 lpRect:是一個指針,指向一個RECT類型的rectangle結構。該結構有四個LONG字段,分別為left、top、right和bottom。GetClientRect將這四個字段設定為窗口顯示區域的尺寸。left和top字段通常設定為0。right和bottom字段設定為顯示區域的寬度和高度(像素點數)。 也可以是一個CRrect對象指針。CRect對象有多個參數,與RECT用法相同。 函數的作用總的來說就是把客戶區的大小寫進第二個參數所指的Rect結構當中。 返回值 如果函數成功,返回一個非零值。 如果函數失敗,返回零。要得到更多的錯誤信息,請使用GetLastError函數 VC+技術內幕學習筆記(1) 寫在前面:我看的VC+技術內幕版本為-潘愛民和王國印譯清華大學出版的第四版,因從網上看到此版譯的最好。這篇學習筆記是后補的,因為這本書我已經看到了第三十二章,之前并沒有做筆記,只是隨意的在書上畫了畫重點,可是越向后學越覺得前面的知識并沒有掌握,所以決定重新來過并補上筆記。我認為只有踏踏實實的記錄下每天的學習心得才能真正的有所收獲。我個人認為學習這本經典之前最好先看看WINDOWS 32位編程的書,至少能用純SDK寫出一些小程序。第一天:WINDOWS應用程序一定要有WinMain函數,該函數用來完成一些特殊的任務,象創建程序的主窗口,主窗口用來處理消息的代碼。MFC將WinMain隱藏在框架中,不象寫SDK程序時可以很容易的找到它。WINDOWS采用的消息處理機制也交給了程序框架,我們不必擔心如何使這些消息和代碼聯系起來。并且WINDOWS定義好了一些消息,當窗口被創建時系統就會發送WM_CREATE消息,當點擊鼠標左鍵時便系統會發送WM_LBUTTONDOWN消息,當用戶按下鍵盤時系統會發送WM_CHAR消息,當用戶關閉窗口時系統會發送WM_CLOSE消息,當用戶進行菜單項選擇或單擊按鈕時系統回發送WM_COMMAND消息,什么都不做系統還會發送WM_TIMER消息。先不說別的,先搞清出這幾個消息再說。從MSDN中可以很方便的找到關于這幾個消息的幫助文檔。WINDOWS提供通用的圖形設備接口(GUI),我們通過調用(GDI)函數和硬件打交道,不必理會設備環境,WINDOWS會自動將設備環境結構映射到相應的物理設備,這應該就是設備無關性吧。動態連接庫(DLL)應該是代碼重用的典型例子(不知道可不可這樣說),把一些模塊、自己新編的類單獨調試并編譯成DLL,及增加代碼的可讀性也提高了程序模塊的靈活性。用Developer Studio建立項目Developer Studio會創建很多中間文件,這些文件還是有必要說一下的。APS /支持ResourceViewBSC /瀏覽器信息文件CLW /支持ClassWizardDSP /項目文件,不能刪除和用文本編輯器編輯DSW /工作空間文件,不能刪除和用文本編輯器編輯MAK /外部的創建文件NCB /支持ClassViewOPT /保存工作空間的配置PLG /建立日志文件這些文件都有一定的作用,拿CLW來說,如果你有一個新類,需要加到ClassWizard中,除了將相應的.h 和.cpp加到DSP中還需要重新編譯CLW。PLG文件記錄著你的項目配置信息。VC+的源程序瀏覽器能夠使我們從類或函數的角度來了解或編輯程序,而不是直接從文件入手。在看別人的源代碼時如果能熟練的使用源代碼瀏覽器將會事倍功半。源程序瀏覽器主要的查看狀態有以下幾種:Definitions and References選擇任何函數、變量、類型、宏定義可以看到它在項目中的定義,并且在何處和什么地方用到它。Call Graph/Caller Graph對于所選擇的函數,給出它的調用與被調用函數的圖示。Derived Class Graph/Base Class Graph給出類層次關系的圖形表示,可以看到所選擇的類的派生類和基類以及成員。File Outline對于所選的文件,列出文件中的類、函數和數據成員,同時還顯示它們定義的位置和使用位置。可見Source Brower比起Class View來功能多了很多也更加好用,以前我就不知道,因為一般的VC+書沒有講或根本沒有注意這塊,看到講菜單、操作界面、編輯器時總是跳過,心想“沒吃過豬肉還沒見過豬跑?這種東西不用學就會”。可實際上還是應該仔細的看看的。對于本章學習雷神建議大家在VC+6中用AppWizard生成一個空的程序,然后試著看看都有那些文件,和他們的類層次、函數、宏、結構的定義,我就是這樣干的,學編程不動手是不行的 VC+技術內幕學習筆記(2) 第二天:Microsoft基本類庫應用程序框架MFC是C+的Microsoft Windows API,如果想要開發WINDOWS的應用程序當然VC/MFC是開發環境的首選。MFC產生的應用程序使用了標準化的結構。(我現在還體會不出這點的優勢所在,請高手指點)MFC產生的應用程序短而運行速度快。這應該說的是可以很容易的建立動態連接,其實程序還是需要大量的DLL,不過由于WINDOWS上有很多可以用DLL所以應用程序很短,我是這樣想的不知對否。VC+工具降低了編碼的復雜性。這點不容質疑比起TC方便太多了。MFC庫功能非常豐富。書上列出了MFC從1.0-4.21的一些特性,我就不廢話了,大家應該看看。 這一章節主要介紹了MFC庫的優點,其實我本人認為在某些特定環境下其實MFC不一定就象說的那樣好。我想不會有人用純VC做MIS系統吧,太累了。我是這樣理解編程序的,如果把學編程看成學武的話,C/C+語言及編程思想(OOP)是內功,API是基本功(編程思想是內功、API是基本功這適用于任何WIN32編程,不論Visual C+、Delphi、C+Builder、VB.),VC/MFC應該不同武功其中的一種,不同的學習方法效果不一樣,只要下工夫也都可以達到一定的境界。真正的高手是有著深厚的內功,扎實的基本功,至于武功招數無所謂了,隨便一站不丁不八全無破綻,無招勝有招了。對不住扯遠了。 C+可以通過類庫來進行擴展,我們除了可以使用隨編譯器提供的類庫外還可以很方便使用軟件公司銷售的類庫產品,甚至可以自己開發。而應用程序框架是一種類庫的超集,它定義了程序的結構。 下面給出兩個示例程序(一個是書上的一個是我寫的):雷神建議:雖然現在很多書都附CD,CD上有書中所有示例的源代碼,但還是應該親自在VC6用手敲進去。這樣可以加深印象以及感受一下編譯除錯后程序正確運行時的樂趣,因為是純手工打造。自從我敲了近一百個代碼示例后,由于筆誤的BUG就很少了,打字速度也提高了。而且最好在原示例代碼的基礎上做些改動例如別千篇一律的顯示HELLO WORLD!換點別的,這樣做也可以加深對示例程序的理解。 我的HELLO WORLD用AppWizard向導創建一個顯示一個字符串的單文檔程序,只需要敲入一行語句,主要是體驗MFC的強大功能。1、打開VC+6從菜單選擇NEW,給項目命名為”MyApp01“。2、選擇MFC AppWizardexe 選項,除STEP 1選擇單文檔外其他STEP缺省。3、在Class View選擇CMyApp01View類的OnDraw()成員函數雙擊會在C+編譯器看到以下內容void CMyApp01View:OnDraw(CDC* pDC)CMyApp01Doc* pDoc = GetDocument();ASSERT_VALID(pDoc);/ TODO: add draw code for native data here在 / TODO: add draw code for native data here的位置增加一行代碼void CMyApp01View:OnDraw(CDC* pDC)CMyApp01Doc* pDoc = GetDocument();ASSERT_VALID(pDoc);pDC-TextOut(10,10,雷神愿意和所有學VC的朋友共同進步!); /Add to project-Files,分別創建一個名為MyApp.h和一個名為MyApp.cpp的文件。3、添加代碼:(最好照敲以下代碼到編譯器,別用Ctrl+C/Ctrl+V)/*/ MyApp.h/class CMyApp:public CWinApp /見下public:virtual BOOL InitInstance();class CMyFrame:public CFrameWndpublic:CMyFrame();protected:afx_msg void OnLButtonDown(UINT nFlags,CPoint point);afx_msg void OnPaint();DECLARE_MESSAGE_MAP();/*/ MyApp.cpp/#include afxwin.h#include myapp.hCMyApp theApp;/建立一個CMyAPP對象見下BOOL CMyApp:InitInstance ()m_pMainWnd=new CMyFrame();m_pMainWnd-ShowWindow (m_nCmdShow);m_pMainWnd-UpdateWindow ();return TRUE;BEGIN_MESSAGE_MAP(CMyFrame,CFrameWnd)ON_WM_LBUTTONDOWN()ON_WM_PAINT()END_MESSAGE_MAP()CMyFrame:CMyFrame()Create(NULL,MYAPP Application);void CMyFrame:OnLButtonDown (UINT nFlags,CPoint point)TRACE(Entering CMyFrame:OnLButtonDown - %lx,%d,%dn,(long)nFlags,point.x ,point.y);void CMyFrame:OnPaint ()CPaintDC dc(this);dc.TextOut (0,0,Hello World!);4、編譯運行,報錯。為什么呢?原來還沒有添加MFC的支持,在Project Setting選項General屬性頁選擇”Use MFC in a Static Library5、再Ctrl+F5,哈成功了。 VC+技術內幕學習筆記(3) 第三篇:消息映射和視圖類 在寫了兩篇筆記后有很多朋友給我發信,和我交流一些在學習過程中的問題。但由于我也是一個初學者,對一些問題自己也沒有把握,所以實在不敢做答,但我會盡量盡我所能和大家一起研究,謝謝大家的鼓勵和信任。 在開始先補充一下上一篇的內容“內容窗口的創建”,兼答天歌網友的問題(如果天歌兄弟能看到的話 )。為了簡化我們看一個更簡單代碼,只有一個文件,創建一個空白的窗口,什么也不做。注意哦:真寫程序時還是要分成.h和.cpp兩個文件比較清晰。 前幾步和VC+技術內幕學習筆記(2)中的一樣,下面是代碼:/*/ MyApp.cpp#include afxwin.h /afxwin.h會調用windows.h是MFC編程的途徑,只要用到MFC就一定要包含它。class CMyApp:public CWinApp /從CWinApp繼承一個類public:virtual BOOL InitInstance();/重載InitInstance虛函數;class CMyFrame:public CFrameWnd /從CFrameWnd繼承一個類;CMyApp myApp; /最后又激活應用程序的構造函數BOOL CMyApp:InitInstance ()m_pMainWnd=new CMyFrame;/new 激活了CMyFrame類構造函數CFrameWnd(),構造函數調又用CREATE()/m_pMainWnd在MFC的定義CWnd* m_pMainWnd;/ main window (usually same AfxGetApp()-m_pMainWnd)/m_pMainWnd保存窗口的位置(CMyFrame * )m_pMainWnd)-Create(NULL,一個MFC應用程序:空白窗口); /創建窗口m_pMainWnd-ShowWindow(m_nCmdShow); /顯示在屏幕上return TRUE; 如果還不明白建議查看MSDN或看看侯大師的深入淺出。關于這個問題就說到這,最后對天歌朋友的學習態度表示敬意。下面進入正體,讓我們繼續來看看MFC的消息映射。 MFC是通過一些宏來將特定的消息影射到派生類相應的成員函數上,這種體制的好處是允許某些非窗口類(如文檔類)來控制命令消息。且不需要C+作任何擴展。 MFC的消息控制函數要求提供函數原形、函數體以及消息映射中的入口。真的很麻煩,還好用Class Wizard可以很容易的將上面說到的東西加到我們的類中。例如只要在Class Wizard中添加WM_LBUTTONDOWN消息,則相應的代碼便加在合適的地方。怎么樣簡單多了吧。 應用程序除了包含應用程序框架類外,一般還要包含文檔和視圖類。這種文檔-視圖結構是應用框架的核心。我一直做MIS開發,當然不是用VC用的是VB,所以看到這我很不自覺的想到了后臺數據庫和界面的關系,這個例子可能不是很恰當,但卻能很好的幫助我們理解文檔和視圖。文檔好比后臺的數據庫,視圖就是界面上顯示的內容,同一個數據庫可以用不同的界面顯示,但由于所有的界面內容都是從數據庫中數據得來,所以當數據庫發生變化時所有的相關界面顯示都會跟著改變。越來越覺得不恰當,不過實在想不出別的例子了。我們的應用程序實際上就是通過視圖對文檔進行一系列操作,不單指輸出。下面我們看看視圖類。 視圖是一個從CView類派生的類的對象,在屏幕上顯示的窗口就是一種。對象的行為完全由類的成員函數和數據成員決定,其中及包括派生類中的特定函數,也包括基類的標準函數,所以了解MFC類庫的結構以及各類的標準成員函數是多么重要啊,別怕麻煩找來MFC的源碼讀讀,看多少算多少,但肯定不白看,這是雷神的經驗。記得上一篇的我的例子嗎1、打開VC+6從菜單選擇NEW,給項目命名為”MyApp01“。2、選擇MFC AppWizardexe 選項,除STEP 1選擇單文檔外其他STEP缺省。此時MFC應用程序框架便幫我們完成了應用程序,你可以執行它,它會在屏幕上顯示一個典型的WINDOWS風格的空白窗口。我們來看一下項目程序所在目錄下的文件:myapp01.dsp /項目文件myapp01.dsw /工作空間文件myapp01.rc /資源描述文件myapp01View.cpp /包含CMyAppView類成員函數的視圖類實現文件 重點myapp01View.h /包含CMyAppView類成員函數的視圖類頭文件 重點myapp01.opt /二進制文件,告訴Developer Studio本項目的哪些文件是打開的,又是如何排列的readme.txt /用來解釋所產生的所有文件,未列出的myapp01Doc.cpp、myapp01Doc.h、StdAfx.cpp、StdAfx.h.在這里都可以找到相應解釋。resource.h /包含#define常量定義的頭文件 仔細研究一下myapp01View.cpp和myapp01View.h文件,程序核心CMyAppView類在這兩個文件中定義,就是我們今天要學的視圖類。要想看到CMyAppView類的全貌,應該用Source Browser查看,選擇CMyApp01View,按Alt+F12,選擇Base Class and Members 選項。我們會看到CMyAppView類的層次關系(從哪來得),以及所有成員函數,包括從基類繼承的(在Class View中不能顯示父類的成員函數)。我們發現實際上你什么也不用做就擁有了一個有著強大功能的類。 下面我們看一下CMyAppView類的OnDraw成員函數,它是虛函數作用是每當窗口需重繪時應用程序框架會調用它。它的原型是這樣的(在myapp01View.h可以找到)virtual void OnDraw(CDC* pDC); / overridden to draw this view 參數是CDC類的指針,WINDOWS是通過和窗口相關聯的設備環境(CDC類的對象就是設備環境)和顯示硬件進行通訊。有了這個指針我們便可以調用CDC類的成員函數來完成各種繪制工作,如上一篇用到的textout()還有一些Ellipse()、Polygon()、BitBlt()等等在MSDN中有好長的一篇,它是直接從CObject派生的,好了我們開始在OnDraw()里添加一些繪圖工作。3、在Class View選擇CMyApp01View類的OnDraw()成員函數雙擊會在C+編譯器看到以下內容void CMyApp01View:OnDraw(CDC* pDC)CMyApp01Doc* pDoc = GetDocument();ASSERT_VALID(pDoc);/ TODO: add draw code for native data here在 / TODO: add draw code for native data here的位置增加一行代碼void CMyApp01View:OnDraw(CDC* pDC)CMyApp01Doc* pDoc = GetDocument();ASSERT_VALID(pDoc);第四篇:資源和編譯 資源文件(就是以應用程序名和擴展名是.rc的文件)很大程度上決定了應用程序的用戶界面。在VC+中資源文件包括以下內容:Accelerator /模擬菜單和工具欄的選擇內容Dialog /對話框的布局及內容Icon /圖標有兩種一種是16X16一種是32X32。Menu /應用程序的主菜單及所屬的彈出式菜單String table /字符串不屬于C+源代碼部分Toolbar /工具條。Version /程序的描述、版本號、支持語言信息。以上信息都在.rc文件中包含,同時.rc文件還包含了以下語句:#include afxres.h#include afxres.rc 它們的作用是把適合于所有應用程序的一些通用MFC庫資源包含進來。 關于資源編輯器的使用就不多說了,因為它的操作很簡單,需要注意的是雖然resource.h是一個ASCII碼文件可以用文本編輯器進行編輯,單如果使用文本編輯器進行編輯的話,下次再使用資源編輯器時所做的修改有可能丟失,所以我們應該在盡量在資源編輯器中編輯應用程序的資源,新增的資源內容回自動的添加在我們的程序相應位置,例如resource.h而不用我們操心。這便是為什么稱為Visual (可視)的原因之一。 編譯在VC+中有兩種模式,一種是Release Build另一種是Debug Build。它們之間的區別在于,Release Build不對源代碼進行調試,不考慮MFC的診斷宏,使用的是MFC Release庫,編譯十對應用程序的速度進行優化,而Debug Build則正好相反,它允許對源代碼進行調試,可以定義和使用MFC的診斷宏,采用MFC Debug庫,對速度沒有優化。所以我們應該在Debug模式下開發應用程序,然后在Release模式下發布應用程序。在我們的工程文件夾下會有一個Debug文件夾和一個Release文件夾分別存放輸出文件和中間文件。 診斷宏是我們編譯程序時檢測程序狀態的有利工具,例如上兩篇用到的TRACE宏,可以在Debug窗口獲得你需要的診斷信息,而不用設置對話框之類的方法,在發布時Release會自動濾掉此信息。 實際上對一個應用程序的調式是一件很具挑戰的工作,我相信我們都有類似的經歷,從網上或書本上找來了一段代碼或源程序,當我們一點點將他們敲進 Deleloper Studio后進行編譯時一下子出現了無數的錯誤和警告,(有些書的源代碼就是錯誤的)這是需要的耐心和經驗,有了VC+提供的調試工具如診斷宏、設斷點、單步執行等等,會讓我們省不少力氣。至于編譯的話題其實應該有很多可以說,但由于雷神本身的經驗不足只能把書上所講的作一個總結,大家應該熟練的掌握VC+為我們提供的的各種調試工具,象SPY之類的工具在MSDN中也有很詳細的使用幫助說明,到現在我體會到了高手們所說的MSDN是最好的最全的也是最權威的。第五篇:基本事件處理 我們已經知道MFC庫應用程序框架調用CView視圖類的虛函數OnDraw來完成屏幕顯示。其實CView和CWnd類包含了幾百個成員函數,在MSDN中可以看到這些成員函數,其中有許多On開頭的,例如第二篇的例子就有一個OnLButtonDown,它們都是應用程序框架響應各種事件所需調用的函數。 OnDraw便是當窗口發生變化是被調用的,OnLButtonDown是鼠標左鍵被按下時調用,還有OnKeyDown是鍵盤被按下時調用等等。 當用戶在視窗中按下鼠標左鍵時,Windows會自動發送WM_LBUTTONDOWN消息給該視窗,當然你可以什么都不做象我們第3篇的例子一樣,如果你想要讓程序對此消息做出反應就必須在視圖類給出相應的函數,類似下面這樣:void CMyView:OnLButtonDown(UINT nFlags,CPoint point)/做些事情的代碼還需要在類頭文件包含相應的函數原型說明afx_msg void OnLButtonDown(UINT nFlags,CPoint point);afx_msg只是說明該函數原型是針對消息映射函數。下一步在代碼文件中還需要有一個消息映射宏,作用是把OnLButtonDown函數和應用程序框架聯系在一起。BEGIN_MESSAGE_MAP(CMyView,CView)ON_WM_LBUTTONDOWNEND_MESSAGE_MAP()最后在類庫的頭文件還需包含:DECLARE_MESSAGE_MAP() 函數和Windows消息的對應關系可以從MSDN中找到在MSDN中索引輸入(WM_ Messages)便會列出所有的Windows消息和消息控制函數原型。在實際的編程過程中我們不可能全部都用手工的添加或編制消息控制函數。除了一些特殊的,我們一般是借助Class Wizard來自動編制消息映射函數。這又是MFC應用程序框架比起SDK來的有一個便捷的地方。 MFC庫對140種windows消息直接提供了消息控制函數,并且我們還可以自己定義自己的消息,下面列出的五種消息是我們應該特別注意的(MSDN上有更詳細的內容)。WM_CREATE 該消息是Windows發給視圖的第一個消息。當應用程序框架調用create函數時該消息便會被發送,此時窗口還未創建完成,不可見,因此在消息控制函數OnCreate內不能調用那些依賴窗口處于完全激活狀態的Windows函數。如果需要可以在重載的OnInitialUpdate函數內調用。不過注意在SDI應用程序OnInitialUpdate函數可能被多次調用。WM_CLOSE 當用戶關閉窗口時,系統會發送WM_CLOSE消息。如果派生類重新定義了OnClose函數,就可以完全控制關閉過程,可以將提醒用戶存盤之類的工作放在這里完成。我們可以通過重載CDocument:SaveModified虛函數達到相同的目的。WM_QUERYENDSESSION 從字面的意思看就可以看出,當用戶退出Windows時,或者調用了ExitWindows 函數時。Windows會發送WM_QUERYENDSESSION消息給所有的正在運行的應用程序,由OnQueryEndSession消息映射函數對消息進行處理。在它之后應該是WM_ENDSESSION 消息。 WM_DESTROY在Windows發送WM_CLOSE消息后,緊接著會發送WM_DESTROY消息,雖然窗口已經Close但實際上并沒有完全清除,在任務管理器中還可以看見應用程序的進程(我想很多木馬或病毒都是無窗口的程序,它們的做法是生成了已經活動狀態的窗口但不顯示出來),利用這個消息控制函數便可以對依賴于當前窗口存在的東西做清除工作,不過一定要注意,應該調用基類的OnDestroy函數,而不能在用戶自己的視圖的OnDestroy函數中終止窗口的析構過程,終止析構過程應該在OnClose函數中。WM_NCDESTROY 當窗口被取消所發送的最后一個消息就是這個消息。我們可以在OnNcDestroy函數中做一些不依賴該窗口是否處于活動狀態的最后的處理工作,(我實在想不出還需要做什么?那位朋友能給個例子),注意一定要調用基類中的OnNcDestroy函數。 我們可以做一個小惡作劇程序:當在窗口內單擊鼠標右鍵(注意是右鍵)時退出所有的正在運行的應用程序。void CMy007View:OnDraw(CDC* pDC)CMy007Doc* pDoc = GetDocument();ASSERT_VALID(pDoc);pDC-TextOut (100,100,請不要單擊鼠標右鍵,否則后果自負!);void CMy007View:OnRButtonDown(UINT nFlags, CPoint point):MessageBox (NULL,你確定要這樣做嗎?,警告,1);:ExitWindows ();/web/189/21186.htm映射模式 在此篇之前我們已經學會了在窗口顯示圖形,更準確的說是在窗口指定位置顯示圖形或文字,我們使用的坐標單位是象素,稱之為設備坐標。看下面語句: pDC-Rectangle(CRect(0,0,200,200); 畫一個高和寬均為200個象素的方塊,因為采用的是默認的MM_TEXT映射模式,所以在設備環境不一樣時,畫的方塊大小也不一樣,在1024*768的顯示器上看到的方塊會比640*480的顯示器上的小(在不同分辨率下的屏幕象素,在WINDOWS程序設計一書中有示例程序可以獲得,或者可以用GetClientRect函數獲得客戶區的矩形大小。在這里就不說了,大家只要知道就行了),在輸出到打印機時也會有類似的情況發生。如何做才能保證在不同設備上得到大小一致的方塊或者圖形、文字呢?就需要我們進行選擇模式映射,來轉換設備坐標和邏輯坐標。 Windows提供了以下幾種映射模式: MM_TEXT MM_LOENGLISH MM_HIENGLISH MM_LOMETRIC MM_HIMETRIC MM_TWIPS MM_ISOTROPIC MM_ANISOTROPIC 下面分別講講這幾種映射模式: MM_TEXT: 默認的映射模式,把設備坐標被映射到象素。x值向右方向遞增;y值向下方向遞增。坐標原點是屏幕左上角(0,0)。但我們可以通過調用CDC的SetViewprotOrg和SetWindowOrg函數來改變坐標原點的位置看下面兩個例子: /* / 例子6-1 void CMyView:OnDraw(CDC * pDC) pDC-Rectangle(CRect(0,0,200,200);/全部采用默認畫一個寬和高為200象素的方塊 /* / 例子6-2 void CMyView:OnDraw(CDC * pDC) pDC-SetMapMode(MM_TEXT);/設定映射模式為MM_TEXT pDC-SetWindowOrg(CPoint(100,100);/設定邏輯坐標原點為(100,100) pDC-Rectangle(CRect(100,100,300,300);/畫一個寬和高為200象素的方塊 這兩個例子顯示出來的圖形是一樣的,都是從屏幕左上角開始的寬和高為200象素的方塊,可以看出例子2將邏輯坐標(100,100)映射到了設備坐標(0,0)處,這樣做有什么用?滾動窗口使用的就是這種變換。 固定比例映射模式: MM_LOENGLISH、MM_HIENGLISH、MM_LOMETRIC、MM_HIMETRIC、MM_TWIPS這一組是Windows提供的重要的固定比例映射模式。 它們都是x值向右方向遞增,y值向下遞減,并且無法改變。它們之間的區別在于比例因子見下:(我想書上P53頁肯定是印錯了,因為通過程序實驗x值向右方向也是遞增的) MM_LOENGLISH 0.01英寸 MM_HIENGLISH 0.001英寸 MM_LOMETRIC 0.1mm MM_HIMETRIC 0.01mm MM_TWIPS 1/1440英寸 /應用于打印機,一個twip相當于1/20磅,一磅又相當于1/72英寸。 看例3 /* / 例子6-3 void CMyView:OnDraw(CDC * pDC) pDC-SetMapMode(MM_HIMETRIC);/設定映射模式為MM_HIMETRIC pDC-Rectangle(CRect(0,0,4000,-4000);/畫一個寬和高為4厘米的方塊 還有一種是可變比例映射模式,MM_ISOTROPIC、MM_ANISOTROPIC。用這種映射模式可以做到當窗口大小發生變化時圖形的大小也會相應的發生改變,同樣當翻轉某個軸的伸展方向時圖象也會以另外一個軸為軸心進行翻轉,并且我們還可以定義任意的比例因子,怎么樣很有用吧。 MM_ISOTROPIC、MM_ANISOTROPIC兩種映射模式的區別在于MM_ISOTROPIC模式下無論比例因子如何變化縱橫比是1:1而M_ANISOTROPIC模式則可以縱橫比獨立變化。 讓我們看例子4 /* / 例子6-4 void CMy002View:OnDraw(CDC* pDC) CRect rectClient; / GetClientRect(rectClient);/返回客戶區矩形的大小 pDC-SetMapMode(MM_ANISOTROPIC);/設定映射模式為MM_ANISOTROPIC pDC-SetWindowExt(1000,1000); pDC-SetViewportExt (rectClient.right ,-rectClient.bottom ); /用SetWindowExt和SetViewportExt函數設定窗口為1000邏輯單位高和1000邏輯單位寬 pDC-SetViewportOrg(rectClient.right/2,rectClient.bottom/2 );/設定邏輯坐標原點為窗口中心 pDC-Ellipse(CRect(-500,-500,500,500);/畫一個撐滿窗口的橢圓。 / TODO: add draw code for native data here 怎么樣,屏幕上有一個能跟隨窗口大小改變而改變的橢圓。把 pDC-SetMapMode(MM_ANISOTROPIC);這句改為pDC-SetMapMode(MM_ISOTROPIC)會怎樣?大家可以試試。那還有一個問題就是上例的比例因子是多少呢?看下面公式(注意是以例子4為例的) x比例因子=rectClient.right/1000 /視窗的寬除以窗口范圍 y比例因子=-rectClient.bottom/1000 /視窗的高除以窗口范圍 從Windows的鼠標消息可以獲得鼠標指針的當前坐標值(point.x和point.y)此坐標值是設備坐標。 很多MFC庫函數尤其是CRect的成員函數只能工作在設備坐標下。 還有我們有時需要利用物理坐標,物理坐標的概念就是現實世界的實際尺寸。 設備坐標-邏輯坐標-物理坐標之間如何進行轉換便成為我們要考慮的一個問題,物理坐標和邏輯坐標是完全要我們自己來做的,但WINDOWS提供了函數來幫助我們轉換邏輯坐標和設備坐標。 CDC的LPtoDP函數可以將邏輯坐標轉換成設備坐標 CDC的DPtoLP函數可以將設備坐標轉換成邏輯坐標 下面列出我們應該在什么時候使用什么樣的坐標系一定要記住: CDC的所有成員函數都以邏輯坐標為參數 CWnd的所有成員函數都以設備坐標為參數 區域的定義采用設備坐標 所有的選中測試操作應考慮使用設備坐標。 需要長時間使用的值用邏輯坐標或物理坐標來保存。因設備坐標會因窗口的滾動變化而改變。 用書上的例子作為以前幾篇的復習,如果你能夠獨立完成它說明前面的內容已經掌握。另外有些東西是新的,我會比較詳細的做出說明,例如客戶區、滾動窗口等。 第七篇:圖形設備接口(GDI) 我想大家和我一樣通過前幾天的學習,對VC+MFC應用程序框架的神奇功能有了一些了解,但是還是感覺不能駕御這個強的開發工具,不過別擔心,我170多斤體重不是一口吃出來的,是經過了30年不懈的努力才吃成了如此“魁梧”的體形,呵呵開個玩笑。所以學習也一樣。學VC尤其如此。還有我發現很多好的技術類書籍有一個共同的特點,就是在前幾章學到了一些東西在你正在疑惑或者苦苦領會的時候,接下來的章節便給你解除疑惑。雷神經驗:遇到實在想不明白的地方先放下,繼續向下讀,也許讀著讀著前面的問題就明白了。VC+技術內幕當然屬于好的技術書籍一類,所以在本書第五章開始仔細的給我們講解設備環境類和圖形設備接口(GDI),使得我們能守得云開見月明。設備環境類CDC: CDC是設備環境類的基類直接由CObject派生。是GDI的關鍵元素,它代表了物理設備。每一個C+設備環境對象都有相對應Windows設備環境,并通過一個32位類型的HDC句柄來標識。CDC類的虛擬性使我們可以很容易的做到編寫同時適用于多種設備的代碼。例如OnDraw函數的pDC-TextOut(0,0,Hello);既可以適用于顯示器、還可以適用于打印預覽和打印,只需要在CView:OnDraw函數的pDC參數指向不同的對象類。CClientDC和CWindowDC是顯示設備環境類,都是由CDC派生而來,區別在于CClientDC是窗口的客戶區不包括邊框、標題欄和菜單欄,(0,0)指客戶區域的左上角。CWindowDC的(0,0)指整個屏幕的左上角,這意味著我們可以在顯示器的任意地方繪圖,包括窗口邊框、標題欄和菜單欄等等。CWindowDC一般應用在框架窗口,而不是視圖窗口。CDC對象被創建后一定要在合適的時候將它刪除掉,如果忘記了刪除設備環境對象則會造成內存丟失。如何做才能避免出現這個問題呢,我們應該在堆棧中構造對象。看例子7-1/*/ 例子7-1void CMyView:OnLButtonDown(UINT nFlags,CPoint point)CRect rect;CClientDC dc(this); /在堆棧中構造設備環境對象,用一個窗口指針this作參數。dc.GetClipBox(rect); /GetClipBox函數是一個虛函數,作用是可以獲得選定區域的尺寸/析構函數在函數返回時自動調用,也就完成對設備環境對象的刪除。書上還給出了另一種寫法:void CMyView:OnLButtonDown(UINT nFlags,CPoint point)CRect rect;CDC * pDC=GetDC(); /通過調用CWnd的GetDC()函數獲得設備環境指針pDC-GetClipBox(rect); /可以獲得選定區域的尺寸ReleaseDC(pDC); /一定不能忘記,釋放設備環境。(書上又寫錯了) 創建的設備環境對象具有一些默認的特性,通過CDC類的成員函數可以設定這些特性。例如前一篇筆記用到的刷子、映射模式等等。我們還可以通過重載SelectObject函數將GDI對象選進設備環境中。GDI對象是通過CGdiObject派生類的C+對

溫馨提示

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

評論

0/150

提交評論