Chinaunix首页 | 论坛 | 博客
  • 博客访问: 66821
  • 博文数量: 29
  • 博客积分: 1500
  • 博客等级: 上尉
  • 技术积分: 270
  • 用 户 组: 普通用户
  • 注册时间: 2009-11-12 14:09
文章分类

全部博文(29)

文章存档

2017年(1)

2012年(1)

2011年(5)

2010年(2)

2009年(20)

我的朋友
最近访客

分类:

2009-11-13 11:17:16

VC++深入详解学习笔记 1
 

 1.mfc 生成的 debug可以加入命令行参数。

3.在sdk中要加入"windows.h"和stdio.h。因为loadcursor,messagebox等函数的声明在这个文件中。

4.创建一个完整的窗口的四个步骤sdk,1设计窗口类,2注册窗口类,3创建窗口,4显示窗口

5.函数名可以代表函数代码的首地址,即可作为函数指针。

6.要查看vc数据类型,可以在msdn中输入“bool”然后选择“data type”。

7.atof将字符串转化为float,atoi将字符串转化为int型。

8.所有从cwnd类派生的类都有m_hwnd句柄。

9.变量的生命周期:可以认为出了包含它的大括号,这个变量的生命周期结束。所以全局变量的声明位于所有大括号之外。但是用new声明的变量和用static声明的变量除外。

10.sdk示范程序,见下面。

11.sprintf格式化字符,其头文件为stdio.h,在mfc中格式化字符用cstring.format

12.getdc()与releasedc()要成对使用,否则会内存泄漏。同样,beginpaint()与endpaint()。

13.getstockobject()得到画笔、画刷、字体、调色板的句柄,使用时必须用类型转换。

14.什么时候用null,什么时候用0.答,对指针赋值时用null,对变量赋值时用0.

15.什么是野指针?答:将指针指向的变量的内存释放后,此指针即变成野指针!如何避免野指针?答:将此指针指向null即可。p=null;

16.sdk代码流程:

#include "windows.h"//包含头文件loadcursor,textout等函数

#include "stdio.h"//包含sprintf,printf等函数

lresult callback myproc(...);//声明回调函数

int winapi winmain()

{

wndclass wndcls;//设计窗口类

wndcls.hcursor=loadcursor();//初始化

....

registerclass(&wndcls);//注册窗口类

hwnd=createwindow(...);//创建窗口

showwindow(..);//显示窗口

updatewindow(..);

msg msg;//定义消息结构体

while(getmessage(...))//消息循环

{

...

}

return 0;

}         lresult callback myproc(...)//实现回调函数

{

switch(umsg)

{

case wm_char:

break;

...

}

}

   

        

    1.定义结构体和类时。例如class point{int x;int y;};

2.#include 与#include "xxx.h"的区别:<>不查找运行时目录,""查找运行时目录!

3.类的定义中,如果未指明成员类型,则缺省为private.而结构体中则缺省为public.

4.引用:引用经常用在函数的传参上。另外数值交换函数也经常用引用。例

change(int &x,int &y){int temp;temp=x;x=y;y=x}调用时即可以用 int a=3;int b=4;change(a,b);一般不用指针来作为参数进行数值交换。因为会引起歧义。

5.通常将类的定义放.h文件,而将其实现放在cpp文件中,别忘记了在cpp文件中#include "xxx.h"

6.如何防止类的重复定义?

用#inndef point_h_h

#define point_h_h

class point{};

#endif来防止

7.源文件cpp文件单独编译成obj文件。最后由链接器将与将要使用到的c++标准库类链接成exe文件,头文件不参加编译。所以在cpp文件中别忘记了加入#include "xxx.h"

8.函数的覆盖,在子类中重写父类的函数,此时采用早期绑定的方法。如果加入了virtual,则将采用迟绑定的技术,在运行时根据对象的类型确定调用哪一个函数。此迟绑定技术是mfc的类的继承的精髓。

9.强制类型转换。如果cfish从canimal派生而来。则可以将鱼的对象转换为canimal的对象,而反之则不行。从现实中理解也是正常的,鱼可以是动物,而动物却不是鱼。再如int可以强制转换成char型。而反之则出错。

  

        

    run();//消息循环

}

