作者:pengkuny
下決心把MFC學(xué)好,
從暑假到現(xiàn)在,
連皮毛都沒學(xué)到一點(diǎn),
真他*丟臉.
發(fā)現(xiàn)寫日記的方法效果不錯(cuò),
該記住的終于記住了
看了仍然不懂的,用"@#$%"符號表示.
錯(cuò)誤理解必然一大堆,只能期望日后補(bǔ)救拉,只是希望不要錯(cuò)得太離譜.
2006.11.10
一.消息響應(yīng)事件的模式,那么消息怎么起作用的?
?? 消息以調(diào)用一個(gè)窗口的窗口過程的形式來表明自己的存在.伴隨4個(gè)參數(shù):
消息所指窗口句柄(包含很多窗口的信息),
消息ID(整型值,消息類型,以WM_開頭),
兩個(gè)名為wParam和lParam的32位參數(shù).
二.@#$%
API函數(shù)RegisterClass注冊的類為WNDCLASS
而"窗口類"指從MFC的CWnd派生的C++類
三.匈牙利命名法:
b,c/ch,By,clr,(x,y),(cx,cy),w,dw,n,I,l,s,sz/str,p,fn,h,wnd,MSG,WM_,g,AFXAPI,WINAPI,SW_,WS_,MM_
函數(shù)名不使用下劃線
所有的類型和常量都是大寫字母,但名字中可以允許有下劃線
所有C++的類必須以大寫C為前綴,類名字的每一個(gè)子名的第一個(gè)字母都必須大寫
四.熟悉一些常用的AFX函數(shù)
五.接觸到的一些類:
CCmdTarget--CWinTread--CWinApp
Cwnd--CFrameWnd,凡是以Wnd結(jié)尾的類都是Cwnd類,框架窗口類
六.protected:對外相當(dāng)于pravite,對內(nèi)相當(dāng)于public
七.頭文件AfxWin.h,里面包含所有類的聲明,可以仔細(xì)看一看
八.查看CWinApp的類定義
待查:分析CWinApp類;
???? DECLARE_DYNAMIC;
?
2006.11.11
一.應(yīng)用程序窗口必須由InitInstance創(chuàng)建,故即使最小的MFC程序都必須覆蓋這個(gè)虛函數(shù).
?? 同理,CMainWnd繼承自CFrameWnd,它必須有自己的構(gòu)造函數(shù),調(diào)用Create創(chuàng)建一個(gè)窗口.
?? CWinApp的一個(gè)非常重要的成員函數(shù)CWnd* m_pMainWnd;它是public的,指向CWnd類
二@#$%
protected:friend class CWinApp;WinApp是CFrameWnd的友元
三.ShowWindow(m_nCmdShow);UpdateWindow();
?? m_nCmdWindow表示窗口CWnd的顯示狀態(tài),CWinApp的public成員函數(shù),其值以SW_前綴,默認(rèn)為SW_SHOWNORMAL
四.從Winmain.cpp中可以看到:
?? AfxWinMain在幕后操縱這一切的運(yùn)行
五.現(xiàn)在可以把框架窗口看作頂層窗口看待,它是應(yīng)用程序與外部世界的主要接口.
六.消息映射:將消息和成員函數(shù)相互關(guān)聯(lián)的表.
BEGIN_MESSAGE_MAP (CMainWindow, CFrameWnd)
??? ON_WM_PAINT ()
END_MESSAGE_MAP ()
CMainWindow為消息所屬的類; CFrameWnd為消息所屬的類的基類,因?yàn)橄⒖梢岳^承.
使用ON_MESSAGE(WM_SETTEXT,OnSetText);創(chuàng)建自己的消息映射.
?
2006.11.13
主題:在窗口中繪圖
一.GDI(Graphics Device Interface)圖形設(shè)備接口負(fù)責(zé)圖形輸出.
?? 具體由設(shè)備描述表(DC)來做.
二.4類設(shè)備描述表類:
CPaintDC
CClientDC
CWindowDC
CMetaFileDC
二.創(chuàng)建一個(gè)設(shè)備描述表后,如CPaintDC dc(this);
就可以調(diào)用各種畫圖函數(shù)了,dc.Fun();
?? 6個(gè)GDI對象:跟設(shè)備描述表dc是什么關(guān)系?
基類:CGDIObject類
畫筆Pen
畫刷Brush
字體Font
位圖Bitmap
調(diào)色板Palette
區(qū)域Region
??
? 它們實(shí)際上刻畫了設(shè)備描述表dc的屬性,并不是dc的函數(shù),
通過dc.SelectObject(GDI對象指針)選入設(shè)備描述表.
三.回憶WM_PAINT消息是怎么產(chǎn)生的:
移動(dòng)了窗口
原來遮掩的部分顯示出來
窗口大小改變
?
CPaintDC類只能干這個(gè)事,只能局限于響應(yīng)WM_PAINT消息,所以要選用CClientDC類
四.取得全屏訪問權(quán),入屏幕截取程序,很少見
傳遞NULL指針
CClientDC dc(NULL);
一般情況下,取this指針給構(gòu)造函數(shù)即可:
CPaintDC dc(this);
CPaintDC *pDC = new CPaintDC(this);
this指向調(diào)用對象本身,不可改變.
?
五.掌握設(shè)備描述表屬性Attribute的常見術(shù)語
文本顏色 CDC::SetTextColor
背景顏色 CDC::SetBKColor
背景模式 CDC::SetBKMode
映射模式 CDC::SetMapMode
繪圖模式 CDC::SetROP2
分別由相關(guān)函數(shù)調(diào)用,非常方便.
既然有Set函數(shù),毫無疑問,就有Get函數(shù)
六.比如OnPaint函數(shù),每次調(diào)用完以后,函數(shù)內(nèi)定義的設(shè)備描述表自然被銷毀
想要保存它的狀態(tài),請使用
CDC::SaveDC,對應(yīng)就有:
CDC::RestoreDC來恢復(fù)
七.映射模式:
一個(gè)邏輯單位對應(yīng)的距離,畫圖的時(shí)候只要告訴GDI多少單位即可,
實(shí)際上這些模式都擴(kuò)大了本來的表示范圍,使得大尺寸的東東都可以壓縮比例顯示
8種映射模式,非常簡單:
(1)默認(rèn)MM_TEXT
(2)公制模式:y軸反轉(zhuǎn),完全符合數(shù)學(xué)坐標(biāo),所以y值一定要用負(fù)的.
(3)可編程模式:不反轉(zhuǎn),但允許反轉(zhuǎn)
?? MM_ISOTROPIC? :x,y同等縮放
?? MM_ANISOTROPIC:x,y獨(dú)立縮放
八.可編程模式
SetViewportExt
SetWindowExt
九.補(bǔ)充:堆和棧的區(qū)別
首先必須弄懂C/C++中內(nèi)存區(qū)的分配:
堆:順序隨意
棧:先進(jìn)后出
一個(gè)由c/C++編譯的程序占用的內(nèi)存分為以下幾個(gè)部分
1、棧區(qū)(stack)— 編譯期間就分配好的內(nèi)存空間,存放函數(shù)的參數(shù)值,局部變量的值等。其操作方式類似于數(shù)據(jù)結(jié)構(gòu)中的棧。 一切管理由系統(tǒng)負(fù)責(zé).
2、堆區(qū)(heap) — 程序運(yùn)行期間動(dòng)態(tài)分配的內(nèi)存空間,你可以根據(jù)程序的運(yùn)行情況確定要分配的堆內(nèi)存的大小.由alloca,new申請,并由free/delete釋放.注意它與數(shù)據(jù)結(jié)構(gòu)中的堆是兩回事。
3、全局區(qū)(靜態(tài)區(qū))(static)—,全局變量和靜態(tài)變量的存儲是放在一塊的,初始化的全局變量和靜態(tài)變量在一塊區(qū)域, 未初始化的全局變量和未初始化的靜態(tài)變量在相鄰的另一塊區(qū)域。 - 程序結(jié)束后有系統(tǒng)釋放
static指函數(shù)調(diào)用后仍然不消失的局部變量.
4、文字常量區(qū) —常量字符串就是放在這里的。 程序結(jié)束后由系統(tǒng)釋放
5、程序代碼區(qū)—存放函數(shù)體的二進(jìn)制代碼。
棧:在Windows下,棧是由高地址向低地址擴(kuò)展的數(shù)據(jù)結(jié)構(gòu),是一塊連續(xù)的內(nèi)存的區(qū)域。這句話的意思是棧頂?shù)牡刂泛蜅5淖畲笕萘渴窍到y(tǒng)預(yù)先規(guī)定好的,在 WINDOWS下,棧的大小是2M,如果申請的空間超過棧的剩余空間時(shí),將提示overflow。
速度快.
堆:堆是由底向高地址擴(kuò)展的數(shù)據(jù)結(jié)構(gòu),是不連續(xù)的內(nèi)存區(qū)域。
容易產(chǎn)生碎片.
舉例:
?CPoint ptX; 和 CPoint ptX = new CPoint();兩者的區(qū)別是什么?
前者棧分配,后者堆分配,用完后delete.
與C++不同,Java自動(dòng)管理?xiàng):投眩绦騿T不能直接地設(shè)置棧或堆。
十.終于他媽的明白GetClientRect的作用了:
CRect rect;
GetClientRect(&rect);
將當(dāng)前窗口的尺寸(比如非最大非最小的狀態(tài))來初始化這個(gè)矩形,
而不是用矩形來初始化窗口大小(難怪rect沒初始化)???????????????????????????????????????????????????????????????????????????????????????????????????????????
十一.
CRect rect;
GetClientRect(&rect);
dc.SetMapMode(MM_ANISOTROPIC);??????????????????? //可編程模式
dc.SetWindowExt(500,600);???????????????????????? //邏輯尺寸就是500*600單位
dc.SetViewportExt(rect.Width(),rect.Height());??? //設(shè)備單位/像素:rect.Width(),rect.Height()
水平方向--每單位多少像素:rect.Width()/500
垂直方向--每單位多少像素:rect.Height()/600????????????????????????????????????????????????????????? 縮放比例就這么來.
SetWindowExt(x1, y1);?????????????????????
SetViewportExt(x2, y2);
與
SetWindowExt(100*x1, 100*y1);??????????????????????
SetViewportExt(596*x2, 596*y2);
效果完全一樣,無非是一個(gè)比例而已.
在同比例縮放模式MM_ISOTROPIC下,
縮放比例取min{x2/x1, y2/y1}!
兩個(gè)范圍設(shè)置函數(shù)僅僅干了一件事,設(shè)置比例,其后畫圖使用邏輯單位,跟它們就沒有直接關(guān)系了.????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
2006.11.15
一.這句話不明白:
"使用SetWindowExt和SetViewportExt時(shí)要注意:在MM_ISOTROPIC映射模式下,
應(yīng)該首先調(diào)用SetWindowExt.否則,部分客戶區(qū)可能會(huì)因落在窗口的邏輯范圍之外而不能使用。
而在MM_ANISOTROPIC映射模式下,窗口范圍和視口范圍中先設(shè)置哪一個(gè)都無關(guān)緊要。"
實(shí)際上,我實(shí)驗(yàn)發(fā)現(xiàn):只要掌握放大因子k=min{x2/x1, y2/y1},和窗口真實(shí)邏輯大小(X,Y),那么畫出來的圖形(x,y)
大小就是(kx,ky),只要kx<=X, ky<=Y,那么就不會(huì)有客戶區(qū)落在窗口的邏輯范圍之外的事情發(fā)生.
二.坐標(biāo)轉(zhuǎn)換
CDC::LPtoDP
CDC::DPtoLP
三.移動(dòng)原點(diǎn),終于搞懂了
SetViewportOrg(x,y)將視口原點(diǎn)移至(x,y)等價(jià)于通知Windows把邏輯點(diǎn)(0,0)映射成設(shè)備點(diǎn)(x,y),
什么意思?就是把邏輯原點(diǎn)移到設(shè)備點(diǎn)(x,y)的位置,在這個(gè)新位置安家作為新的邏輯原點(diǎn),
對設(shè)備坐標(biāo)沒有絲毫改變,所謂映射,只不過是一種簡單的移動(dòng)關(guān)系,并不改變設(shè)備坐標(biāo)
同理,SetWindowOrg(x, y)將邏輯原點(diǎn)(x,y)移到原設(shè)備原點(diǎn)(0, 0)的位置
述說的時(shí)候,(x, y)和(0, 0);邏輯點(diǎn)和設(shè)備點(diǎn)
兩個(gè)"反義詞"不要同時(shí)反說,否則等于沒說.
統(tǒng)一說:把邏輯點(diǎn)(*,*)移到設(shè)備點(diǎn)(*,*)的位置
四.兩個(gè)設(shè)備坐標(biāo)值:
用戶坐標(biāo)值
屏幕坐標(biāo)值
互相轉(zhuǎn)化;
CWnd::ClientToScreen
CWnd::ScreenToClient
四.獲取設(shè)備信息:
CDC::GetDeviceCaps
五.GDI畫筆CPen
樣式PS_
寬度
顏色
Windows自動(dòng)選用當(dāng)前畫筆給圖形加邊框,若選用PS_NULL"NULL筆",邊框就沒有了.
擴(kuò)展筆:@#$%
六.GDI畫刷CBrush
畫刷用來干什么?作為dc的屬性,它一旦選入,就自動(dòng)填充一切畫出的封閉圖形
類型:
單色
帶陰影線:6種,默認(rèn)白色背景
帶圖案:填充指定的位圖
@#$%:
移動(dòng)畫刷原點(diǎn):選入設(shè)備之前
brush.UnrealizeObject();
dc.SetBrushOrg(x0, y0);//注意,畫刷原點(diǎn)以設(shè)備坐標(biāo)值給出
dc.SelectObject(&brush);
七.CDC文本函數(shù):
@#$%
DrawText
TextOut等
八.GDI字體CFont
一個(gè)很好用的API函數(shù)::ZeroMemory(指針,內(nèi)存大小)將一塊內(nèi)存清零.
LOGFONT為字體結(jié)構(gòu),如:
LOGFONT lf;
::ZeroMemory(&lf, sizeof(lf));
初始化lf;
lf.lfEscapement和lf.Orientation指定文本旋轉(zhuǎn)角度的10倍值
CRect::OffsetRect(x,y)設(shè)置一個(gè)矩形坐標(biāo)偏移量.
光柵字體:位圖保存,不適合縮放,MS Sans Serif
TrueType字體:任意縮放
Times New Roman
Arial
Courier
Symbol
八.備用對象:一種非常好的GDI對象,系統(tǒng)預(yù)定義,無須顯式創(chuàng)建,也無須刪除,非常安全.
CDC::SelectStockObject選入DC
CDC::CreateStockObject賦給已有對象
九.怎么刪除GDI對象?
堆上創(chuàng)建的/new,需要CGDIObject::DeleteObject顯式刪除
十.怎么取消GDI對象?
變相的方法:通過選入另外一個(gè)GDI對象將當(dāng)前GDI對象從設(shè)備描述表中"提取"出來.
先保存調(diào)用SelectObject時(shí)返回的指針,
然后將這個(gè)指針重選默認(rèn)對象,或者選入備用對象
來取代當(dāng)前對象.
實(shí)際上,@#$%
十一.CString::Format:
與C語言的printf功能一樣,支持printf所有的格式,
如string.(_T("d%"), i/100);
然后dc.TextOut即可.
十二.滾動(dòng)條:窗口樣式參數(shù),將來學(xué)到更高級的滾動(dòng)條控件,就應(yīng)該可以拋棄這種低級的方式
滾動(dòng)條向它所屬的窗口發(fā)送消息,一切響應(yīng)有窗口來做,滾動(dòng)條很少自己響應(yīng)消息.
Create的第三個(gè)參數(shù)
WS_VSCROLL , WS_
設(shè)置:范圍,位置,頁面大小
方法一:
CWnd::SetScrollRange和CWnd::SetScrollPos
參數(shù)TRUE意味著重不重畫,小技巧
方法二:CWnd::SetScrollInfo,很好用,如:
??? SCROLLINFO si;
??? si.fMask = SIF_PAGE | SIF_RANGE | SIF_POS;
??? si.nMin = 0;
??? si.nMax = nHScrollMax;
??? si.nPos = m_nHScrollPos;
??? si.nPage = m_nHPageSize;
??? SetScrollInfo (SB_HORZ, &si, TRUE);
十三.滾動(dòng)條滑塊大小與窗口尺寸同步變化:
WM_SIZE消息:
窗口建立的時(shí)候,就有WM_SIZE的消息傳來,以后只要窗口尺寸改變,就有WM_SIZE消息傳來
用OnSize處理.
afx_msg void Onsize(UINT nType, int cx, int cy);輕松解決//類型+新寬度+新高度
十四.滾動(dòng)條消息類型自動(dòng)傳遞給nCode參數(shù),位置信息pos都是自動(dòng)傳遞給消息處理函數(shù),不用擔(dān)心
WM_HSCROLL,WM_VSCROLL不是具體的消息類型,SB_才是,
OnHScroll,OnVScroll.
但是在任何事件中,更新滾動(dòng)條的位置都是程序員的事情,滾動(dòng)條自己不會(huì)干.
小技巧:比如有時(shí)忽略"拖動(dòng)滾動(dòng)條"消息SB_THUMBTRACK,
?????? 而只管"釋放滾動(dòng)條"SB_THUMBPOSITION
十五.ScrollWindow(x,y)://向右滾動(dòng)x個(gè)像素,向下滾動(dòng)y個(gè)像素
數(shù)據(jù)快速拷貝滾動(dòng)滾動(dòng),空出來的地方激活OnPaint去重畫
待續(xù)……
posted on 2006-11-15 13:56
哈哈 閱讀(2276)
評論(2) 編輯 收藏 引用