vc++学习笔记—11月14日

第三章 应用程序框架

句柄
HWND 窗口句柄
HBITMAP 位图句柄
HICON 图标句柄
HMENU 菜单句柄
HFILE 文件句柄
HINSTANCE 当前实例句柄
HGLOBAL 全局内存对象句柄
HDC 设备环境句柄
HCURSOR 光标句柄
HFONT 字体句柄
HPEN 画笔句柄
HBRUSH 画刷句柄
HLOCAL 局部内存对象句柄

旁注:
char是char[]的首地址
同样 main是main()的首地址

消息
  消息号: 事先定义好的消息标识
  wParam: 字参数 消息附加信息
  lParam:长字节参数 消息附加信息
消息循环:
常见的:
 while(GetMessage(&Msg,NULL,0,))
{
TranslatMessage(&Msg);//将消息的虚拟键转换为字符信息 例如把

wm_keyup/wm_keydown 转换为wm_char消息,它不会消灭以前的旧消息而是产生一

个新消息

DispatchMessage(&Msg);//将消息传送到指定窗口,即把消息传递给窗口类中的

lpfnWndProc所指向的函数名
}

窗口函数WinProc()
定义了程序对于接收到的不同消息的响应,包含了对各种可能接受到的消息的处

理过程。
每一个case处理一个消息
      
当你不感兴趣的消息也不能不管,在一般的消息回调函数中default 都会return

defwindowproc(...)交由系统处理,否则窗口会不显示
回调函数的callback是用来区分_stdcall(delphi语系以及其他api的语言约定)与

_cdle(c语言的语言约定)的 不同函数 的。

初始化
 1 定义窗口类
 2 注册窗口  RegisterClass();
 3 创建窗口  CreateWindow();
 4 窗口显示  ShowWindow();

MFC类库

包括CWinApp CDoucument CView CFrameWnd CDocTemplate 五大类

命令相关类 CCmdTarget  是消息映射属性的基类,消息映射规定了当一个对象接

收到消息命令时,调用哪个函数进行处理。

线程基类 CWinThread 可直接使用

应用程序类 CWinApp

窗口类 CWnd

框架窗口类 CFrameWnd

文档视窗类 CDocTemplate

winmain中lCmdline参数为 系统参数之意

窗口重画cs_vredraw..为单独位为1的意思如0x00001
如要去掉,可以采用style&~cs_vredraw

窗口类wndClass

旁注:HDC
HDC hdc1 创建一个hdc的变量(hdc是指跟显示设备相关的中间层变量,只要复制

给hdc就可以被显示)
hdc1.getDC(指定要显示窗口的句柄如hwnd);
可以用TextOut(hdc1,...)来显示文字
用完要释放  ReleaseDC(hwnd,hdc1)

 Class :

构造函数
它的名字就是类的名字,一般会在public中,它会在类创建的时候被调用,本来

用于自动给参数赋初值的函数,是类创建所必须的如果不写,系统会默认一个

例子:
class Point
{
public:
 int x;
 int y;
/* void init()       ///此处用于 手工赋初值的

方法,如Point s1; s1.init();//即为初始化
 {
  x=0;
  y=0;
 }*/
 Point()//此就是构造函数
 {
  x=0;
  y=0;
 }
---------------
析构函数:

它的名字就是~类名字,它会在类使用完的时候调用,本来用于释放类占据的空

间的,一般也会出现在public中

例子:

class Point
{
public:
 int x;
 int y;

 
 ~Point()/// 此即为析构函数
 {
 }

---------
函数的重载

有多个名字相同 参数个数或者类型不同的函数

例如:
Point()
 {
  x=0;
  y=0;
 }
Point(int a,int b)
 {
  x=a;
  y=b;
 }
到时候那个符合参数就用那个。。自适应的。

----------------------
this指针用于指向对象,

例如:
Class Point
{
...
void output(int x,int y)
 {
  this->x=x;
  this->y=y;
 }
}
...
Point ist;

此时类中的this就是指ist
----------------
函数的继承和派生

例如class a;
再定义b时,可采用
class b :public a
{

}
即b继承了a类,b是a的派生
====摘自csdn
继承和派生两个术语的区别在于它们的主宾关系不同。  
  继承是对于父类来说是被动的,可以描述为:父类XXX被子类XXX继承  
   