而在bool ctestapp::initinstance()中的代码

csingledoctemplate* pdoctemplate;

pdoctemplate = new csingledoctemplate(

idr_mainframe,

runtime_class(ctestdoc),

runtime_class(cmainframe),       // main sdi frame window

runtime_class(ctestview));

adddoctemplate(pdoctemplate);

完成了将这三个类关联起来的工作。

4.如何在单文档文件中显示一个cbutton的对象?

在cmainframe::oncreate()中定义一个cbutton的对象btn;然后调用btn.create("维新",ws_disabled   |ws_child | ws_visible | bs_auto3state,

crect(0,0,300,100),/*getparent(),*/this,123);

注意点:

     (1).此处btn不能是局部变量,否则它的生命周期太短,将不能显示。

     (2).在create函数的第二个参数中加入ws_visible 参数才行。否则必须调用showwindow

也可以在view的oncreate消息响应函数中加入

     (3).cbutton类的定义头文件在afxwin.h中,而stdafx.h包含了afxwin.h,所以可以直接使用。因为mfc中的每一个类中都有#include "stdafx.h"的声明。

   

        

    lineto(point);

releasedc(pdc);必须成对使用。*/         //cclientdc dc(this);

/*cclientdc dc(getparent());

dc.moveto(m_ptorigin);

dc.lineto(point);此处不需要releasedc,因为cclientdc会自动释放dc*/         //cwindowdc dc(this);

//cwindowdc dc(getparent());

/*cwindowdc dc(getdesktopwindow());//此时可以在整个屏幕上画线。

dc.moveto(m_ptorigin);

dc.lineto(point);*/

/*cpen pen(ps_dot,1,rgb(0,255,0));

cclientdc dc(this);

cpen *poldpen=dc.selectobject(&pen);

dc.moveto(m_ptorigin);

dc.lineto(point);

dc.selectobject(poldpen);*/

5)用bitmap填充所画的矩形。

cbitmap bitmap;

bitmap.loadbitmap(idb_bitmap1);

cbrush brush(&bitmap);

cclientdc dc(this);

dc.fillrect(crect(m_ptorigin,point),&brush);

//cbrush::fromhandle是静态成员函数,所以可以用下面的方法调用。

cbrush *pbrush=cbrush::fromhandle((hbrush)getstockobject(null_brush));

cbrush *poldbrush=dc.selectobject(pbrush);

dc.rectangle(crect(m_ptorigin,point));

dc.selectobject(poldbrush);

m_bdraw=false;

6)用其它颜色画线

cclientdc dc(this);

cpen pen(ps_solid,1,rgb(255,0,0));

cpen *poldpen=dc.selectobject(&pen);//选中红色画笔

if(m_bdraw==true)

{

dc.setrop2(r2_black);//设置绘画模式

dc.moveto(m_ptorigin);

//dc.lineto(point);

dc.lineto(m_ptold);

//dc.moveto(m_ptorigin);

dc.moveto(m_ptold);

dc.lineto(point);

//m_ptorigin=point;

m_ptold=point;

}

dc.selectobject(poldpen);

4.mfc中隐式的包含了windows.h。为什么?

因为在afxv_w32.h文件中:

// this is a part of the microsoft foundation classes c++ library.

// copyright (c) 1992-1998 microsoft corporation

// all rights reserved.

在afxwin.h中

// note: windows.h already included from afxv_w32.h

5.如何从句柄获得对象的指针?

答fromhandle

6.类的静态成员函数可以由类名直接调用,也可以由对象调用。可以认为静态成员函数并不属于某个对象,它属于类本身。程序运行伊始,即使没有实例化类的对象,静态成员函数和静态成员变量已然有其内存空间。静态成员函数不能访问非静态成员变量!静态成员变量必须在类的外部初始化。当然如果并不打算用到静态成员变量,此时你可以不初始它。

7.理解代码区,数据区,堆,栈!

请见下面的简介:

  

