VC++学习笔记5

 OnEraseBkgnd 的一些理解【转】

MFC这个框架不搞清楚其中的来龙去脉,总有你郁闷的时候……

Q: OnEraseBkgnd函数中返回TRUE或FALSE有什么区别?

A:  
WM_ERASEBKGND
Return Values
An application should return nonzero if it erases the background; otherwise, it should return zero.

A:true表示已处理背景刷新,false表示需要在OnPaint里处理

Q:在OnEraseBkgnd中绘制对话框的背景图片和在OnPaint中绘制对话框的背景图片由什么区别,另外OnEraseBkgnd和CtlColor有什么区别?

A:  
OnEraseBkgnd是在窗口大小发生改变等情况下发生的,它将绘制窗口背景;而OnCtlColor是当窗口的控件需要绘制时发生的,它将绘制窗口的控件。
  
A:
OnEraseBkgnd :在窗口背景需要重绘时调用.
OnPaint : 此时OnEraseBkgnd已经调用过了,所以在此响应函数体内对背景进行的操作将覆盖OnEraseBkgnd中所做的操作.
OnCtlColor : 有于在窗口将要被(第一次)绘制时响应,子窗口可以通过发关WM_CTLCOLOR请求父窗口传来一个HBRUSH.

 

MFC应用程序中处理消息的顺序

1.AfxWndProc()      该函数负责接收消息,找到消息所属的CWnd对象,然后调用AfxCallWndProc

2.AfxCallWndProc()  该函数负责保存消息(保存的内容主要是消息标识符和消息参数)供应用程序以后使用,然后调用WindowProc()函数

3.WindowProc()      该函数负责发送消息到OnWndMsg()函数,如果未被处理,则调用DefWindowProc()函数

4.OnWndMsg()        该函数的功能首先按字节对消息进行排序,对于WM_COMMAND消息,调用OnCommand()消息响应函数,对于WM_NOTIFY消息调用OnNotify()消息响应函数。任何被遗漏的消息将是一个窗口消息。OnWndMsg()函数搜索类的消息映像,以找到一个能处理任何窗口消息的处理函数。如果OnWndMsg()函数不能找到这样的处理函数的话,则把消息返回到WindowProc()函数,由它将消息发送给DefWindowProc()函数

5.OnCommand()       该函数查看这是不是一个控件通知(lParam参数不为NULL,如果lParam参数为空的话,说明该消息不是控件通知),如果它是,OnCommand()函数会试图将消息映射到制造通知的控件;如果他不是一个控件通知(或者如果控件拒绝映射的消息)OnCommand()就会调用OnCmdMsg()函数

6.OnCmdMsg()        根据接收消息的类,OnCmdMsg()函数将在一个称为命令传递(Command Routing)的过程中潜在的传递命令消息和控件通知。例如:如果拥有该窗口的类是一个框架类,则命令和通知消息也被传递到视图和文档类,并为该类寻找一个消息处理函数

 

MFC应用程序创建窗口的过程

1.PreCreateWindow()   该函数是一个重载函数,在窗口被创建前,可以在该重载函数中改变创建参数(可以设置窗口风格等等)

2.PreSubclassWindow() 这也是一个重载函数,允许首先子分类一个窗口

3.OnGetMinMaxInfo()   该函数为消息响应函数,响应的是WM_GETMINMAXINFO消息,允许设置窗口的最大或者最小尺寸

4.OnNcCreate()        该函数也是一个消息响应函数,响应WM_NCCREATE消息,发送消息以告诉窗口的客户区即将被创建

5.OnNcCalcSize()      该函数也是消息响应函数,响应WM_NCCALCSIZE消息,作用是允许改变窗口客户区大小

6.OnCreate()          该函数也是一个消息响应函数,响应WM_CREATE消息,发送消息告诉一个窗口已经被创建

7.OnSize()            该函数也是一个消息响应函数,响应WM_SIZE消息,发送该消息以告诉该窗口大小已经发生变化

8.OnMove()            消息响应函数,响应WM_MOVE消息,发送此消息说明窗口在移动

9.OnChildNotify()     该函数为重载函数,作为部分消息映射被调用,告诉父窗口即将被告知一个窗口刚刚被创建

 

MFC应用程序关闭窗口的顺序(非模态窗口)