  而派生对于父类来说是主动的。描述为:父类XXX派生子类XXX。  
   
  关于派生类和子类的区别:应该是继承关系的层次结构的概念区别。  
  派生类可以是多余一级的继承关系,  
  子类是一级关系。  
  但同时也有这样的概念:子类属于派生类。  
   
  例如:基类A,  
              类B直接继承于A  
              类C直接继承于B;  
   
          那么依据上面的说法则有:  
   
              类A派生类B,类A被类B继承;类B派生类C,   类B被类C继承。  
              类B是类A的子类,类C是类B的子类;  
              类B和类C都是类A的派生类。  
------------------------
多态性

就是父类的同名函数若设置为虚函数,则放弃父虚函数的类型,主要看子类。子

类有的调用子的,没有的调用父类。
----------------------
虚函数

见上述函数的多态性 ,
例子:
class animal
{
public:
....
..
virtual viod breathe()//此即为虚函数,
 {
 }

}

若为virtual viod breathe()=0;则为纯虚函数纯虚函数是父类用来“留白”的

,即,子类必须定义自己的这个函数
--------------
引用

就是一种别名
例子:
int a=6;
int &b=a;
则b就是a的引用,而且b变换,a也会跟着变化,
注意引用只能在定义时候定义一次,之后不会被重复定义
用法
如果b=5,则a也会变成5

一般用法 定义函数

change(int &a,int &b0)
{...}
使用的时候change(x,y)即使把参数x和y的 本身 进行交换。。。

======================
类的一般 用法
把文件分为cpp和h文件
h文件中只是声明类的函数,不做具体定义
如 animal.h就只用写
class animal
{
public:
animal(int heght , int weght);
viod eat();
viod sleep();
virtual viod breathe();
}
在animal.cpp中写

animal:: animal()//注意此处不必写函数返回值,因为构造函数没有返回值
{
//构造函数
}
void Animal::eat()
{
}
.....

继承animail类的fish类 定义的fish构建函数
Fish::Fish():Animal(300,400)
{
}
---------注意头文件不参与编译
--------------
::shownwindow() 表示调用全局或者平台的函数
AFX类是框架类的函数,系统把众多类联系起来的全局函数
AfxGetApp()可以获得一个CWinApp类的指针即this
CWinApp是应用程序类

先构建 CWinApp 先构建全局变量
然后构建winmain
afxwinmain是winmain的调用函数,用来完成winmain函数的功能
AfxRegisterClass注册窗口类函数,用来使用win32风格的几种窗口
Initapplication()是用来初始化管理用函数
InitInstance()调用子类的初始化函数

this 指向是CxxxApp xxxApp 定义中的xxxApp 是应用程序类

PreCreatWindows()函数中先注册窗口AfxDeferRegisterClass

()//AfxEndDeferRegisterClass判断有没有注册,如果没有就注册参数
可以通过其参数 CREATESTRUCT& cs改变有无最大化等窗口类型
主窗口的创建,是在ProcessShellComand(cmdinfo)实现的
::CreatWindowEx(...)创建窗口,其返回值是个句柄
m_pMainWnd是指向cMainFrame的指针
CWinThread::Run()完成了消息循环

注意wndcls.lpfnWndProc=DefWindowProc并非单纯把消息交给消息处理函数,所

谓的Defxxxx而是做了消息映射,所以此处该处理函数是没有相应的。--leon注解

单文档程序的子窗口是cxxxxview类
LPCTSTR 常量字符串

CxxxDOC 文档类
在C++中,结构体也是一种特殊的类

MFC和WIN32 创建窗口方法的区别和联系