对于一个进程的内存空间而言,可以在逻辑上分成3个部份:代码区,静态数据区和动态数据区。动态数据区一般就是“堆栈”。“栈(stack)”和“堆(heap)”是两种不同的动态数据区,栈是一种线性结构,堆是一种链式结构。进程的每个线程都有私有的“栈”,所以每个线程虽然代码一样,但本地变量的数据都是互不干扰。一个堆栈可以通过“基地址”和“栈顶”地址来描述。全局变量和静态变量分配在静态数据区,本地变量分配在动态数据区,即堆栈中。程序通过堆栈的基地址和偏移量来访问本地变量。

   

        

   1,创建**符:

void createsolidcaret( int nwidth, int nheight );//创建**符

void createcaret( cbitmap* pbitmap );//创建位图**符

void showcaret( );//显示**符

void hidecaret( );//隐藏**符

static void pascal setcaretpos( point point );//移动**符号

说明:

1)创建**符要在窗口创建完成之后,createsolidcaret函数创建的**符被初始化为隐藏,所以需要调用showcaret()将其显示。

2)使用createcaret函数创建位图**符的时候,不能使用局部的位图对象关联位图资源。(与资源相关联的c++对象,当它析构的时候会同时把与它相关联的资源销毁。)

2,获取当前字体信息的度量:cdc::gettextmetrics

bool gettextmetrics( lptextmetric lpmetrics ) const;

说明:

typedef struct tagtextmetric { /* tm */

    int tmheight;//字体高度。specifies the height (ascent + descent) of characters.

    int tmascent;//基线以上的字体高度

    int tmdescent;//基线以下的字体高度

    int tminternalleading;

    int tmexternalleading;

    int tmavecharwidth;//字符平均宽度

    int tmmaxcharwidth;

    int tmweight;

    byte tmitalic;

    byte tmunderlined;

    byte tmstruckout;

    byte tmfirstchar;

    byte tmlastchar;

    byte tmdefaultchar;

    byte tmbreakchar;

    byte tmpitchandfamily;

    byte tmcharset;

    int tmoverhang;

    int tmdigitizedaspectx;

    int tmdigitizedaspecty;

} textmetric;

3,ondraw函数:

virtual void ondraw( cdc* pdc )

当窗口(从无到有或尺寸大小改变等)要求重绘的时候,会发送wm_pain消息,调用ondraw函数进行重绘。

4,获取字符串的高度和宽度(区别字符串的长度):

cdc::gettextextent

csize gettextextent( lpctstr lpszstring, int ncount ) const;

csize gettextextent( const cstring& str ) const;

说明:

the csize class is similar to the windows size structure。

typedef struct tagsize {

    int cx;//the x-extent

    int cy;//the y-extent

} size;        5,路径层:

bool beginpath( );

//在这作图定义路径层剪切区域

bool endpath( );

bool selectclippath( int nmode );//调用这个函数来使当前路径层剪切区域与新剪切区域进行互操作。  

//在这覆盖作图(包含前定义的路径层区域)定义新的剪切区域

说明:

1)selectclippath selects the current path as a clipping region for the device context, combining the new region with any existing clipping region by using the specified mode. the device context identified must contain a closed path.

////

nmode:rgn_and,rgn_copy,rgn_diff,rgn_or,rgn_xor

rgn_and   the new clipping region includes the intersection (overlapping areas) of the current clipping region and the current path.

rgn_copy   the new clipping region is the current path.

rgn_diff   the new clipping region includes the areas of the current clipping region, and those of the current path are excluded.

rgn_or   the new clipping region includes the union (combined areas) of the current clipping region and the current path.

rgn_xor   the new clipping region includes the union of the current clipping region and the current path, but without the overlapping areas.

2)应用:当作图的时候,如果想要在整幅图形其中的某个部分和其它部分有所区别,我们可以把这部分图形放到路径层当中,然后指定调用指定互操作模式调用selectclippath( int nmode )函数来使路径层和覆盖在其上新绘图剪切区域进行互操作,达到特殊效果。

6,关于文本字符串一些函数:

colorref getbkcolor( ) const;//得到背景颜色

virtual colorref setbkcolor( colorref crcolor );//设置背景颜色

bool settextbkcolor( colorref cr );//设置文本背景颜色

virtual colorref settextcolor( colorref crcolor );//设置文本颜色

