作者:pengkuny
下决心把MFC学好,
从暑假到现在,
连皮毛都没学到一点,
真他*丢脸.
发现写日记的方法效果不错,
该记住的终于记住了
看了仍然不懂的,用"@#$%"符号表示.
错误理解必然一大堆,只能期望日后补救拉,只是希望不要错得太离谱.
2006.11.10
一.消息响应事件的模式,那么消息怎么起作用的?
消息以调用一个窗口的窗口过程的形式来表明自己的存在.伴随4个参数:
消息所指窗口句柄(包含很多窗口的信息),
消息ID(整型值,消息类型,以WM_开头),
两个名为wParam和lParam的32位参数.
二.@#$%
API函数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_
函数名不使用下划线
所有的类型和常量都是大写字母,但名字中可以允许有下划线
所有C++的类必须以大写C为前缀,类名字的每一个子名的第一个字母都必须大写
四.熟悉一些常用的AFX函数
五.接触到的一些类:
CCmdTarget--CWinTread--CWinApp
Cwnd--CFrameWnd,凡是以Wnd结尾的类都是Cwnd类,框架窗口类
六.protected:对外相当于pravite,对内相当于public
七.头文件AfxWin.h,里面包含所有类的声明,可以仔细看一看
八.查看CWinApp的类定义
待查:分析CWinApp类;
DECLARE_DYNAMIC;
2006.11.11
一.应用程序窗口必须由InitInstance创建,故即使最小的MFC程序都必须覆盖这个虚函数.
同理,CMainWnd继承自CFrameWnd,它必须有自己的构造函数,调用Create创建一个窗口.
CWinApp的一个非常重要的成员函数CWnd* m_pMainWnd;它是public的,指向CWnd类
二@#$%
protected:friend class CWinApp;WinApp是CFrameWnd的友元
三.ShowWindow(m_nCmdShow);UpdateWindow();
m_nCmdWindow表示窗口CWnd的显示状态,CWinApp的public成员函数,其值以SW_前缀,默认为SW_SHOWNORMAL
四.从Winmain.cpp中可以看到:
AfxWinMain在幕后操纵这一切的运行
五.现在可以把框架窗口看作顶层窗口看待,它是应用程序与外部世界的主要接口.
六.消息映射:将消息和成员函数相互关联的表.
BEGIN_MESSAGE_MAP (CMainWindow, CFrameWnd)
ON_WM_PAINT ()
END_MESSAGE_MAP ()
CMainWindow为消息所属的类; CFrameWnd为消息所属的类的基类,因为消息可以继承.
使用ON_MESSAGE(WM_SETTEXT,OnSetText);创建自己的消息映射.
2006.11.13
主题:在窗口中绘图
一.GDI(Graphics Device Interface)图形设备接口负责图形输出.
具体由设备描述表(DC)来做.
二.4类设备描述表类:
CPaintDC
CClientDC
CWindowDC
CMetaFileDC
二.创建一个设备描述表后,如CPaintDC dc(this);
就可以调用各种画图函数了,dc.Fun();
6个GDI对象:跟设备描述表dc是什么关系?
基类:CGDIObject类
画笔Pen
画刷Brush
字体Font
位图Bitmap
调色板Palette
区域Region
它们实际上刻画了设备描述表dc的属性,并不是dc的函数,
通过dc.SelectObject(GDI对象指针)选入设备描述表.
三.回忆WM_PAINT消息是怎么产生的:
移动了窗口
原来遮掩的部分显示出来
窗口大小改变
CPaintDC类只能干这个事,只能局限于响应WM_PAINT消息,所以要选用CClientDC类
四.取得全屏访问权,入屏幕截取程序,很少见
传递NULL指针
CClientDC dc(NULL);
一般情况下,取this指针给构造函数即可:
CPaintDC dc(this);
CPaintDC *pDC = new CPaintDC(this);
this指向调用对象本身,不可改变.
五.掌握设备描述表属性Attribute的常见术语
文本颜色 CDC::SetTextColor
背景颜色 CDC::SetBKColor
背景模式 CDC::SetBKMode
映射模式 CDC::SetMapMode
绘图模式 CDC::SetROP2
分别由相关函数调用,非常方便.
既然有Set函数,毫无疑问,就有Get函数
六.比如OnPaint函数,每次调用完以后,函数内定义的设备描述表自然被销毁
想要保存它的状态,请使用
CDC::SaveDC,对应就有:
CDC::RestoreDC来恢复
七.映射模式:
一个逻辑单位对应的距离,画图的时候只要告诉GDI多少单位即可,
实际上这些模式都扩大了本来的表示范围,使得大尺寸的东东都可以压缩比例显示
8种映射模式,非常简单:
(1)默认MM_TEXT
(2)公制模式:y轴反转,完全符合数学坐标,所以y值一定要用负的.
(3)可编程模式:不反转,但允许反转
MM_ISOTROPIC :x,y同等缩放
MM_ANISOTROPIC:x,y独立缩放
八.可编程模式
SetViewportExt
SetWindowExt
九.补充:堆和栈的区别
首先必须弄懂C/C++中内存区的分配:
堆:顺序随意
栈:先进后出
一个由c/C++编译的程序占用的内存分为以下几个部分
1、栈区(stack)— 编译期间就分配好的内存空间,存放函数的参数值,局部变量的值等。其操作方式类似于数据结构中的栈。 一切管理由系统负责.
2、堆区(heap) — 程序运行期间动态分配的内存空间,你可以根据程序的运行情况确定要分配的堆内存的大小.由alloca,new申请,并由free/delete释放.注意它与数据结构中的堆是两回事。
3、全局区(静态区)(static)—,全局变量和静态变量的存储是放在一块的,初始化的全局变量和静态变量在一块区域, 未初始化的全局变量和未初始化的静态变量在相邻的另一块区域。 - 程序结束后有系统释放
static指函数调用后仍然不消失的局部变量.
4、文字常量区 —常量字符串就是放在这里的。 程序结束后由系统释放
5、程序代码区—存放函数体的二进制代码。
栈:在Windows下,栈是由高地址向低地址扩展的数据结构,是一块连续的内存的区域。这句话的意思是栈顶的地址和栈的最大容量是系统预先规定好的,在 WINDOWS下,栈的大小是2M,如果申请的空间超过栈的剩余空间时,将提示overflow。
速度快.
堆:堆是由底向高地址扩展的数据结构,是不连续的内存区域。
容易产生碎片.
举例:
CPoint ptX; 和 CPoint ptX = new CPoint();两者的区别是什么?
前者栈分配,后者堆分配,用完后delete.
与C++不同,Java自动管理栈和堆,程序员不能直接地设置栈或堆。
十.终于他妈的明白GetClientRect的作用了:
CRect rect;
GetClientRect(&rect);
将当前窗口的尺寸(比如非最大非最小的状态)来初始化这个矩形,
而不是用矩形来初始化窗口大小(难怪rect没初始化)
十一.
CRect rect;
GetClientRect(&rect);
dc.SetMapMode(MM_ANISOTROPIC); //可编程模式
dc.SetWindowExt(500,600); //逻辑尺寸就是500*600单位
dc.SetViewportExt(rect.Width(),rect.Height()); //设备单位/像素: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);
效果完全一样,无非是一个比例而已.
在同比例缩放模式MM_ISOTROPIC下,
缩放比例取min{x2/x1, y2/y1}!
两个范围设置函数仅仅干了一件事,设置比例,其后画图使用逻辑单位,跟它们就没有直接关系了.
2006.11.15
一.这句话不明白:
"使用SetWindowExt和SetViewportExt时要注意:在MM_ISOTROPIC映射模式下,
应该首先调用SetWindowExt.否则,部分客户区可能会因落在窗口的逻辑范围之外而不能使用。
而在MM_ANISOTROPIC映射模式下,窗口范围和视口范围中先设置哪一个都无关紧要。"
实际上,我实验发现:只要掌握放大因子k=min{x2/x1, y2/y1},和窗口真实逻辑大小(X,Y),那么画出来的图形(x,y)
大小就是(kx,ky),只要kx<=X, ky<=Y,那么就不会有客户区落在窗口的逻辑范围之外的事情发生.
二.坐标转换
CDC::LPtoDP
CDC::DPtoLP
三.移动原点,终于搞懂了
SetViewportOrg(x,y)将视口原点移至(x,y)等价于通知Windows把逻辑点(0,0)映射成设备点(x,y),
什么意思?就是把逻辑原点移到设备点(x,y)的位置,在这个新位置安家作为新的逻辑原点,
对设备坐标没有丝毫改变,所谓映射,只不过是一种简单的移动关系,并不改变设备坐标
同理,SetWindowOrg(x, y)将逻辑原点(x,y)移到原设备原点(0, 0)的位置
述说的时候,(x, y)和(0, 0);逻辑点和设备点
两个"反义词"不要同时反说,否则等于没说.
统一说:把逻辑点(*,*)移到设备点(*,*)的位置
四.两个设备坐标值:
用户坐标值
屏幕坐标值
互相转化;
CWnd::ClientToScreen
CWnd::ScreenToClient
四.获取设备信息:
CDC::GetDeviceCaps
五.GDI画笔CPen
样式PS_
宽度
颜色
Windows自动选用当前画笔给图形加边框,若选用PS_NULL"NULL笔",边框就没有了.
扩展笔:@#$%
六.GDI画刷CBrush
画刷用来干什么?作为dc的属性,它一旦选入,就自动填充一切画出的封闭图形
类型:
单色
带阴影线:6种,默认白色背景
带图案:填充指定的位图
@#$%:
移动画刷原点:选入设备之前
brush.UnrealizeObject();
dc.SetBrushOrg(x0, y0);//注意,画刷原点以设备坐标值给出
dc.SelectObject(&brush);
七.CDC文本函数:
@#$%
DrawText
TextOut等
八.GDI字体CFont
一个很好用的API函数::ZeroMemory(指针,内存大小)将一块内存清零.
LOGFONT为字体结构,如:
LOGFONT lf;
::ZeroMemory(&lf, sizeof(lf));
初始化lf;
lf.lfEscapement和lf.Orientation指定文本旋转角度的10倍值
CRect::OffsetRect(x,y)设置一个矩形坐标偏移量.
光栅字体:位图保存,不适合缩放,MS Sans Serif
TrueType字体:任意缩放
Times New Roman
Arial
Courier
Symbol
八.备用对象:一种非常好的GDI对象,系统预定义,无须显式创建,也无须删除,非常安全.
CDC::SelectStockObject选入DC
CDC::CreateStockObject赋给已有对象
九.怎么删除GDI对象?
堆上创建的/new,需要CGDIObject::DeleteObject显式删除
十.怎么取消GDI对象?
变相的方法:通过选入另外一个GDI对象将当前GDI对象从设备描述表中"提取"出来.
先保存调用SelectObject时返回的指针,
然后将这个指针重选默认对象,或者选入备用对象
来取代当前对象.
实际上,@#$%
十一.CString::Format:
与C语言的printf功能一样,支持printf所有的格式,
如string.(_T("d%"), i/100);
然后dc.TextOut即可.
十二.滚动条:窗口样式参数,将来学到更高级的滚动条控件,就应该可以抛弃这种低级的方式
滚动条向它所属的窗口发送消息,一切响应有窗口来做,滚动条很少自己响应消息.
Create的第三个参数
WS_VSCROLL , WS_
设置:范围,位置,页面大小
方法一:
CWnd::SetScrollRange和CWnd::SetScrollPos
参数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);
十三.滚动条滑块大小与窗口尺寸同步变化:
WM_SIZE消息:
窗口建立的时候,就有WM_SIZE的消息传来,以后只要窗口尺寸改变,就有WM_SIZE消息传来
用OnSize处理.
afx_msg void Onsize(UINT nType, int cx, int cy);轻松解决//类型+新宽度+新高度
十四.滚动条消息类型自动传递给nCode参数,位置信息pos都是自动传递给消息处理函数,不用担心
WM_HSCROLL,WM_VSCROLL不是具体的消息类型,SB_才是,
OnHScroll,OnVScroll.
但是在任何事件中,更新滚动条的位置都是程序员的事情,滚动条自己不会干.
小技巧:比如有时忽略"拖动滚动条"消息SB_THUMBTRACK,
而只管"释放滚动条"SB_THUMBPOSITION
十五.ScrollWindow(x,y)://向右滚动x个像素,向下滚动y个像素
数据快速拷贝滚动滚动,空出来的地方激活OnPaint去重画
待续……
posted on 2006-11-15 13:56
哈哈 阅读(2266)
评论(2) 编辑 收藏 引用