 WNDCLASS wndcls;
 wndcls.cbClsExtra=0;
 wndcls.cbWndExtra=0;
 ......
 RegisterClass(&wndcls);

 CWnd wnd;//wnd并不是窗口,窗口销毁时之销毁了句柄为空,但是成员

函数仍可以用,但是如果wnd销毁,则窗口销毁
 wnd.CreateEx(...);//hwnd 内部传递并没有外漏
 wnd.ShowWindow(SW_SHOWNORMAL);
 wnd.UpdateWindow();
|WIN32----------------------------------------------------------------

--个MFC
v HWND hwnd;
 hwnd=CreateWindowEx();
 ::ShowWindow(hwnd,SW_SHOWNORMAL);
 ::UpdateWindow(hwnd);

 ......

CButton::Create(LPSTSTR按键的文字,风格,大小和位置,父窗口,ID)
例子 : CButton btn;//加到class中的private中
调用
        btn.Create("test",WS_Child|BS_PUSHBUTTON,CRect(0,0,1,1),this,

ID123);
        btn.ShowWindow。。。
小锁 private ,钥匙protect ,什么都没有就是public
得到父窗口指针HWND GetParent();


----------------------------------------------------------------------

--------------------
----------------------------------------------------------------------

--------------------
文本编辑
创建插入符
CreateSolidCaret(20宽度,100高度);
ShowCaret();
//Ascent 升序高度,即h角到头的高度
//Descent 降序高度 ,即G从头到脚的高度
获得字体高度
CCilentDC dc(this);
TEXTMETRIC tm;//注意此处的tm为随意命名
dc.GetTextMetrics(&tm);
tm.tmhight 就是他的高度
这个用法很有用!

位图插入符

CBitmap bitmap;//如果要用,最好放到类的private中,以免析构的时候被干掉
bitmap.LoadBitmap(IDC_XXX);//CString也有类似的读取资源的方法就是

LoadString//可以在资源的String Table中添加
CreateCaret(&bitmap);
ShowCaret();


View 类, 中的OnDraw 窗口重绘时经历

CDC类定义的*pDC
CString str("Hello World!");
文本输出:
pDC->TextOut(50,50,str);//50,50就是文字的左上角的坐标

CSize 中的成员x y 分别是长度和高度

获得字符串的高度
CSize sz=pDC->GetTextExtent(str);

画矩形 pDC->Rectangle(x0,y0,x1,y1);
cstring.GetLength()取长度
 //
此函数实在CxxxView类中右击选择 Add Windowsmessage Hander 从而增添的消息

截获WM_CHAR消息做的响应
void CTextView::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags)
{
 CClientDC dc(this);
 CFont font;
 font.CreatePointFont(300,"华文行楷",NULL);
 CFont *pOldFont=dc.SelectObject(&font);
 TEXTMETRIC tm;
 dc.GetTextMetrics(&tm);
 if(0x0d==nChar)//回车
 {
  m_strLine.Empty();
  m_ptOrigin.y+=tm.tmHeight;
 }
 else if(0x08==nChar)// 退格
 {
  COLORREF clr=dc.SetTextColor(dc.GetBkColor());
  dc.TextOut(m_ptOrigin.x,m_ptOrigin.y,m_strLine);
  m_strLine=m_strLine.Left(m_strLine.GetLength()-1);
  dc.SetTextColor(clr);
 }
 else
 {
  m_strLine+=nChar;
 }
 CSize sz=dc.GetTextExtent(m_strLine);

 CPoint pt;
 pt.x=m_ptOrigin.x+sz.cx;
 pt.y=m_ptOrigin.y;

 SetCaretPos(pt);
 dc.TextOut(m_ptOrigin.x,m_ptOrigin.y,m_strLine);

 dc.SelectObject(pOldFont);

 CView::OnChar(nChar, nRepCnt, nFlags);
}

CTextView::OnTimer(UINT nIDEvent) //文字追随变色的Timer组件代码
{
 // TODO: Add your message handler code here and/or call default
 m_nWidth+=5;

 CClientDC dc(this);
 TEXTMETRIC tm;
 dc.GetTextMetrics(&tm);
 CRect rect;
 rect.left=0;
 rect.top=200;
 rect.right=m_nWidth;
 rect.bottom=rect.top+tm.tmHeight;

 dc.SetTextColor(RGB(255,0,0));
 CString str;
 str.LoadString(IDS_WEIXIN);
 dc.DrawText(str,rect,DT_LEFT);

 rect.top=150;
 rect.bottom=rect.top+tm.tmHeight;
 dc.DrawText(str,rect,DT_RIGHT);

 CSize sz=dc.GetTextExtent(str);
 if(m_nWidth>sz.cx)
 {
  m_nWidth=0;
  dc.SetTextColor(RGB(0,255,0));
  dc.TextOut(0,200,str);
 }
///

/
 CView::OnTimer(nIDEvent);
}

///
=======================================================================

====
关于消息的三点:

1.类的头文件中注释宏之间(//{{AFX_VIRTUAL(xxx)。。。//}}AFX_VIRTUAL)
2.源文件的
BEGIN_MESSAGE_MAP(CXXXView, CView)
 //{{AFX_MSG_MAP(CXXXView)
这个位置
//}}AFX_MSG_MAP
3.源文件的viod cXXxx::onXXX ()自定义的处理函数部分

MFC的消息映射(非WIN32的消息循环处理)

WIN32的编程中 消息处理是把所有的消息都做成虚函数,只要定了子类就可以进

行相应
这样会造成内存资源的浪费

后台有个句柄和c++类对象指针的映射表 ,有消息发生后,后台会把消息以及相

关的窗口对应起来,通过该窗口的句柄找到C++对象的指针,然后将指针传给基类

,基类通过消息循环调用了WindowProc,而WindowProc本身是虚函数,在具体子

类定义次函数时必然会调用了OnWinMsg(消息路由部分),OnWinMsg会查找 1和2

从而判断有没有该消息响应的生命,最后找到3 进行处理。--孙鑫先生原文

我理解MFC的消息映射过程是这样的:

消息产生了-》启用那个后台的映射表-》查找响应窗口的句柄-》WindowProc-》

OnWinMsg-》看看1,2部分有无定义,有的话就—》3 ;、、、、没有就算了(交

由基类处理) :)

view中无须用函数获得本窗口句柄,直接用m_hWnd就是本窗口句柄

画线函数及其用法:

win32用法

HDC hdc;
hdc=::GetDC(m_hWnd);//平台sdk的函数需要加::
MoveToEx(hdc,m_old.x,m_old.y,NULL);//先把鼠标移动到最初的点
LineTo(hdc,point.x,point.y);//画函数
::ReleaseDC(m_hWnd,hdc);//用完释放dc

MFC用法

CDC *pDC=GetDC();
pDC->MoveTo(m_old);
pDC->LineTo(point);
ReleaseDC(pDC);
注释同上


更快的MFC(自动会GetDC和ReleaseDC)

//CClientDC dc(GetParent());//若用此法,可以在工具栏上画,即目标是整个

框架,但不包括非客户区域即标题栏和菜单。
CClientDC dc(this);//注意此函数需要的是一个CWnd的指针,而不是hwnd,hwnd

只是cwnd的一个变量可以用cwnd->hwnd 来调用
dc.Moveto(m_old);
dc.LineTO(ponit);

第四种方法,CWindowDC(也自动会GetDC和ReleaseDC)

CWindowDC dc(this);//若用GetParent可以全窗画
dc.MoveTo(m_old);
dc.LineTo(ponit);

桌面本身就是窗口!
获取桌面窗口的句柄: GetDesktopWindow()可以获取一个CWnd;

注意,此处若用CWnd::的就是获取CWnd类的指针
若用sdk的即::类的就是获取这个窗口的句柄!

CPen画笔类
CPen pen(笔形,宽度,RGB颜色);
需要选入设备描述表中!!
应采用SelectObject可以选择pPen,pBrush,pFont,pBitmap(使用时需要加& 如

&pen,其返回值也是指针,需要用 *pen接)
其返回值是先前一个状态的设备,比如定义了新画笔,那么返回值就是旧画笔。

 

CBrush画刷类

颜色画刷
CBrush brush(RGB(255,0,0));
CClientDC dc(this);
dc.FillRect(CRect(m_old,point),&brush);//填充
//画红色矩形

位图画刷

CBitmap bitmap;
bitmap.LoadBitmap(IDB_XXXX);
CBrush brush(&bitmap);
CClientDC dc(this);
dc.FillRect(CRect(m_old,point),&brush);//填充


画矩形最快的方法:
dc.Rectangle(CRect(m_old,point));


透明画刷方法:

CBrush:*pB=CBrush::FromHandle((HBURSH)GetStockObject(NULL_BRUSH));
dc.SelectObject(pB);
dc.Rectangle....
---------------------
Class p
{
public:
       void a()
       {}
       static void b()
』//静态使用成员函数可以在任何地方写 
如, 静态环境不能调用非静态(没有static定义)的成员变量,

非静态的可以引用静态参数

静态的必须初始化!!即在定义前就要做好!

p point;
p:b();就可以


        {}
}
==============================================
ss菜单:

新增菜单命令响应函数的四大文件篇
 
MainFrame
第三优先级
App
第四优先级
Doc
第二优先级
View
最高优先级

个级别都是如果有函数,就不再允许别的类相应

-----------

消息分类

标准消息:
它是CWnd派生的类,它派生的类中都可以接受到这个消息
除了WM_COMMAND外,所有已WM开头的消息

命令消息
菜单,快捷键,工具栏按钮的消息
都是以WM_COMMAND呈现,要区分 需要菜单项的ID号码
CCmdTarget(CWnd的父类)派生的类都可以接受这类消息

通告消息
有控件产生的消息,按键的单击,区分需要ID。。。
也是以WM_COMMAND呈现
CCmdTarget(CWnd的父类)派生的类都可以接受这类消息

CWnd类可以接受所有的消息,但是CCmdTarget只能接受后两者

命令消息的路由:                                     
AfxWndProc->AfxCallWandProc->WindowProc->OnWndMsg  ->.1 OnNotify(通告消

息)  ->OnCmdMsg   
                                                     .2 OnCommand(命令

消息)

标记菜单——带对勾的那种
实现方法:
在相应函数处加入OnCreate中
GetMenu()->GetSubMenu(0)->CheckMenuItem(ID_按键,

MF_BYCOMMAND|MF_CHECKED);//MF_UNCHECKED
0 代表是第几个子菜单
GetMenu是CWnd的一个成员函数,它返回一个指向整个菜单栏的指针
而GetSubMenu只是返回子菜单的指针
CheckMenuItem是在菜单中放置或者取消一个标记

注意如果用索引法,一定能够要计算分割栏!

设置默认菜单(字体变粗)
GetMenu()->GetSubMenu(0)->SetDefaultItem(ID);
一个子菜单只能有一个缺省菜单,即最后一次命名的。

设置图片菜单
SetMenuItemBitmaps
可以有连个位图,选中一个位图,没选中一个位图。
CBitmap cc;
cc.loadbitmap(图片的ID);
SetMenuItemBitmaps(ID_FILE_OPEN,MF_BYCOMMAND,&m_cbp,&m_cbp);

按键变灰色的函数:GetMenu()->GetSubMenu(0)->EnableMenuItem(ID,

MF_BYCOMMAND/MF_DISABLE|MF_GRAYED);需要在mainframe的构造函数中加

m_bAutoMenuEnable=0;


GetSystemMetrics();//获得系统参数,详情请参考msdn可以查到很多有用的数据
移走菜单 : SetMenu(NULL);
回复菜单:
CMenu menu;
menu.LoadMenu(菜单的ID);
SetMenu(&menu);
1.10
CMenu类

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值