1.OnClose()       消息响应函数,响应窗口的WM_CLOSE消息,当关闭按钮被单击的时候发送此消息

2.OnDestroy()     消息响应函数,响应窗口的WM_DESTROY消息,当一个窗口将被销毁时,发送此消息

3.OnNcDestroy()   消息响应函数,响应窗口的WM_NCDESTROY消息,当一个窗口被销毁后发送此消息

4.PostNcDestroy() 重载函数,作为处理OnNcDestroy()函数的最后动作,被CWnd调用


MFC应用程序中打开模式对话框的函数调用顺序

1.DoModal()             重载函数,重载DoModal()成员函数

2.PreSubclassWindow()   重载函数,允许首先子分类一个窗口

3.OnCreate()            消息响应函数,响应WM_CREATE消息,发送此消息以告诉一个窗口已经被创建

4.OnSize()              消息响应函数,响应WM_SIZE消息,发送此消息以告诉窗口大小发生变化

5.OnMove()              消息响应函数,响应WM_MOVE消息,发送此消息,以告诉窗口正在移动

6.OnSetFont()           消息响应函数,响应WM_SETFONT消息,发送此消息,以允许改变对话框中控件的字体

7.OnInitDialog()        消息响应函数,响应WM_INITDIALOG消息,发送此消息以允许初始化对话框中的控件,或者是创建新控件

8.OnShowWindow()        消息响应函数,响应WM_SHOWWINDOW消息,该函数被ShowWindow()函数调用

9.OnCtlColor()          消息响应函数,响应WM_CTLCOLOR消息,被父窗口发送已改变对话框或对话框上面控件的颜色

10. OnChildNotify()     重载函数,作为WM_CTLCOLOR消息的结果发送

 

MFC应用程序中关闭模式对话框的顺序

1.OnClose()        消息响应函数,响应WM_CLOSE消息,当"关闭"按钮被单击的时候,该函数被调用

2.OnKillFocus()    消息响应函数,响应WM_KILLFOCUS消息,当一个窗口即将失去键盘输入焦点以前被发送

3.OnDestroy()      消息响应函数,响应WM_DESTROY消息,当一个窗口即将被销毁时,被发送

4.OnNcDestroy()    消息响应函数,响应WM_NCDESTROY消息,当一个窗口被销毁以后被发送

5.PostNcDestroy()  重载函数,作为处理OnNcDestroy()函数的最后动作被CWnd调用


打开无模式对话框的顺序

1.PreSubclassWindow()    重载函数,允许用户首先子分类一个窗口

2.OnCreate()             消息响应函数,响应WM_CREATE消息,发送此消息以告诉一个窗口已经被创建

3.OnSize()               消息响应函数,响应WM_SIZE消息,发送此消息以告诉窗口大小发生变化

4.OnMove()               消息响应函数,响应WM_MOVE消息,发送此消息以告诉窗口正在移动

5.OnSetFont()            消息响应函数,响应WM_SETFONT消息,发送此消息以允许改变对话框中控件的字体


以上这些的执行都是按给定的顺序执行!

只有清楚的了解应用程序的执行顺序,才能在编写代码的时候知道,在什么时候应该执行什么,以及在什么地方该处理什么!
这只是本人总结的一点小小的经验,希望能对MFC的初学者有所帮助!

 


列表控件ListCtrl用法


原作者:不详    源出处:百度    发布者:施昌权    发布类型:转载    发布日期:2008-09-24

                        

        列表控件可以看作是功能增强的ListBox,它提供了四种风格,而且可以同时显示一列的多中属性值。MFC中使用CListCtrl类来封装列表控件的各种操作。
        通过调用BOOL Create( DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID );创建一个窗口,dwStyle中可以使用以下一些列表控件的专用风格:

  • LVS_ICON LVS_SMALLICON LVS_LIST LVS_REPORT 这四种风格决定控件的外观,同时只可以选择其中一种,分别对应:大图标显示,
    小图标显示,列表显示,详细报表显示
  • LVS_EDITLABELS 结点的显示字符可以被编辑,对于报表风格来讲可编辑的只为第一列。
  • LVS_SHOWSELALWAYS 在失去焦点时也显示当前选中的结点
  • LVS_SINGLESEL 同时只能选中列表中一项
        首先你需要设置列表控件所使用的ImageList,如果你使用大图标显示风格,你就需要以如下形式调用:
        CImageList* SetImageList( CImageList* pImageList, LVSIL_NORMAL);
        如果使用其它三种风格显示而不想显示图标你可以不进行任何设置,否则需要以如下形式调用:
        CImageList* SetImageList( CImageList* pImageList, LVSIL_SMALL);

        通过调用int InsertItem( int nItem, LPCTSTR lpszItem );可以在列砜丶 衝Item指明位置插入一项,lpszItem为显示字符。除LVS_REPORT风格外其他三种风格都只需要直接调用InsertItem就可以了,但如果使用报表风格就必须先设置列表控件中的列信息。

        通过调用int InsertColumn( int nCol, LPCTSTR lpszColumnHeading, int nFormat , int nWidth, int nSubItem);可以插入列。iCol为列的位置,从零开始,