virtual bool textout( int x, int y, lpctstr lpszstring, int ncount );//输出文本

bool textout( int x, int y, const cstring& str );

cstring left( int ncount ) const;//得到字符串左边ncount个字符

int getlength( ) const;//得到字符串长度

7,字体cfont::cfont

cfont( );//构造函数

//constructs a cfont object. the resulting object must be initialized with createfont, createfontindirect, createpointfont, or createpointfontindirect before it can be used.

选用字体事例代码组:

cclientdc dc(this);

cfont font;//构造字体对象

font.createpointfont(300,"华文行楷",null);//初始化字体对象,与字体资源相关联

cfont *poldfont=dc.selectobject(&font);//将新字体选入dc

...

dc.selectobject(poldfont);//恢复原字体

说明:

1)构造字体对象时候,必须初始化。(初始化是将字体对象与字体资源相关联)。

2)初始化对象时候,选用的字体也可以是系统字体,但不一定都有效,据测试选用。

8,在mfc中ceditview 和 cricheditview类已经完成了初步的文字处理。可以让应用程序的view类以ceditview 和 cricheditview类为基类。

9,平滑变色

cdc::textout()是一个字母一个字母的输出,达不到平滑效果。

cdc::drawtext():将文字的输出局限于一个矩形区域,超出矩形区域的文字都被截断。利用这一特点,可每隔些时间增加矩形大小,从而可实现人眼中的平滑效果。

cwnd::settimer():设置定时器。按设定的时间定时发送wm_timer消息。

说明:

uint settimer( uint nidevent, uint nelapse, void (callback export* lpfntimer)(hwnd, uint, uint, dword) );

//nidevent定时器标示,nelapse消息发送间隔时间,void (callback export* lpfntimer)(hwnd, uint, uint, dword)设置回调函数,如果设置则由设置的回调函数处理wm_timer消息,如果没有设置回调函数设为null,这发送的wm_timer消息压入消息队列,交由相关联的窗口处理(添加wm_timer消息处理函数ontimer())。

afx_msg void ontimer( uint nidevent );

//响应wm_timer消息,nidevent为消息对应定时器标示(可以设置不同的定时器发送wm_timer消息)

问题:

1,在ccareview类中添加wm_create消息响应函数oncreate(),wm_create消息是在什么时候被检查到而被响应的呢?

(猜测:添加wm_create消息后,消息被压入消息队列,然后经过消息循环进行分发到具体窗口,从而进行响应)

2,现有一文本文件内容已经读入串str中,要求在视图客户区按原先文本文件中的格式输出。

问题是,利用cdc的textout()来在cview类派生类窗口中输出串时,忽略了串中的tab、回车换行等格式,无论串有多长均在一行上输出。

这其中是cdc类成员函数textout()忽略串中格式的,还是cview类派生类窗口设置从中做怪呢?怎么解决

   

        

   1,弹出菜 单(pop -up)是不能用来作命令响应的。        2,mfc中菜单项消息如果利用classwizard来对菜单项消息分别在上述四个类中进行响应,则菜单消息传递顺序:view类--doc类--cmainframe类--app类。菜单消息一旦在其中一个类中响应则不再在其它类中查找响应函数。

具体:

当点击一个菜单项的时候,最先接受到菜单项消息的是cmainframe框架类,cmainframe框架类将会把菜单项消息交给它的子窗口view类,由view类首先进行处理;如果view类检测到没对该菜单项消息做响应,则view类把菜单项消息交由文档类doc类进行处理;如果doc类检测到doc类中也没对该菜单项消息做响应,则doc类又把该菜单项消息交还给view类,由view类再交还给cmainframe类处理。如果cmainframe类查看到cmainframe类中也没对该消息做响应,则最终交给app类进行处理。         3,消息的分类:标准消息,命令消息,通告消息。

[标准消息]:除wm_command之外,所有以wm_开头的消息。

[命令消息]:来自菜单、加速键或工具栏按钮的消息。这类消息都以wm_command呈现。

在mfc中,通过菜单项的标识(id)来区分不同的命令消息;在sdk中,通过消息的wparam参数识别。