lpszColumnHeading为显示的列名,nFormat为显示对齐方式,nWidth为显示宽度,nSubItem为分配给该列的列索引。

        在有多列的列表控件中就需要为每一项指明其在每一列中的显示字符,通过调用BOOL SetItemText( int nItem, int nSubItem, LPTSTR lpszText );可以设置每列的显示字符。nItem为设置的项的位置,nSubItem为列位置,lpszText为显示字符。下面的代码演示了如何设置多列并插入数据:

        m_list.SetImageList(&m_listSmall,LVSIL_SMALL);//设置ImageList
        m_list.InsertColumn(0,"Col 1",LVCFMT_LEFT,300,0);//设置列
        m_list.InsertColumn(1,"Col 2",LVCFMT_LEFT,300,1);
        m_list.InsertColumn(2,"Col 3",LVCFMT_LEFT,300,2);
        m_list.InsertItem(0,"Item 1_1");//插入行
        m_list.SetItemText(0,1,"Item 1_2");//设置该行的不同列的显示字符
        m_list.SetItemText(0,2,"Item 1_3");

        此外CListCtrl还提供了一些函数用于得到/修改控件的状态。
        COLORREF GetTextColor( )/BOOL SetTextColor( COLORREF cr );用于得到/设置显示的字符颜色。
        COLORREF GetTextBkColor( )/BOOL SetTextBkColor( COLORREF cr );用于得到/设置显示的背景颜色。
        void SetItemCount( int iCount );用于得到添加进列表中项的数量。
        BOOL DeleteItem(int nItem);用于删除某一项,
        BOOL DeleteAllItems( );将删除所有项。
        BOOL SetBkImage(HBITMAP hbm, BOOL fTile , int xOffsetPercent, int yOffsetPercent);用于设置背景位图。
        CString GetItemText( int nItem, int nSubItem );用于得到某项的显示字符。

        列表控件的消息映射同样使用ON_NOTIFY宏,形式如同:ON_NOTIFY( wNotifyCode, id, memberFxn ),wNotifyCode为通知代码,id为产生该消息的窗口ID,memberFxn为处理函数,函数的原型如同void OnXXXList(NMHDR* pNMHDR, LRESULT* pResult),其中pNMHDR为一数据结构,在具体使用时需要转换成其他类型的结构。对于列表控件可能取值和对应的数据结构为:

  • LVN_BEGINLABELEDIT 在开始某项编辑字符时发送,所用结构:NMLVDISPINFO

  • LVN_ENDLABELEDIT 在结束某项编辑字符时发送,所用结构:NMLVDISPINFO

  • LVN_GETDISPINFO 在需要得到某项信息时发送,(如得到某项的显示字符)所用结构:NMLVDISPINFO

        关于ON_NOTIFY有很多内容,将在以后的内容中进行详细讲解。

        关于动态提供结点所显示的字符:首先你在项时需要指明lpszItem参数为:LPSTR_TEXTCALLBACK。在控件显示该结点时会通过发送
TVN_GETDISPINFO来取得所需要的字符,在处理该消息时先将参数pNMHDR转换为LPNMLVDISPINFO,然后填充其中item.pszText。通过item中的
iItem,iSubItem可以知道当前显示的为那一项。下面的代码演示了这种方法:

        char szOut[8][3]={"No.1","No.2","No.3"}; //添加结点
        m_list.InsertItem(LPSTR_TEXTCALLBACK,...) m_list.InsertItem(LPSTR_TEXTCALLBACK,...) //处理消息
        void CParentWnd::OnGetDispInfoList(NMHDR* pNMHDR, LRESULT* pResult)
        {
               LV_DISPINFO* pLVDI = (LV_DISPINFO*)pNMHDR;
               pLVDI->item.pszText=szOut[pTVDI->item.iItem];//通过iItem得到需要显示的字符在数组中的位置
               *pResult = 0;
        }

        关于编辑某项的显示字符:(在报表风格中只对第一列有效)首先需要设置列表控件的LVS_EDITLABELS风格,在开始编辑时该控件将会发送
LVN_BEGINLABELEDIT,你可以通过在处理函数中返回TRUE来取消接下来的编辑,在编辑完成后会发送LVN_ENDLABELEDIT,在处理该消息时需要将
参数pNMHDR转换为LPNMLVDISPINFO,然后通过其中的item.pszText得到编辑后的字符,并重置显示字符。如果编辑在中途中取消该变量为NULL。
下面的代码说明如何处理这些消息:

        //处理消息 LVN_BEGINLABELEDIT
        void CParentWnd::OnBeginEditList(NMHDR* pNMHDR, LRESULT* pResult)
        {
               LV_DISPINFO* pLVDI = (LV_DISPINFO*)pNMHDR;
               if(pLVDI->item.iItem==0);//判断是否取消该操作
               *pResult = 1; else *pResult = 0;
        }
        //处理消息 LVN_BEGINLABELEDIT
        void CParentWnd::OnBeginEditList(NMHDR* pNMHDR, LRESULT* pResult)
        {
               LV_DISPINFO* pLVDI = (LV_DISPINFO*)pNMHDR;
               if(pLVDI->item.pszText==NULL);//判断是否已经取消取消编辑
               m_list.SetItemText(pLVDI->item.iItem,0,pLVDI->pszText);//重置显示字符
               *pResult = 0;
        }

        上面讲述的方法所进行的消息映射必须在父窗口中进行(同样WM_NOTIFY的所有消息都需要在父窗口中处理)。

        如何得到当前选中项位置:在列表控件中没有一个类似于ListBox中GetCurSel()的函数, 但是可以通过调用
        GetNextItem( -1, LVNI_ALL | LVNI_SELECTED);得到选中项位置。

 

Visual C++中实现双缓冲的基本原理

双缓冲的原理可以这样形象的理解:把电脑屏幕看作一块黑板。首先我们在内存环境中建立一个“虚拟“的黑板,然后在这块黑板上绘制复杂的图形,等图形全部绘制完毕的时候,再一次性的把内存中绘制好的图形“拷贝”到另一块黑板(屏幕)上。采取这种方法可以提高绘图速度,极大的改善绘图效果。能理解到这一层,工作便变得简单了,只要四步就可以搞定了,看下面代码:

例如在OnDraw()函数中可以如下所述实现双缓冲,其主要步骤分为四步:

以下为引用的内容:
CPen Pen;
Pen.CreatePen(PS_INSIDEFRAME,1,RGB(225,225,0));
CBrush Brush;
Brush.CreateSolidBrush(RGB(225,225,0));
CDC dcMem;
CBitmap bm;
CRect rc;
GetClientRect(&rc);
// Step 1:为屏幕DC创建兼容的内存DC :CreateCompatibleDC()
dcMem.CreateCompatibleDC(pDC);
// Step 2:创建位图:CreateCompatibleBitmap()
bm.CreateCompatibleBitmap(pDC,rc.Width(),rc.Height());
// Step 3:把位图选入设备环境:SelectObject(),可以理解为选择画布
dcMem.SelectObject(&bm);
dcMem.SelectObject(Pen);
dcMem.SelectObject(Brush);
dcMem.Ellipse(0,0,50,50);//画椭圆
// Step 4:把绘制好的图形“拷贝“到屏幕上:BitBlt()
pDC->BitBlt(0,0,rc.Width(),rc.Height(),&dcMem,0,0,SRCCOPY);
dcMem.DeleteDC();
bm.DeleteObject();

这样便实现了双缓冲,通过这个方法可以防止在VC中画图时出现屏幕闪烁的情况。

你可能感兴趣的:(数据结构,mfc,vc++,报表,图形,imagelist)