[通告消息]:由控件产生的消息,例如,按钮的单击,列表框的选择等均产生此类消息,为的是向其父窗口(通常是对话框)通知事件的发生。这类消息也是以wm_command形式呈现。

说明:

1)从cwnd派生的类,都可以接收到[标准消息]。

2)从ccmdtarget派生的类,都可以接收到[命令消息]和[通告消息]。         4,一个菜单拦可以有若干个子菜单,一个子菜单又可以有若干个菜单项等。对菜单栏的子菜单由左至右建立从0开始的索引。对特定子菜单的菜单项由上至下建立了从0开始的索引。访问子菜单和菜单项均可以通过其索引或标识(如果有标识的话)进行。

相关重要函数:

cmenu* getmenu( ) ;//cwnd::getmenu得到窗口菜单栏对象指针。

cmenu* getsubmenu( ) ;//cmenu::getsubmenu获得指向弹出菜单对象指针

uint checkmenuitem( );//cmenu::checkmenuitem adds check marks to or removes check marks from menu items in the pop-up menu.

bool setdefaultitem();//cmenu::setdefaultitem sets the default menu item for the specified menu.

bool setmenuitembitmaps( );//cmenu::setmenuitembitmaps 设置位图标题菜单。

uint enablemenuitem();//cmenu::enablemenuitem使菜单项有效,无效,或变灰。

bool setmenu( cmenu* pmenu );//cwnd::setmenu在当前窗口上设置新菜单或移除菜单。

hmenu detach( );//cmenu::detach detaches a windows menu from a cmenu object and returns the handle.

说明:

1)在计算子菜单菜单项的索引的时候,分隔栏符也算索引的。

2)int getsystemmetrics()获取系统信息度量。可以用它来获取菜单标题的尺寸从而设置位图标题菜单中位图的大小。

3)在mfc中mfc为我们提供了一套命令更新机制,所有菜单项的更新都是由这套机制来完成的。所以要想利用cmenu::enablemenuitem来自己控制菜单使用或不使用变灰等,必须要在cmainframe的构造函数中将变量m_bautomenuenable设置为false。

4)create a cmenu object on the stack frame as a local, then call cmenu’s member functions to manipulate the new menu as needed. next, call cwnd::setmenu to set the menu to a window, followed immediately by a call to the cmenu object’s detach member function. the cwnd::setmenu member function sets the window’s menu to the new menu, causes the window to be redrawn to reflect the menu change, and also passes ownership of the menu to the window. the call to detach detaches the hmenu from the cmenu object, so that when the local cmenu variable passes out of scope, the cmenu object destructor does not attempt to destroy a menu it no longer owns. the menu itself is automatically destroyed when the window is destroyed.

5)you can use the loadmenuindirect member function to create a menu from a template in memory, but a menu created from a resource by a call to loadmenu is more easily maintained, and the menu resource itself can be created and modified by the menu editor.         6)example:

cmenu menu;//定义为局部对象

menu.loadmenu(idr_mainframe);

setmenu(&menu);

menu.detach();// 这里menu对象作为一个局部对象。使用detach()从menu对象中分离窗口菜单句柄,从而当menu对象析构的时候窗口菜单资源不随之销毁。         5,命令更新机制:

菜单项状态的维护是依赖于cn_update_command_ui消息,谁捕获cn_update_command_ui消息,mfc就在其中创建一个ccmdui对象。

在后台操作系统发出wm_initmenupopup消息,然后由mfc的基类如cframewnd接管并创建一个ccmdui对象和第一个菜单项相关联,调用对象成员函数doupdate()(注:这个函数在msdn中没有找到说明)发出cn_update_command_ui消息,这条消息带有指向ccmdui对象的指针。此后同一个ccmdui对象又设置为与第二个菜单项相关联,这样顺序进行,直到完成所有菜单项。

更新命令ui处理程序仅应用于弹出式菜单项上的项目,不能应用于永久显示的顶级菜单项目。

说明:

1)可以手工或用classwizard来给菜单项添加update_command_ui消息响应,利用响应函数中传进来的ccmdui对象指针可完成设置菜单项可使用,不可使用,变灰,设置标记菜单等操作。         6,如果要想让工具栏上的某个图标与菜单项的某个菜单相关联,只需要将图标的id设置为该菜单项的id。

工具栏图标的索引记数顺序是:从做至右从0开始,分隔符也算索引号。         components and controls..

系统增加的内容:a,一个菜单资源;b,在派生view类中增加了oncontextmenu()函数

说明:

1)cwnd::oncontextmenu called by the framework when the user has clicked the right mouse button (right clicked) in the window. you can process this message by displaying a context menu using the trackpopupmenu.

2)bool trackpopupmenu( uint nflags, int x, int y, cwnd* pwnd, lpcrect lprect = null );

//cmenu::trackpopupmenu displays a floating pop-up menu at the specified location and tracks the selection of items on the pop-up menu. a floating pop-up menu can appear anywhere on the screen.         trackpopupmenu(tpm_leftalign | tpm_rightbutton, point.x, point.y,this);

说明:

cwnd::clienttoscreen(..);//将一个坐标点或一个矩形区域坐标转换成屏幕坐标。

cmenu::trackpopupmenu(..);//在指定位置以指定的方式显示弹出菜单。

cwnd::screentoclient(..);

//converts the screen coordinates of a given point or rectangle on the display to client coordinates.          9,当弹出菜单属于框架窗口的时候(可在trackpopupmenu函数参数中设置),弹出菜单上的消息,在路由的时候,仍然遵循view-doc-mainframe-app的响应顺序。         10,动态菜单编程:

所有的资源对象都有一个数据成员保存了资源的句柄。

cmenu::appendmenu //appends a new item to the end of a menu.

cmenu::createpopupmenu //creates an empty pop-up menu and attaches it to a cmenu object.

cmenu::insertmenu

//inserts a new menu item at the position specified by nposition and moves other items down the menu.

cmenu::getsubmenu //retrieves a pointer to a pop-up menu.

cwnd::getmenu //retrieves a pointer to the menu for this window.

cmenu::deletemenu //deletes an item from the menu.          11,手动给动态菜单项添加响应函数:

在resource.h中可以添加资源的id

在头文件中写消息函数原型

在代码文件中添加消息映射和添加消息响应函数

说明:

可以先创建一个临时的菜单项,设置它的id和动态菜单项的一致,然后对它用向导进行消息响应,然后删除临时菜单。

再在代码文件中把消息映射放到宏外(注意一定要放到宏外面,因为classwizard发现菜单删除了,同时要把其宏对里的消息映射也删除掉的)         12,cwnd::drawmenubar

//redraws the menu bar. if a menu bar is changed after windows has created the window, call this function to draw the changed menu bar         cwnd::getparent //get a pointer to a child window’s parent window (if any).

cwnd::invalidate //注意其参数的作用         13,集合类:

cstringarray,cstringarray,cdwordarray,cptrarray,cstringarray,cuintarray,cwordarray

其中成员函数:

carray::getat

carray::add         =idm_phone1 && menucmdid m_strarray.getat(menucmdid-idm_phone1));

return true;

   //函数返回,避免调用cframewnd::oncommand函数,在cframewnd::oncommand中截获的消息会交由view类处理

}

return cframewnd::oncommand(wparam, lparam);

//调用基类oncommand函数,在cframewnd::oncommand中截获的消息会交由view类处理

}

msdn说明:

virtual bool oncommand( wparam wparam, lparam lparam );

//the framework calls this member function when the user selects an item from a menu, when a child control sends a notification message, or when an accelerator keystroke is translated.

oncommand processes the message map for control notification and on_command entries, and calls the appropriate member function.

override this member function in your derived class to handle the wm_command message. an override will not process the message map unless the base class oncommand is called.         15,loword与hiword宏

word loword(

dword dwvalue // value from which low-order word is retrieved

);

word hiword(

dword dwvalue // value from which high-order word is retrieved

);         //the loword macro retrieves the low-order word from the given 32-bit value.

//the hiword macro retrieves the high-order word from the given 32-bit value.        

16,cframewnd::getactiveview

cview* getactiveview( ) const;//获取当前视窗口指针(单文档框架中)         17,源文件是单独参与编译的。

阅读(1191) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~