消息机制和指针获取与操作

C++ Development 专栏收录该内容
87 篇文章 0 订阅

 MFC是Win API与C++的结合,API,即微软提供的WinDOS下应用程序的编程语言接口,是一种软件编程的规范,但不是一种程序开发语言本身,可以允许用户使用各种各样的第三方(如我是一方,微软是一方,Borland就是第三方)的编程语言来进行对WinDOS下应用程序的开发,使这些被开发出来的应用程序能在WinDOS下运行,比如VB,VC++,Java,Dehpi编程语言函数本质上全部源于API,因此用它们开发出来的应用程序都能工作在WinOS的消息机制和绘图里,遵守WinDOS作为一个操作系统的内部实现,这其实也是一种必要,微软如果不提供API,这个世上对Win编程的工作就不会存在,微软的产品就会迅速从时尚变成垃圾,上面说到MFC是微软对API函数的专用C++封装,这种结合一方面让用户使用微软的专业C++ SDK来进行Win下应用程序的开发变得容易,因为MFC是对API的封装,微软做了大量的工作,隐藏了好多程序开发人员在Win下用C++ & MFC编制软件时的大量内节,如应用程序实现消息的处理,设备环境绘图,这种结合是以方便为目的的,必定要付出一定代价(这是微软的一向作风),因此就造成了MFC对类封装中的一定程度的的冗余和迂回,但这是可以接受的..
  最后要明白MFC不只是一个功能单纯的界面开发系统,它提供的类绝大部分用来进行界面开发,关联一个窗口的动作,但它提供的类中有好多类不与一个窗口关联,即类的作用不是一个界面类,不实现对一个窗口对象的控制(如创建,销毁),而是一些在WinDOS(用MFC编写的程序绝大部分都在WinDOS中运行)中实现内部处理的类,如数据库的管理类等,学习中最应花费时间的是消息和设备环境,对C++和MFC的学习中最难的部分是指针,C++面向对像程序设计的其它部分,如数据类型,流程控制都不难,建议学习数据结构C++版。

MFC是微软封装了的API。什么意思呢?windows作为一个提供功能强大的应用程序接口编程的操作系统,的确方便了许多程序员,传统的win32开发(直接使用windows的接口函数API)对于程序员来说非常的困难,因为,API函数实在太多了,而且名称很乱,从零构架一个窗口动辄就是上百行的代码。MFC是面向对象程序设计与Application framework的完美结合,他将传统的API进行了分类封装,并且为你创建了程序的一般框架, 
  MFC是对WindowsAPI的封装,大大简化了我们的工作;学VC主要就是要学MFC,大约有100多个类,但常用的也就二三十个。应该象背4级单词一样将这些常用类搞懂;当然不要死记,要通过看帮助、看例子、动手练习来学会它们;而且,并非每个类的内部的所有函数都要学会,要日积月累。如果真的想成为高手,做个笔记本把自己认为重要的类、函数记下来,随时学习,也是很好的突击方法。 


下面介绍最重要的MFC。 
  CWnd:窗口,它是大多数“看得见的东西”的父类(Windows里几乎所有看得见的东西都是一个窗口,大窗口里有许多小窗口),比如视图CView、框架窗口CFrameWnd、工具条CToolBar、对话框CDialog、按钮CButton,etc;一个例外是菜单(CMenu)不是从窗口派生的。该类很大,一开始也不必学,知道就行了。 
  CDocument文档,负责内存数据与磁盘的交互。最重要的是OnOpenDocument(读入),OnSaveDocument(写盘),Serialize(读写) 
  CView视图,负责内存数据与用户的交互。包括数据的显示、用户操作的响应(如菜单的选取、鼠标的响应)。最重要的是OnDraw(重画窗口),通常用CWnd::Invalidate()来启动它。另外,它通过消息映射表处理菜单、工具条、快捷键和其他用户消息。你自己的许多功能都要加在里面,你打交道最多的就是它。 
  CDC设备文本。无论是显示器还是打印机,都是画图给用户看。这图就抽象为CDC。CDC与其他GDI(图形设备接口)一起,完成文字和图形、图像的显示工作。把CDC想象成一张纸,每个窗口都有一个CDC相联系,负责画窗口。CDC有个常用子类CClientDC(窗口客户区),画图通常通过CClientDC完成。 
  CDialog对话框 
  CWinApp应用程序类。似于C中的main函数,是程序执行的入口和管理者,负责程序建立、消灭,主窗口和文档模板的建立。最常用函数InitInstance():初始化。 
  CGdiObject及子类,用于向设备文本画图。它们都需要在使用前选进DC。 
  CPen笔,画线 
  CBrush刷子,填充 
  CFont字体,控制文字输出的字体 
  CBitmap位图 
  CPalette调色板 
  CRgn区域,指定一块区域可以用于做特殊处理。 
  CFile文件。最重要的不外是Open(打开),Read(读入),Write(写) 
  CString字符串。封装了C中的字符数组,非常实用。 
  CPoint点,就是(x,y)对 
  CRect矩形,就是(left,top,right,bottom) 
  CSize大小,就是(cx,cy)对(宽、高)MFC是在1992年的Microsoft 16位版的C/C++编译器的7.0版本中作为一个扩展轻量级的Windows API面向对象的C++封装库而引入的。此时,C++因为它在和API方面的卓越表现,刚刚开始被用来取代C应用于开发商用软件。因此,他们推出了替代早期的老式的字符界面的集成开发环境(IDE)的PWB。
  有趣的是,MFC使用“Afx”作为所有的全局函数的前缀,“afx”作为全局变量的前缀。因为在MFC的早期开发阶段它叫“Application Framework Extensions”缩写为“AFX”。AFX提供了对Windows API的高度抽象,建立了全新的面向对象的AFX API,但它对于新手来说太复杂了,所以AFX小组不得不重新开始。后来他们创建了一组C++类,这就是MFC。MFC这个名字被采用得太晚了以至于没来得及修改这些引用。
  最近,MFC8.0和Visual Studio 2005一起发布了;MFC9.0和Visual Studio 2008一起发布。在免费的Express版本的Visual Studio 2005/2008中没有包含MFC。
  作为一个强有力的竞争对手,为Borland的Turbo C++编译器设计OWL(Object Windows Library)在同一时间也发布了。但最后,Borland停止了对OWL的继续开发并且不久就从Microsoft那里购买了MFC头文件,动态链接库等的授权,微软没有提供完整的MFC的集成支持。之后Borland发布了VCL(Visual Component Library)来替换OWL框架。


1) 在View中获得Doc指针 
2) 在App中获得MainFrame指针 
3) 在View中获得MainFrame指针 
4) 获得View(已建立)指针 
5) 获得当前文档指针 
6) 获得状态栏与工具栏指针 
7) 获得状态栏与工具栏变量 
8) 在Mainframe获得菜单指针 
9) 在任何类中获得应用程序类 
10) 从文档类取得视图类的指针(1) 
11) 在App中获得文档模板指针 
12) 从文档模板获得文档类指针 
13) 在文档类中获得文档模板指针 
14) 从文档类取得视图类的指针(2) 
15) 从一个视图类取得另一视图类的指针

VC中编程对于刚刚开始学习的同学,最大的障碍和问题就是消息机制和指针获取与操作。其实这些内容基本上是每本VC学习工具书上必讲的内容,而且通过MSDN很多问题都能解决。 
下面文字主要是个人在编程中指针使用的一些体会,说的不当的地方请指正。 
一般我们使用的框架是VC提供的Wizard生成的MFC App Wizard(exe)框架,无论是多文档还是单文档,都存在指针获取和操作问题。 
下面这节内容主要是一般的框架,然后再讲多线程中的指针使用。使用到的类需要包含响应的头文件。首先一般获得本类(视,文档,对话框都支持)实例指针 this,用this的目的,主要可以通过类中的函数向其他类或者函数中发指针,以便于在非本类中操作和使用本类中的功能。

1) 在View中获得Doc指针 CYouSDIDoc *pDoc=GetDocument();一个视只能有一个文档。


2) 在App中获得MainFrame指针 
CWinApp 中的 m_pMainWnd变量就是MainFrame的指针 
也可以: CMainFrame *pMain =(CMainFrame *)AfxGetMainWnd();


3) 在View中获得MainFrame指针 CMainFrame *pMain=(CmaimFrame *)AfxGetApp()->m_pMainWnd;


4) 获得View(已建立)指针 CMainFrame *pMain=(CmaimFrame *)AfxGetApp()->m_pMainWnd; 
CyouView *pView=(CyouView *)pMain->GetActiveView();


5) 获得当前文档指针 CDocument * pCurrentDoc =(CFrameWnd *)m_pMainWnd->GetActiveDocument();


6) 获得状态栏与工具栏指针 CStatusBar * pStatusBar=(CStatusBar *)AfxGetMainWnd()->GetDescendantWindow(AFX_IDW_STATUS_BAR); 
CToolBar * pToolBar=(CtoolBar *)AfxGetMainWnd()->GetDescendantWindow(AFX_IDW_TOOLBAR);

 

7) 如果框架中加入工具栏和状态栏变量还可以这样 (CMainFrame *)GetParent()->m_wndToolBar; 
(CMainFrame *)GetParent()->m_wndStatusBar;

 

8) 在Mainframe获得菜单指针 CMenu *pMenu=m_pMainWnd->GetMenu();


9) 在任何类中获得应用程序类 
用MFC全局函数AfxGetApp()获得。

 

10) 从文档类取得视图类的指针 
我是从http://download.cqcnc.com/soft/program/article/vc/vc405.html学到的,从文档获得 视图类指针目的一般为了控制同一文档的多个视图的定位问题,我的体会特别是文字处理CEditView当产生多个视图类时,这个功能是非常需要的。 
CDocument类提供了两个函数用于视图类的定位: 
GetFirstViewPosition()和GetNextView() virtual POSITION GetFirstViewPosition() const; 
virtual CView* GetNextView(POSITION& rPosition) const;

注意:GetNextView()括号中的参数用的是引用方式,因此执行后值可能改变。 
GetFirstViewPosition()用于返回第一个视图位置(返回的并非视图类指针,而是一个POSITION类型值), GetNextView()有两个功能:返回下一个视图类的指针以及用引用调用的方式来改变传入的POSITION类型参数的值。很明显,在Test程序 中,只有一个视图类,因此只需将这两个函数调用一次即可得到CTestView的指针如下(需定义一个POSITION结构变量来辅助操作): CTestView* pTestView; 
POSITION pos=GetFirstViewPosition(); 
pTestView=GetNextView(pos);

这样,便可到了CTestView类的指针pTestView.执行完几句后,变量pos=NULL,因为没有下一个视图类,自然也没有下一个视图类的 POSITION.但是这几条语句太简单,不具有太强的通用性和安全特征;当象前面说的那样,当要在多个视图为中返回某个指定类的指针时,我们需要遍历所 有视图类,直到找到指定类为止。判断一个类指针指向的是否某个类的实例时,可用IsKindOf()成员函数时行检查,如: pView->IsKindOf(RUNTIME_CLASS(CTestView)); 
即可检查pView所指是否是CTestView类。

有了以上基础,我们已经可以从文档类取得任何类的指针。为了方便,我们将其作为一个文档类的成员函数,它有一个参数,表示要获得哪个类的指针。实现如下: CView* CTestDoc::GetView(CRuntimeClass* pClass) 

CView* pView; 
POSITION pos=GetFirstViewPosition();

while(pos!=NULL){ 
pView=GetNextView(pos); 
if(!pView->IsKindOf(pClass)) 
break; 
}

if(!pView->IsKindOf(pClass)){ 
AfxMessageBox("Connt Locate the View.\r\n http://www.VCKBASE.com"); 
return NULL; 
}

return pView; 
}

其中用了两次视图类的成员函数IsKindOf()来判断,是因为退出while循环有三种可能:

1.pos为NULL,即已经不存在下一个视图类供操作; 
2.pView已符合要求。

1和2同是满足。这是因为GetNextView()的功能是将当前视图指针改变成一个视图的位置同时返回当前视图指针,因此pos是pView的下一个 视图类的POSITION,完全有可能既是pos==NULL又是pView符合需要。当所需的视图是最后一个视图是最后一个视图类时就如引。因此需采用 两次判断。 
使用该函数应遵循如下格式(以取得CTestView指针为例):CTestView* pTestView=(CTestView*)GetView(RUNTIME_CLASS(CTestView)); 
RUNTIME_CLASS是一个宏,可以简单地理解它的作用:将类的名字转化为CRuntimeClass为指针。 
至于强制类型转换也是为了安全特性考虑的,因为从同一个基类之间的指针类型是互相兼容的。这种强制类型转换也许并不必要,但能避免一些可能出现的麻烦。

3.从一个视图类取得另一视图类的指针 综合1和2,很容易得出视图类之间互相获得指针的方法:就是用文档类作中转,先用1的方法得到文档类的指针,再用2的方法,以文档类的视图定位函数取得另一个视图类。同样,可以实现成一个函数: 
(假设要从CTestAView中取得指向其它视图类的指针)CView* CTestAView::GetView(CRuntimeClass* pClass) 

CTestDoc* pDoc=(CTestDoc*)GetDocument(); 
CView* pView; 
POSITION pos=pDoc->GetFirstViewPosition(); 
while(pos!=NULL){ 
pView=pDoc->GetNextView(pos); 
if(!pView->IsKindOf(pClass)) 
break; 

if(!pView->IsKindOf(pClass)){ 
AfxMessageBox("Connt Locate the View."); 
return NULL; 
}

return pView; 

这个函数和2中的GetView()相比,一是多了第一句以取得文档类指针,二是在GetFirstViewPosition()和GetNextView()前加上了文档类指针,以表示它们是文档类成员函数。 
有了此函数;当要从CTestAView中取得CTestBView的指针时,只需如下:CTestBView* pTestbView=(CTestView*)GetView(RUNTIME_CLASS(CTestBView));


11)对于单文档中也可以加入多个文档模板,但是一般的开发就使用MDI方式开发多文档模板,其方法与上述视图的获取方法很接近,这里稍做解释,如果不清 楚,请查阅MSDN,(以下四个内容(11、12、13、14)来源:http: //sanjianxia.myrice.com/vc/vc45.htm)

可以用CWinApp::GetFirstDocTemplatePostion获得应用程序注册的第一个文档模板的位置; 
利用该值来调用CWinApp::GetNextDocTemplate函数,获得第一个CDocTemplate对象指针。 POSITION GetFirstDocTemplate( ) const; 
CDocTemplate *GetNextDocTemplate( POSITION & pos ) const;

第二个函数返回由pos 标识的文档模板。POSITION是MFC定义的一个用于迭代或对象指针检索的值。通过这两个函数,应用程序可以遍历整个文档模板列表。如果被检索的文档模板是模板列表中的最后一个,则pos参数被置为NULL。

在文档窗口框架里面怎么都获得各自的指针


首先在视图类里面有个GetDocument()函数 则 在试图中通过这个函数可以获得文档指针
对于一个多文档程序来说它有几个子窗口视图窗口和相应的多个文档类 
获得应用程序主窗口的指针主窗口的指针保存在CWindThread::m_pMainWnd,则调用AfxGetMainWnd可以实现

AfxGetApp() 指向程序的单一CWinApp对象的指针 此返回的指针可以被用来访问应用程序的信息,如主消息调度代码以及顶层窗口
HINSTANCE AfxGetInstanceHandle() 返回应用程序的当前实例的HINSTANCE 值,如果是从与MFC的USRDLL版本连接的DLL内调用的,则返回代表DLL

的HINSTANCE值 这个函数使你能够获得当前应用程序的实例句柄,

AfxGetResourceHandle() 应用程序调入缺省资源的实例的HINSTANCE局部 
利用这个函数返回的HINSTANCE句柄来直接访问应用程序的句柄,例如在调用FindResource时使用

在MDI活着SDI应用程序中获得了主框架指针就比较容易获得其他窗口指针活着其他有用信息,

CMainFrame::GetActiveDocument()获得当前活动文档指针

Doc类中科研 POSITON pos=GetFirstViewPosTion()

m_pMainWnd->GetActiveDocument()

应用程序中GetFirstDocTemplate GetNextDocTemplate获得文档模板对象
文档列表是由CDocTemplate类管理的 GetFirstDocPosition GetNextDoc函数获得文档指针
视图列表CDocument 类来管理,GetFirstViewPosition GetNextView函数来获得


在CWinApp中 通过AfxGetMainWnd() 或者直接就是应用程序里面的m_pmainwnd指针
科研通过AfxGetMainWnd()->GetMDIActive 或者->GetActiveFrame获得CChildFrame
单文档科研通过AfxGetMainWnd()->GetActiveView()->GetDocument() 获得文档指针
在多文档里面 通过AfxGetMainWnd()->MDIGetActive()->GetActiveView()->GetDocument
即先获得框架指针 然后 由框架指针获得视图指针 然后视图指针获得文档指针

对于在CMainFrame中 科研通过AfxGetApp获得theApp指针 MDI通过MDIGetActive 或则GetActiveFrame获得子框架指针
对于SDI 通过GetActiveVie->GetDocument MDI MDIGetActive()->GetActiveView()->GetDocument() 
SDI直接GetActiveView获得视图指针 MDI MDIGretActive ->GetActiveView

在CChildFrame AfxGetApp 获得theApp GetParentFrame()获得主框架 GetActiveView

CDocument AfxGetApp AfxGetmainWnd

6) 获得状态栏与工具栏指针 CStatusBar * pStatusBar=(CStatusBar *)AfxGetMainWnd()->GetDescendantWindow(AFX_IDW_STATUS_BAR); 
CToolBar * pToolBar=(CtoolBar *)AfxGetMainWnd()->GetDescendantWindow(AFX_IDW_TOOLBAR);

7) 如果框架中加入工具栏和状态栏变量还可以这样 (CMainFrame *)GetParent()->m_wndToolBar; 
(CMainFrame *)GetParent()->m_wndStatusBar;

8) 在Mainframe获得菜单指针 CMenu *pMenu=m_pMainWnd->GetMenu

1.列表视图控件:
   
  ClistCtrl类的用法:
   1常规操作函数:它们可以完成向列表视图中插入新
   条目或新列等操作。
  ISubItem-指定条目子索引项
  BOOL DeleteAllItems()删除列表控件中所有条目
  int InsertColumn(int nCol,const LVCOLUMN * pColum)插入新列 操作成功返回新列索引
   nCol-----指定新列索引。
   pColum---为LVCOLUMN结构指针,包含将插入的信息。
   LVCOLUMN结构
   例:m_ListCtrl.InsertColumn( 0, _T( "所有匹配的单词" ), LVCFMT_LEFT, 115 );
  int InsertItem(const LVITEM *pItem)调用该函数以
  向列表中插入新条目 返回新条目索引值 
  pItem-------为LVITEM结构,其中包含了将插入的条目信息
  列表控制中包含两个非常重要的数据结构LV_ITEM和LV_COLUMN。LV_ITEM用于定义列表控制的一个表项,LV_COLUMN用于定义列表控制的一个表列
  例:m_ListCtrl.InsertItem( 0, WordSet.m_Word );//数据项
  CString s;
   s.Format("%d",m_Set.m_column1);//格式化
   //int InsertItem(i,s,0)调用该函数以向列表中插入新条目 返回新条目索引值
   //相当于插入新的一行 数字代表列数
   m_ListCtrlx.InsertItem(i,s,0);
  EnsureVisible---调用该函数以确保指定的列表视图条目可见,其原型为:
  BOOL EnsureVisible(int nItem,BOOL bPartialOK)
   返回值:
   nItem:指定了必须可见的条目索引。
   bPartialOK:指定了是否允许部分可见。
   列表视图控件将在必要时进行滚动,以确保指定条目可见。如果bPartialOK参数为非零值,则当条目部分可见时,列表视图控件不进行滚动。
  
  2。属性操作函数:它们可以完成对列表视图控件的属性的设置和查询等操作。
  DWORD SetExtendedStyle(DWORD dwNewStyle) //先设计列表风格
   如果函数调用成功,则返回列表视图控件先前所使用的
  扩展风格。
  LVS_EX_FULLROWSELECT-----对列表视图中的项目进行整行选择,即选择某条目时,该条目的所在行都被选择。
  LVS_EX_GRIDLINES----将在列表视图控件中绘制网格线0x21。
  例:m_ListCtrl.SetExtendedStyle( LVS_EX_GRIDLINES );//将在列表视图控件中绘制网格线0x21。
  POSITION GetFirstSelectedItemPosition() const 如果函数执行成功,则返回条目的POSITION值,如果返回值为KULL,则表示当前列表视图控件中没有条目选中。
  Int GetNextSelectedItem(POSITION& pos) const 如果函数执行成功,则返回列表视图控件中下一个被选中的条目索引。其中参数pos为将接收条目POSITION值的变量。
  BOOL SetColumnWidth(int nCol,int cx)
   调用该函数以设置报表视图或列表视图中指定列的宽度。
   nCol----指定了将被设置宽度的列索引。
   cx-------指定了列的新宽度。
  Int GetItemText(int nItem, int nSubItem,LPTSTR lpszText,int nLen) const;
  CString GetItemText(int nItem, int nSubItem) const;
   对于int,其返回值为所指定的文本长度;对CString,其返回值为包含条目文本的CString对象。
   nItem--------指定将被获取文本的条目索引
   nSubItem---------指定了将被获取文本的条目子项的索引。
   lpszText---------将返回条目文本的缓冲区指针。
   nLen----------指定lpszText缓冲区的长度。
   如果nSubItem为0,则函数将获取条目的标签,nSubItem不为0,将获取指定条目子项的文本。
   例:
   
  BOOL SetItemText(int nItem, int nSubItem,LPTSTR lpszText);
   如果函数调用成功,则返回非零值,否则返回零值。
   nItem--------指定将被设置的条目索引
   nSubItem---------指定了将被设置文本的条目子项的索引。
   lpszText---------指定了将被设置的新条目文本。
  
   例:
  char szTemp[27] = { '/0' };//缓冲区
  
   POSITION Pos = m_ListCtrl.GetFirstSelectedItemPosition();
   if ( Pos == NULL ) return;
   int nCurIndex = m_ListCtrl.GetNextSelectedItem( Pos );
   
   m_Display.Empty();//文本编辑框
   m_ListCtrl.GetItemText( nCurIndex, 0, szTemp, 26 );
  CImageList:图像列表
  
  CImagelist* GetImageList(int nImageList) const;
   如果函数执行成功,则返回列表视图控件的图像列表指针。
   nImageList----指定了将获得的图像列表类型。
   LVSIL_NORMAL---获取大图标图像列表指针
   LVSIL_SMALL--获取小图标图像列表指针
   LVSIL_STATE--获取状态图像列表指针
   CImageList* SetImageList(CImageList* pImageList,int nImageList);
   如果函数执行成功,返回先前的图像列表指针
   参数: pImageList--指定了要设置的图像列表指针 
   nImageList--指定了要设置的图像列表类型
   COLORREF GetBkColor() const; 调用该函数获得列表视图控件的背景颜色。
   函数执行成功,返回32位RGB值
   BOOL SetBkColor (COLORREF cr); 调用该函数设置列表视图控件的背景颜色。
   函数执行成功,返回非零值,否则返回零值。
   CHeaderCtrl* GetHeaderCtrl(); 调用改函数以得到列表视图控件的标头控件指针
   函数调用成功,返回列表视图控件所使用的标头控件指针
   例:
   m_imagelist.Create(16,16,TRUE,2,2); 
   m_imagelist.Add(AfxGetApp()->LoadIcon(IDI_YES));
   m_imagelist.Add(AfxGetApp()->LoadIcon(IDI_NO));
   m_list.SetImageList(&m_imagelist,LVSIL_SMALL);
   
   m_list.SetExtendedStyle(0x21);
   m_list.SetFont(&m_font1);//设置全部字体
  // m_list.GetHeaderCtrl()->SetFont(&m_font1);//只设置标头控件的字体
   //以下函数与文本有关
   m_list.SetBkColor(RGB(247,247,0));
   m_list.SetTextColor(RGB(255,255,255));//设置列表视图控件的文本颜色
   m_list.SetTextBkColor(RGB(0,0,255));//设置列表视图控件中文本背景色
  m_iImageList.Create(24, 24, TRUE,1, 0);
   HICON hIcon = NULL;
   hIcon = (HICON)::LoadImage(::AfxGetInstanceHandle(), 
   MAKEINTRESOURCE(IDI_KEBIAO), IMAGE_ICON, 24, 24, 0);
   m_iImageList.Add(hIcon);
   m_FileTree.SetImageList ( &m_iImageList,TVSIL_NORMAL );
  ----------------------事例----------------------------------
  实现排序:
  BOOL m_Bs;
  BOOL m_bIsAsc;//互斥信号量:true升序 反之降序
  CDRecordset m_Set; 
  void Sort(BOOL isAsc=TRUE,int secol=1);
  
  void CBaDialog::Sort(BOOL isAsc,int secol)
  { 
   if(m_Set.IsOpen())
   m_Set.Close();
   this->Select(); //打开所选择数据表
   m_bSet.Close();//只对m_Set数据标排序 所以关闭m_bSet
   CODBCFieldInfo fieldInfo;
   m_Set.GetODBCFieldInfo(secol,fieldInfo);//返回纪录集中字段的特定种类的信息 即所选
   择的信息
   if(isAsc)//实现排序功能
   {
   m_Set.m_strSort=fieldInfo.m_strName+" ASC";//order by
   m_bIsAsc=TRUE;
   }
   else
   {
   m_Set.m_strSort=fieldInfo.m_strName+" DESC";
   m_bIsAsc=FALSE;
   }
   m_Set.Requery(); 
  
  }
  //单击索引
  void CBaDialog::OnColumnclickList3(NMHDR* pNMHDR, LRESULT* pResult) 
  {
   NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;//系统自动生成
   // TODO: Add your control notification handler code here
   if(FALSE== m_bS)
   {
   int k= pNMListView->iSubItem; //鼠标单击选择第几行
   Sort(!m_bIsAsc, k);
   m_ListCtrlx.DeleteAllItems();
   this->Show();//把数据库学生的数据表内容显示
   }
   *pResult = 0;
  }
  右键单击事件
  void CCCDlg::OnRclickList1(NMHDR* pNMHDR, LRESULT* pResult) 
  {
   // TODO: Add your control notification handler code here
   POSITION pos = m_list.GetFirstSelectedItemPosition(); //得到当前选中的行
   if(pos) 
   {
   int nItem = m_list.GetNextSelectedItem(pos);
   
   CPoint pt;
   ::GetCursorPos(&pt);
   COfficeXPMenu m_menu;
   m_menu.LoadMenu(IDR_MENU_LIST);
   COfficeXPMenu::SetType(TYPE_XP); //设置菜单的风格,(TYPE_XP, TYPE_NORMAL) 
   
   COfficeXPMenu *psub = (COfficeXPMenu *)m_menu.GetSubMenu(0); 
   DWORD dwID =psub->TrackPopupMenu(TPM_RIGHTBUTTON,pt.x,pt.y ,this); 
   m_menu.DestroyMenu(); 
   }
   
  
   *pResult = 0;
  }
  列表双击事件(实现在编辑框中显示内容)
  // 双击则显示显示信息
  void CListItemDlg::OnDblclkList(NMHDR* pNMHDR, LRESULT* pResult) 
  {
   CWordDaoSet WordSet;
   CString strSQL;
   CString strNewLine( "/r/n" );//回车换行
   char szTemp[27] = { '/0' };
  //得到双击列的位置
   POSITION Pos = m_ListCtrl.GetFirstSelectedItemPosition();
   if ( Pos == NULL ) return;
   int nCurIndex = m_ListCtrl.GetNextSelectedItem( Pos );
  
   m_Display.Empty();
   m_ListCtrl.GetItemText( nCurIndex, 0, szTemp, 26 );
  
   strSQL.Format( "SELECT * FROM WordList WHERE word = '%s'", szTemp );
  
   if ( WordSet.IsOpen() )
   WordSet.Close();
  
   WordSet.Open( AFX_DAO_USE_DEFAULT_TYPE, strSQL, 0 );
   
   if ( !WordSet.IsEOF() )
   {
   if ( !WordSet.m_Explain0.IsEmpty() )
   m_Display += WordSet.m_Explain0 ;//字符串相加
   if ( !WordSet.m_Explain1.IsEmpty() )
   m_Display += ( strNewLine + WordSet.m_Explain1 );
   if ( !WordSet.m_Explain2.IsEmpty() )
   m_Display += ( strNewLine + WordSet.m_Explain2 );
   if ( !WordSet.m_Phrase0.IsEmpty() )
   m_Display += ( strNewLine + WordSet.m_Phrase0 );
   if ( !WordSet.m_Phrase1.IsEmpty() )
   m_Display += ( strNewLine + WordSet.m_Phrase1 );
   if ( !WordSet.m_Phrase2.IsEmpty() )
   m_Display += ( strNewLine + WordSet.m_Phrase2 );
   if ( !WordSet.m_Sentence0.IsEmpty() )
   m_Display += ( strNewLine + WordSet.m_Sentence0 );
   if ( !WordSet.m_Sentence1.IsEmpty() )
   m_Display += ( strNewLine + WordSet.m_Sentence1 );
   }
  
   if ( WordSet.IsOpen() )
   WordSet.Close();
  
   UpdateData( FALSE );//在编辑框中显示文本
   
   *pResult = 0;
  }
  、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、
  、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、
  void CCcDlg::OnDblclkList(NMHDR* pNMHDR, LRESULT* pResult) //双击list控件的函数
  {
   
   POSITION pos = m_list.GetFirstSelectedItemPosition(); //得到当前选中的行
   if(pos) //如果选中一行
   {
   int nItem = m_list.GetNextSelectedItem(pos);
   
   CAddDlg dlgadd;
   dlgadd.m_bAddOrModify=1; //修改记录的标志
   
   if(m_list.GetItemText(nItem,0)=="N")
   dlgadd.m_bPassed=false; //单项按钮
   else
   dlgadd.m_bPassed=true;
  
   dlgadd.m_strName=m_list.GetItemText(nItem,1);
   dlgadd.m_strCollege =m_list.GetItemText(nItem,2);
   dlgadd.m_strReason =m_list.GetItemText(nItem,3);
   dlgadd.m_date1 =m_list.GetItemText(nItem,4);
   dlgadd.m_date2 =m_list.GetItemText(nItem,5);
   dlgadd.m_strRemark =m_list.GetItemText(nItem,6);
   
   dlgadd.DoModal(); 
   } 
   *pResult = 0;
  }
  
  CListCtrl中选择变化时如何获得通知?
  我在Report View中使用了一个CListCtrl(自绘制类型),我想知道什么时候选择项发生了改变.
  在选择项变化时,可以使用按钮有效或失效,按如下操作:
   加入LVN_ITEMCHANGED消息处理.
   void CYourClassNameHere::OnItemchangedEventList(NMHDR* pNMHDR, LRESULT* pResult)
  {
   NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;
   *pResult = 0;
   if (pNMListView->uChanged == LVIF_STATE)
   {
   if (pNMListView->uNewState)
   GetDlgItem(IDC_DELETE)->EnableWindow(TRUE);
   else
   GetDlgItem(IDC_DELETE)->EnableWindow(FALSE);
   }
  }
  /
  树视图控件-树视图控件 
  属性设置-style:有按钮、有行、line at root 、边框;more style:卷轴、工具栏提示。
  属性操作函数
  。GetParentItem:调用该函数得到指定树视图条目的父条目.
  HTREEITEM GetParentItem(HTREEITEM hItem);
   hItem:指定条目句柄。
  常规操作函数
  .InsertItem:向树形控件插入新条目
  /* TVINSERTSTRUCT tvInsert; //d第一中插入方法
   tvInsert.hParent = NULL;//指定了父条目句柄,参数为TVI_ROOT或NULL,则该条目被插入控件的根部
   tvInsert.hInsertAfter = NULL;
   tvInsert.item.mask = TVIF_TEXT;
   tvInsert.item.pszText = _T("VC知识库www.vckbase.com");
   
   HTREEITEM hCountry = m_CtrlTree.InsertItem(&tvInsert);*/
  //第二种方法
   HTREEITEM hCountry = m_CtrlTree.InsertItem( _T("VC知识库www.vckbase.com"), NULL, NULL);//根目录
   HTREEITEM hPA = m_CtrlTree.InsertItem(TVIF_TEXT,_T("程序员社区"), 0, 0, 0, 0, 0, hCountry, NULL);//二级目录
   
   HTREEITEM hWA = m_CtrlTree.InsertItem(_T("文档代码中心"),0, 0, hCountry, hPA);// 二级目录
  // m_CtrlTree.InsertItem(_T("程序员论坛"),0, 0, hPA, TVI_SORT);//三级目录
   m_CtrlTree.InsertItem(_T("程序员论坛"), hPA, TVI_SORT);
   m_CtrlTree.InsertItem(_T("程序员交友"), hPA, TVI_SORT);
   m_CtrlTree.InsertItem(_T("人才交流"), hPA, TVI_SORT);
   
   m_CtrlTree.InsertItem(_T("文档中心"), hWA, TVI_SORT); //三级目录
   m_CtrlTree.InsertItem(_T("代码仓库"), hWA, TVI_SORT);
   m_CtrlTree.InsertItem(_T("个人专辑"), hWA, TVI_SORT);
  
   m_CtrlTree.Expand(hCountry,TVE_EXPAND);
  。GetItemText:得到指定条目的文本
  。SetItemText 
  
  .Expand:调用该函数以展开或收拢指定条目的子条目。
  BOOL Expand(HTREEITEM hItem,UINT nCode);
   函数成功,返回非零值,否则返回零值。
  hItem:指定将打开或收拢的条目句柄。 
  nCode:指定了采取的操作,如下:
   TVE_COLLAPSE:收拢列表
   TVE_COLLAPSERESET:收拢列表,并删除子条目
   TVE_EXPAND:打开列表
   TVE_TOGGLE:如果当前列表已经打开,则收拢之;如果已经收拢,则打开;
  选择所单击的内容
  void CPppView::OnSelchangingTree1(NMHDR* pNMHDR, LRESULT* pResult) 
  {
   NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR;
   // TODO: Add your control notification handler code here
   CTreeCtrl* pTree2 = (CTreeCtrl*) GetDlgItem(IDC_TREE1);//
   HTREEITEM hSelected = pNMTreeView->itemNew.hItem;
   CPppDoc* pDoc = (CPppDoc*)GetDocument();//一切都以文档传输
   CString hParentName;
   HTREEITEM hParent=pTree2->GetParentItem(hSelected); //
   if(hSelected!=NULL)
   {
   pDoc->Name=pTree2->GetItemText(hSelected);// Name在文档里定义
   } 
  
   *pResult = 0;
  }
  /
  2.组合框控件: 
  int GetCurSel() const 得到当前选项的索引,
  失败则返回CB_ERR。
  Int SetCurSel(int nSelect);
   如果函数调用成功,返回当前选项索引。如果nSelect的值超出范围,或为-1,则返回CB_ERR,并清除当前选项。
  int GetLBText(int nIndex,Cstring& rString ) const
  void GetLBText(int nIndex, LPTSTR lpszText) const
   如果函数调用成功,则返回字符串的字节长度(不包括末尾的空字符)。如果nIndex并非合法的索引,则返回CB_ERR。
   nIndex----指定将获取文本选项的索引。
   LpszText---指定将用以存放所得文本的缓冲区指针。该缓冲区必须足够容纳要获取的文本及其结尾空字符。
  rString:用于存放所的文本的Cstring对象
  int GetLBTextLen( int nIndex) const
  如果函数调用成功,则返回字符串的字节长度(不包括末尾的空字符)。如果nIndex并非合法的索引,则返回CB_ERR。
  nIndex----指定将获取组合框选项的索引。
  -----------------------------------------------------------
  ComboBox(下拉框)的用法:
  CComboBox m_cob;
  CString m_Getstring;
  m_cob.GetLBText(m_cob.GetCurSel(),m_Getstring);//把选择的内容传给m_Getstring
  
  void CBaDialog::OnTimer(UINT nIDEvent) 
  { //设置列表框的选择 当再一次选择时 重新设置按钮的属性
   // TODO: Add your message handler code here and/or call default
   CString m_string;
   m_cob.GetLBText(m_cob.GetCurSel(),m_string);
   if(m_Getstring!=m_string)
   {
   GetDlgItem(IDC_STATR)->EnableWindow(TRUE);
   this->Enable(FALSE);
   }
   CDialog::OnTimer(nIDEvent);
  }
  //
  3.BUTTON
  操作函数:
  HICON SetIcon(HICON hIcon); 如果函数操作成功,返回先前与按钮联系的图标句柄。
  以链表的方式实现了主界面所有Button的初始化
  // 设置按钮风格
  // 将其单独定义而不是在ClassWizard中定义,参看InitBuffonStyle();
  private:
   CButtonStyle m_Setting, m_ListItem, m_Addition, m_Remove, 
   m_Modify, m_Search, m_About, m_Exit,
   m_Previous, m_Next, m_End, m_Home,
   m_Goto, m_Jump;
  void CMagicWordDlg::InitButtonStyle()
  {
   CList< CButtonStyle*, CButtonStyle* > ButtonList;
   //ButtonList.AddTail( &m_Setting );
   ButtonList.AddTail( &m_ListItem );
   ButtonList.AddTail( &m_Addition );
   ButtonList.AddTail( &m_Remove );
   ButtonList.AddTail( &m_Modify );
   ButtonList.AddTail( &m_Search );
   ButtonList.AddTail( &m_About );
   ButtonList.AddTail( &m_Exit );
   ButtonList.AddTail( &m_Previous );
   ButtonList.AddTail( &m_Next );
   ButtonList.AddTail( &m_End );
   ButtonList.AddTail( &m_Home );
   ButtonList.AddTail( &m_Goto );
   ButtonList.AddTail( &m_Jump );
  
  
   // 用循环实现必须手动改动Resource.h中的定义
   for ( int nIco = IDI_JUMP, nBtn = IDC_JUMP; nBtn >= IDC_LISTITEM; nIco--, nBtn-- )
   {
   CButtonStyle *Button = ButtonList.RemoveTail();
   Button->SubclassDlgItem( nBtn, this );
   Button->SetIcon( nIco );
   Button->SetInactiveBgColor();
   Button->SetInactiveFgColor();
   Button->SetActiveBgColor();
   }
  }
  使按钮不可用
  BOOL m_bS;
  m_bS = GetDlgItem(IDC_STATR)->EnableWindow(FALSE);
  void CBaDialog::Enable( BOOL p)
   {
   BOOL HB;
   HB=p;
   GetDlgItem(IDC_ADD)->EnableWindow(HB);
   GetDlgItem(IDC_DELECT)->EnableWindow(HB);
   GetDlgItem(IDC_EDIT)->EnableWindow(HB);
   GetDlgItem(IDC_FIND)->EnableWindow(HB);
   GetDlgItem(IDC_ALL)->EnableWindow(HB);
   }
  
  //
  编辑控件
  属性操作函数:完成属性的设置和查询等操作〉
  
  常规操作函数:完成清空编辑控件的恢复缓冲区、得到编辑控件中的被选文本等操作。
   SetSel:调用该函数以设置编辑控件中的当前被选文本,其原型:
   void SetSel(DWORD dwSelection,BOOL bNoScroll=FALSE);
   void SetSel(int nStartChar,int nEndChar,BOOL bNoScroll=FALSE);
  dwSelection
  bNoScroll
  nStartChar
  nEndCha
  bNoScroll
  剪贴板操作:
  
  //
  
   状态栏—CstatusBar
   构造函数:完成创建状态栏对象、设置状态栏窗格ID等操作。
  SetIndicators:调用该函数可以设置各个指示窗口的ID,其原型为:
   BOOL SetIndicators(const UINT* lpIDArray,int nIDCount);
   调用成功,返回非零值,否则,零值。
  lpIDArray :为包含状态栏指示窗格ID的数组。
  nIDCount:指定了状态栏指示窗格数目。
   属性操作函数:完成创建状态栏对象、设置状态栏分栏ID等操作。
  CommandToIndex:调用该函数可以获得给定ID值的状态栏指示窗格索引,其原型:
  Int CommandToIndex(UINT nIDFind) const;
  调用成功,返回指示窗格索引,否则,返回-1.
  nIDFind——指定了将获取其索引的窗格ID。
  SetPaneText:调用该函数可以设置给定指示窗格的文本,其原型:
  BOOL SetPaneText(int nIndex,LPCTSTR lpszNewText,BOOL bUpdate=TRUE);
  调用成功,返回非零值,否则,零值。
  nIndex:指定了将设置其文本的状态栏指示窗格索引。
  lpszNewText:指定了将设置的指示窗格文本。
  bUpdate:如果改参数为TRUE,则指示窗格的显示将被更新。
  //
  /
  检查框(Check boxes)和单选按钮(Radio button)
  Radio button:
   
  m_radio.SetCheck(1);//选中状态
  int m_nSel;
  void CSearchDlg::OnOK() 
  {
   try
   {
   UpdateData();
   switch(m_nSel)
   {
   case 0:
   theApp.m_strSQL="SELECT * FROM Records WHERE date1>='"+m_strDate1+"' AND date2<='"+m_strDate2+"'";
   break;
  
   case 1:
   theApp.m_strSQL="SELECT * FROM Records WHERE Name LIKE '%"+m_strName+"%'";
   break;
   
   case 2:
   theApp.m_strSQL="SELECT * FROM Records WHERE College LIKE '%"+m_strCollege+"%'";
   break;
   
   case 3:
   theApp.m_strSQL="SELECT * FROM Records WHERE Reason LIKE '%"+m_strReason+"%'";
   break; 
   }
   ((CCcDlg*)AfxGetMainWnd())->List(theApp.m_strSQL); 
   }
   catch(_com_error e)
   {
   CATCH_ERROR;
   }
   
   CDialog::OnOK(); 
  }
   
  //
  ///
  
  对话框
   隐藏和显示对话框:ShowWindow (SW_HIDE); ShowWindow (SW_SHOW);
   ShowWindow (SW_HIDE);
   CAcsLogDlg loginDlg;
   if (loginDlg.DoModal ()==IDOK)
   {
   success = TRUE;
   }
   else
   {
   success = FALSE;
   ShowWindow (SW_SHOW);
   }
  对话框中的控件:可见(visible)风格通过调用CWnd::ShowWindow()改变可见性。
  m_button.ShowWindow(SW_SHOW);//显示按钮
  m_button.ShowWindow(SW_HIDE);//隐藏按钮
   禁止(disabled)调用CWnd::EnabledWindow()
   UpdateData();参数为TRUE时,对话框控件中的内容传递给数据成员,为FALSE时反之。
  SetDlgItemText(IDC_Use,"");//对话框中的编辑框清空
  GetDlgItem(IDC_Use)->SetFocus();//光标停在对话框中的IDC_Use
  SetDialogBkColor( RGB( 96, 160, 16 ), RGB( 255, 255, 255 ) ); // 设置对话框背景色及文本色
  调用对话框
  打开文件对话框
  void CMediaPlayerDlg::OnOpen() 
  {
   // TODO: Add your control notification handler code here
   char szFileFilter[]=
   "Mp3 File(*.mp3)|*.mp3|"
   "Wma File(*.wma)|*.wma|"
   "Video File(*.dat)|*.dat|"
   "Wave File(*.wav)|*.wav|"
   "AVI File(*.avi)|*.avi|"
   "Movie File(*.mov)|*.mov|"
   "Media File(*.mmm)|*.mmm|"
   "Mid File(*.mid;*,rmi)|*.mid;*.rmi|"
   "MPEG File(*.mpeg)|*.mpeg|"
   "All File(*.*)|*.*||";
  
   CFileDialog dlg(TRUE,NULL,NULL,OFN_HIDEREADONLY,szFileFilter);
  //CFileDialog fileDlg(TRUE, "mdb", "*.mdb", NULL, "Access Files(*.mdb)", NULL);
   if(dlg.DoModal()==IDOK){
   CString PathName=dlg.GetPathName();
   PathName.MakeUpper();
   m_ActiveMovie.SetFileName(PathName);
   }
  
  }
  
  //
  
  字体
  CFont m_font2;
  CFont m_font1;
   m_font1.CreateFont(12, 0,0,0,FW_BOLD, 0,0,0,
   DEFAULT_CHARSET, OUT_CHARACTER_PRECIS, CLIP_CHARACTER_PRECIS,
   DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE, "宋体");//加粗
  /* m_font2.CreateFont(14, 0,0,0,FW_NORMAL, 0,0,0,
   DEFAULT_CHARSET, OUT_CHARACTER_PRECIS, CLIP_CHARACTER_PRECIS,
   DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE, "宋体");
  */
  /


  4.数据库
  
  ODBC动态添加数据库:Lhwy工程
   
  CDatabase类
  public:
   CDatabase m_DB;
  extern CLhwyApp theApp;
  
  #include <odbcinst.h>
  //由于 VC的缺省库文件中不包含 SQLConfigDataSource()函数,因此使用该函数之前需要将 odbcinst.h文件包含在工程的头文件中
  
  BOOL CLhwyApp::InitInstance()
  {
   //在VC中动态加载ODBC的方法
   if (!AfxSocketInit())
   {
   AfxMessageBox(IDP_SOCKETS_INIT_FAILED);
   return FALSE;
   }
  
   CString sPath;//数据库存放路径
   GetModuleFileName(NULL,sPath.GetBufferSetLength(MAX_PATH+1),MAX_PATH);
   sPath.ReleaseBuffer ();
   int nPos;
   nPos=sPath.ReverseFind ('//');
   sPath=sPath.Left (nPos);
   nPos=sPath.ReverseFind('//');
   sPath=sPath.Left (nPos);
   CString lpszFile = sPath + "//lhwy.mdb";
   
   
   char* szDesc;
   int mlen;
   szDesc=new char[256];
   sprintf(szDesc,"DSN=%s? DESCRIPTION=TOC support source? DBQ=%s? FIL=MicrosoftAccess? DEFAULTDIR=%s?? ","lhwy",lpszFile,sPath);
  
  
  
   mlen = strlen(szDesc);
   for (int i=0; i<mlen; i++)
   {
   if (szDesc[i] == '?')
   szDesc[i] = '/0';
   }
  //Windows系统子目录中的动态链接库 Odbcinst.dll提供了一个可以动态地增加、修改和删除数据源的函数 SQLConfigDataSource()。
  //
   if (FALSE == SQLConfigDataSource(NULL,ODBC_ADD_DSN,"Microsoft Access Driver (*.mdb)/0",(LPCSTR)szDesc))
   AfxMessageBox("SQLConfigDataSource Failed");
   
  
   try
   {
   CString strConnect;
   strConnect.Format("DSN=lhwy;");//指定odbc连接的字符串:数据源的名称和其他//一些选项信息
   if(!m_DB.OpenEx(strConnect,CDatabase::useCursorLib))//装载ODBC光标库DLL,如果想直接从Crecordset类得到对象而不是派生得到,就不应该装载光标库/
  //要使程序与数据源建立联系,需用CDateBase::OpenEx()或CDatabase::Open()函数来进行初始化。数据库对象必须在使用它构造记录集对象之前初始化。
   {
   AfxMessageBox("Unable to Connect to the Specified Data Source");
   return FALSE ;
   }
   }
   catch(CDBException *pE)
   {
   pE->ReportError();
   pE->Delete();
   return FALSE;
   }
  
   AfxEnableControlContainer();
   //SetDialogBkColor(RGB(140,130,210),RGB(255,0,0));
   SetDialogBkColor (RGB (140, 180, 220), RGB ( 255 ,0 , 0 ) );//背景色
  连接数据表
  CDRecordset m_Set(&theApp.m_DB);// &theApp.m_DB为CDatabase类型
  CBRecordset m_bSet(&theApp.m_DB);
  CTRecordset m_tSet(&theApp.m_DB);
  CRecordset类
  数据成员
  m_nFields:记录集中的字段数目,类型为UINT.
  m_strFilter:CString对象,包含一个SOL的WHERE字句,作为过滤器对那些满足一定条件的记录进行选择。
  m_strSort: CString对象,包含一个SOL的ORDER BY字句,用于控制记录排序的方式。
  GetODBCFieldInfo------返回记录集中字段的特定种类的信息。
  记录导向操作
  MoveFirst------设置记录集的当前记录为第一个记录,此前应调用IsBOF测 试。
  记录更新操作
  Edit-------准备对当前记录的更改,编辑,调用Update()完成编辑。
  AddNew----准备增加一个新记录,调用Update()完成。
  Delete------从记录中删除当前记录,在删除之后必须滚动到下一个记录。
  操作应用:
  打开数据表m_Set.Open(AFX_DB_USE_DEFAULT_TYPE,"[NO2STUDENT]");// [NO2STUDENT为数据表名

用ADO连接数据库
  ADO库包含三个基本接口:_ConnectionPtr接口、_CommandPtr接口和_RecordsetPtr接口。
  库包含三个基本接口:_ConnectionPtr接口、_CommandPtr接口和_RecordsetPtr接口。
  _ConnectionPtr接口返回一个记录集或一个空指针。通常使用它来创建一个数据连接或执行一条不返回任何结果的SQL语句,如一个存储过程。使用_ConnectionPtr接口返回一个记录集不是一个好的使用方法。通常同CDatabase一样,使用它创建一个数据连接,然后使用其它对象执行数据输入输出操作。
  _CommandPtr接口返回一个记录集。它提供了一种简单的方法来执行返回记录集的存储过程和SQL语句。在使用_CommandPtr接口时,你可以利用全局_ConnectionPtr接口,也可以在_CommandPtr接口里直接使用连接串。如果你只执行一次或几次数据访问操作,后者是比较好的选择。但如果你要频繁访问数据库,并要返回很多记录集,那么,你应该使用全局_ConnectionPtr接口创建一个数据连接,然后使用_CommandPtr接口执行存储过程和SQL语句。
  _RecordsetPtr是一个记录集对象。与以上两种对象相比,它对记录集提供了更多的控制功能,如记录锁定,游标控制等。同_CommandPtr接口一样,它不一定要使用一个已经创建的数据连接,可以用一个连接串代替连接指针赋给_RecordsetPtr的connection成员变量,让它自己创建数据连接。如果你要使用多个记录集,最好的方法是同Command对象一样使用已经创建了数据连接的全局_ConnectionPtr接口,然后使用_RecordsetPtr执行存储过程和SQL语句。
  程序中通过_variant_t和_bstr_t转换COM对象和C++类型的数据, _variant_t类封装了OLE自治VARIANT数据类型。在C++中使用_variant_t类要比直接使用VARIANT数据类型容易得多。
  在stdafx.h 文件中添加:
  #include 〈comdef.h〉//头文件comdef.h使我们的应用程序能够使用Visual C++中的一些特殊COM支持类,这些类使得处//理OLE自治更为容易一些,OLE自治是ADO使用的数据类型。
  #import "msado15.dll" no_namespace rename("EOF","adoEOF")
  //#import "c:/program files/common files/system/ado/msado15.dll" no_namespace rename("EOF","adoEOF")
  
  #if !defined CATCH_ERROR
  #define CATCH_ERROR /
   { /
   CString strComError; /
   strComError.Format("错误编号: %08lx/n错误信息: %s/n错误源: %s/n错误描述: %s", /
   e.Error(), /
   e.ErrorMessage(), /
   (LPCSTR) e.Source(), /
   (LPCSTR) e.Description()); /
   ::MessageBox(NULL,strComError,"错误",MB_ICONEXCLAMATION); /
   }
  #endif
  
  连接数据库:
   打开一个库连接。先创建一个实例指针,再用Open打开一个库连接,它将返回一个IUnknown的自动化接口指针。
   _ConnectionPtr m_pConnection;//public
  
   BOOL CCcApp::InitInstance()
   {
   AfxOleInit();//初始化COM库
  AfxEnableControlContainer();//系统生成
  // 在ADO操作中建议语句中要常用try...catch()来捕获错误信息,
  // 因为它有时会经常出现一些意想不到的错误。
   try
   {
   
   m_pConnection.CreateInstance("ADODB.Connection");///创建Connection对象
  //m_pConnection.CreateInstance(__uuidof(Connection));
   m_pConnection->ConnectionTimeout=3;///设置超时时间为3秒
   
   m_pConnection->Open("Provider=Microsoft.Jet.OLEDB.4.0;Data 
   Source=data.mdb;","","",adModeUnknown);//Data是数据类型
   }
   catch(_com_error e)///捕捉异常
   {
   CATCH_ERROR;
   return false;
   }
  、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、
  、、、、、、、、、、、、、、、、、、、、、、、
  关闭一个库连接 如果连接状态有效,则用Close方法关闭它并赋于它空值。代码如下所示:
  
   if(m_pConnection->State)
   m_pConnection->Close();
   m_pConnection= NULL;
  _RecordsetPtr智能指针,可以用来打开库内数据表,并可以对表内的记录、字段等进行各种操作。
  _RecordsetPtr m_pRecordset;
  m_pRecordset.CreateInstance("ADODB.Recordset"); //查询数据库,看是否有此用户和密码 m_pRecordset->Open((_variant_t)sql,_variant_t((IDispatch*)theApp.m_pConnection,true),adOpenStatic,adLockOptimistic,adCmdText);
  /* m_pRecordset->Open("SELECT * FROM DemoTable", // 
   查询DemoTable表中所有字段
   theApp.m_pConnection.GetInterfacePtr(), // 
   获取库接库的IDispatch指针
   adOpenDynamic,
   adLockOptimistic,
   adCmdText);
   } */
  具体操作:
   附加
   #define CATCH_ERROR /
   catch (_com_error e) /
   { /
   CString strComError; /
   strComError.Format("错误编号: %08lx/r/n/r/n错误信息: %s/r/n/r/n错误源: %s/r/n/r/n错误描述: %s", /
   e.Error(), /
   e.ErrorMessage(), /
   (LPCSTR) e.Source(), /
   (LPCSTR) e.Description()); /
   SetDlgItemText(IDC_MESSAGE,strComError); /
   }
  #define SET_TEXT SetDlgItemText(IDC_MESSAGE,"!/r/n/r/n/r/n/r/n/t/t操作成功完成!");
  读取表内数据 
   将表内数据全部读出并显示在列表框内,m_AccessList为列表框的成员变量名。如果没有遇到表结束标志adoEOF,则用GetCollect(字段名)或m_pRecordset->Fields->GetItem(字段名)->Value方法,来获取当前记录指针所指的字段值,然后再用MoveNext()方法移动到下一条记录位置。
  插入记录 
   可以先用AddNew()方法新增一个空记录,再用PutCollect(字段名,值)输入每个字段的值,最后再Update()更新到库中数据既可。其中变量m_Name和m_Age分别为姓名及年龄编辑框的成员变量名。
  _variant_t RecordsAffected;
  theApp.m_strSQL="INSERT INTO Records (Name,YorN,College,date1,date2,Reason,Remark,Flag) values('"+m_strName+"','"+YorN+"','"+m_strCollege+"','"+m_date1+"','"+m_date2+"','"+m_strReason+"','"+m_strRemark+"','"+strNowTime+"')";
   theApp.m_pConnection->Execute((_bstr_t)theApp.m_strSQL,&RecordsAffected,adCmdText);
  移动记录指针 
   移动记录指针可以通过MoveFirst()方法移动到第一条记录、MoveLast()方法移动到最后一条记录、MovePrevious()方法移动到当前记录的前一条记录、MoveNext()方法移动到当前记录的下一条记录。但我们有时经常需要随意移动记录指针到任意记录位置时,可以使用Move(记录号)方法来实现,注意: 
   Move()方法是相对于当前记录来移动指针位置的,正值向后移动、负值向前移动,如:Move(3),当前记录是3时,它将从记录3开始往后再移动3条记录位置。
  改记录中字段值 
   可以将记录指针移动到要修改记录的位置处,直接用PutCollect(字段名,值)将新值写入并Update()更新数据库既可。
  theApp.m_strSQL="update Records set Name='"+m_strName+
   "',YorN='"+YorN+
   "',College='"+m_strCollege+
   "',Reason='"+m_strReason+
   "',date1='"+m_date1+
   "',date2='"+m_date2+
   "',Remark='"+m_strRemark+
   "' where Flag='"+m_strFlag+"'";
   
   _variant_t RecordsAffected;
   theApp.m_pConnection->Execute((_bstr_t)theApp.m_strSQL,&RecordsAffected,adCmdText);
  删除记录 
   删除记录和上面修改记录的操作类似,先将记录指针移动到要修改记录的位置,直接用Delete()方法删除它并用Update()来更新数据库既可。
  登陆窗口连接数据库
   BOOL LogonDlg::OnInitDialog() //初始化登陆窗口
  {
   CDialog::OnInitDialog();
   
   // TODO: Add extra initialization here
   try
   {
   m_pRecordset.CreateInstance("ADODB.Recordset");//创建对象
   m_pRecordset->Open((_variant_t)"SELECT * FROM Admin",_variant_t((IDispatch*)theApp.m_pConnection,true),adOpenStatic,adLockOptimistic,adCmdText);
   
   if(!m_pRecordset->adoEOF)
   {
   theApp.g_Admin=((LPCTSTR)(_bstr_t)m_pRecordset->GetCollect("AdminName"));
   SetDlgItemText(IDC_Use,theApp.g_Admin);
   } 
   m_pRecordset->Close();
   }
  
   catch (_com_error e) 
   { 
   CATCH_ERROR; 
   return false;
   }
   return TRUE; // return TRUE unless you set the focus to a control
   // EXCEPTION: OCX Property Pages should return FALSE
  }
  void LogonDlg::OnOK() //当点击确定按钮时,所作的操作,成功弹出主界面
  {
   // TODO: Add extra validation here
  UpdateData(); 
   if(m_Use.IsEmpty() || m_Pass.IsEmpty()) 
   {
   AfxMessageBox("请输入用户名和密码!");
   }
   else
   {
   CString sql="SELECT * FROM Admin where AdminName='"+theApp.g_Admin+"' and pwd='"+m_Pass+"'";
   try
   { //创建Recordset对象的实例 
   m_pRecordset.CreateInstance("ADODB.Recordset"); //查询数据库,看是否有此用户和密码
   m_pRecordset->Open((_variant_t)sql,_variant_t((IDispatch*)theApp.m_pConnection,true),adOpenStatic,adLockOptimistic,adCmdText);
   
   if(m_pRecordset->adoEOF) //如果没有此用户和密码
   {
   MessageBox("请输入正确的用户名和密码!","错误",MB_ICONASTERISK );
   SetDlgItemText(IDC_Use,"");
   GetDlgItem(IDC_Use)->SetFocus();
   }
   else
   {
   theApp.g_Admin=m_Use;
   theApp.g_Pass=m_Pass;
   CDialog::OnOK();
   }
   }
   catch (_com_error e) 
   { 
   CATCH_ERROR;
   return;
   }
   } 
   
  // CDialog::OnOK();
  }
  void LogonDlg::OnCancel() //
  {
   // TODO: Add extra cleanup here
  //((CCcDlg*)AfxGetMainWnd()):取得主界面的指针
   ((CCcDlg*)AfxGetMainWnd())->EndDialog(IDOK);//当点击取消按钮时不弹出主界面
   CDialog::OnCancel();
  }
  显示所查内容
  extern CCcApp theApp;
  void CCcDlg::List(CString sql) //将SQL语句查询的结果显示在列表框中
  {
   m_list.DeleteAllItems(); 
   
   int nItem=0;
   try
   {
   m_pRecordset.CreateInstance("ADODB.Recordset");
   m_pRecordset->Open((_variant_t)sql,_variant_t((IDispatch*)theApp.m_pConnection,true),adOpenStatic,adLockOptimistic,adCmdText);
   if(!m_pRecordset->adoEOF) //如果记录不为空
   { 
   while(!m_pRecordset->adoEOF)
   { 
   if(strcmp((LPCTSTR)(_bstr_t)m_pRecordset->GetCollect("YorN"),"Y")==0) //是否批准
   nItem=m_list.InsertItem(0xffff,"Y",0);//0代表正确的图标 0xffff可用数字代替
   else
   nItem=m_list.InsertItem(0xffff,"N",1);//1代表错误的图标 
   m_list.SetItemText(nItem,1,(LPCTSTR)(_bstr_t)m_pRecordset->GetCollect("Name"));
   m_list.SetItemText(nItem,2,(LPCTSTR)(_bstr_t)m_pRecordset->GetCollect("College"));
   m_list.SetItemText(nItem,3,(LPCTSTR)(_bstr_t)m_pRecordset->GetCollect("Reason"));
   m_list.SetItemText(nItem,4,(LPCTSTR)(_bstr_t)m_pRecordset->GetCollect("date1"));
   m_list.SetItemText(nItem,5,(LPCTSTR)(_bstr_t)m_pRecordset->GetCollect("date2"));
   m_list.SetItemText(nItem,6,(LPCTSTR)(_bstr_t)m_pRecordset->GetCollect("Remark"));
   m_pRecordset->MoveNext();
   }
   }
   m_pRecordset->Close();
   }
   catch (_com_error e)
   { 
   CATCH_ERROR;
   return;
   }
   
   
   CString strTitle; 
   strTitle.Format("学生请假管理系统 共有%d条记录",nItem+1);
   SetWindowText(strTitle);
  }
  
  删除一条记录
  
  void CCcDlg::OnButtonDel() //删除一条记录
  {
   try
   {
   POSITION pos = m_list.GetFirstSelectedItemPosition();
   if(pos) //如果选中一行,则生成动态的sql语句
   {
   if(MessageBox("你确定要删除此记录吗?","警告",MB_ICONQUESTION|MB_YESNO|MB_DEFBUTTON2)==IDYES)
   {
   int nItem = m_list.GetNextSelectedItem(pos);
   theApp.m_strSQL="DELETE FROM Records WHERE name='"
   +m_list.GetItemText(nItem,1)+"' and College='"
   +m_list.GetItemText(nItem,2)+"' and Reason='"
   +m_list.GetItemText(nItem,3)+"' and date1='"
   +m_list.GetItemText(nItem,4)+"' and date2='"
   +m_list.GetItemText(nItem,5)+"' and Remark='"
   +m_list.GetItemText(nItem,6)+"'";
   _variant_t RecordsAffected;
   
   theApp.m_pConnection->Execute((_bstr_t)theApp.m_strSQL,&RecordsAffected,adCmdText); //执行此sql语句
   List("SELECT * FROM Records");
   }
   }
   else
   AfxMessageBox("请选择一行数据!");
   }
   catch(_com_error e)
   {
   CATCH_ERROR;
   }
  }
  1. 建表
   void CADlg::OnCreatetTable() 
  {
   try
   { 
   m_pConnection->Execute("CREATE TABLE new(ID INTEGER,username TEXT,old INTEGER)",NULL,adCmdText);
   SET_TEXT;
   }
   CATCH_ERROR;
  }
  2. 删除数据表
   void CADlg::OnDropTable() 
  { 
   try
   {
   m_pConnection->Execute("DROP TABLE new",NULL,adCmdText);
   SET_TEXT;
   }
   CATCH_ERROR;
  }
  void CADlg::OnAddItem() 
  {
   try
   { 
   m_pConnection->Execute("ALTER TABLE new ADD newcolumn1 INTEGER",NULL,adCmdText); 
   SET_TEXT;
   }
   CATCH_ERROR;
  }
  
  void CADlg::OnDelItem() 
  {
   try
   {
   m_pConnection->Execute("ALTER TABLE new ADD newcolumn1 INTEGER", NULL,adCmdText); 
   SET_TEXT;
   }
   CATCH_ERROR;
   
  }
  
  void CADlg::OnAddRecords() 
  {
   try
   {
   for(int i = 1;i < 10; i ++)
   {
   CString strSQL;
   strSQL.Format("INSERT INTO new(ID,username,old) VALUES (%d, '程红秀',%d)",i,i*3);
   m_pConnection->Execute((_bstr_t)strSQL,NULL,adCmdText); 
   
   SET_TEXT; 
   }
   }
   CATCH_ERROR;
  }
  
  void CADlg::OnOldAdd1() 
  { 
   try
   {
   m_pConnection->Execute("UPDATE new SET old = old+1", NULL,adCmdText); 
   SET_TEXT;
   }
   CATCH_ERROR;
  }
  
  void CADlg::OnSum() 
  {
   try
   {
   _RecordsetPtr m_pRecordset;
   _variant_t RecordsAffected;
   
   m_pRecordset =m_pConnection->Execute("SELECT COUNT(*) FROM new where ID > 0",&RecordsAffected,adCmdText);
   
   _variant_t vCount = m_pRecordset->GetCollect((_variant_t)(long)0); //取得第一个字段的值放入vCount变量
   
   
   CString str;
   str.Format("!/r/n/r/n/r/n/t/t/t共有%d条记录",vCount.lVal);
   SetDlgItemText(IDC_MESSAGE,str);
   
   m_pRecordset->Close(); 
   }
   CATCH_ERROR;
   
  }
  
  void CADlg::OnSetIdIndex() 
  {
   try
   {
   m_pConnection->Execute("CREATE UNIQUE INDEX id ON new(ID)",NULL,adCmdText); 
   SET_TEXT;
   }
   CATCH_ERROR;
   
  }
  
  void CADlg::OnOldSum() 
  {
   try
   {
   _RecordsetPtr m_pRecordset;
   _variant_t RecordsAffected;
   m_pRecordset =m_pConnection->Execute("select MAX(old) from new",&RecordsAffected,adCmdText);
   
   _variant_t vCount = m_pRecordset->GetCollect((_variant_t)(long)0);
   
  
   m_pRecordset->Close();
   m_pRecordset.Release();
  
   CString Message;
   Message.Format("!/r/n/r/n/r/n/t/t/t最大值是%d",vCount.lVal);
   SetDlgItemText(IDC_MESSAGE,Message);
   }
   CATCH_ERROR; 
  }
  
  void CADlg::OnOldSum2() 
  {
   try
   {
   _RecordsetPtr m_pRecordset;
   _variant_t RecordsAffected;
   
   m_pRecordset =m_pConnection->Execute("select SUM(old) from new",&RecordsAffected,adCmdText);
   _variant_t vIndex = (long)0;
   _variant_t vCount = m_pRecordset->GetCollect(vIndex);
   
  
   m_pRecordset->Close();
   m_pRecordset.Release();
   CString Message;
   Message.Format("!/r/n/r/n/r/n/t/t/t总和是%d",(long)vCount);
   SetDlgItemText(IDC_MESSAGE,Message);
   }
   CATCH_ERROR;
  }
  
  
  void CADlg::OnOldAverage() 
  {
   
   try
   {
   _RecordsetPtr m_pRecordset;
   _variant_t RecordsAffected;
   m_pRecordset =m_pConnection->Execute("select AVG(old) from new",&RecordsAffected,adCmdText);
   _variant_t vIndex = (long)0;
   _variant_t vCount = m_pRecordset->GetCollect(vIndex);
   
  
   m_pRecordset->Close();
   m_pRecordset.Release();
   CString Message;
   Message.Format("!/r/n/r/n/r/n/t/t/t平均值是%d",(long)vCount);
   SetDlgItemText(IDC_MESSAGE,Message);
   
   }
   CATCH_ERROR;
  }
   
  //
  DAO访问ACCESS数据库
  CDaoRecordSet类
  类成员:
  数据成员:m_nFields(),m_strFilter(),m_strSort()
   m_pSet->m_strFilter=filter;
   m_pSet->Requery();
  . 属性成员函数:CanUpdate()
  。记录操作函数: AddNew()
  动态连接数据库:
  #include <afxdao.h>
  private:
   CString m_DataSource;
   //动态连接数据库
   char path[ MAX_PATH ] = { '/0' };
   GetCurrentDirectory( MAX_PATH, path );
   m_DataSource.Format( "%s", path );
   m_DataSource += "//MagicWord.mdb";//数据库名
  CString CWordDaoSet::GetDefaultDBName()
  {
   return _T( m_DataSource );//数据源的路径 m_DataSource不加引号
  }
  //实例化
   m_pSet = new CWordDaoSet();
  在视图文档中,采用:在PppView.cpp文件的OnInitialUpdate()函数中得到指向数据集的指针 
  CFormView::OnInitialUpdate();
   CPppDoc* pDoc = (CPppDoc*)GetDocument(); //得到指向文档类指针
   m_ShengSet=&pDoc->m_ShengSet;//得到数据库指针
  /
  //PUBLIC函数 打开数据表进行操作
  void CMagicWordDlg::DisplayFirstRecord()
  {
   try
   {
   if ( m_pSet->IsOpen() )
   m_pSet->Close();
  
   m_pSet->Open();
   PublicAssign();//操作函数
   }
   catch( CDaoException *exception )
   {
   exception->ReportError();
   return;
   }
  }
  、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、
   添加功能:执行添加、删除、查找等操作。
   首先。写SQL查询语句
  其次。创建一个新的纪录集对象
   功能操作
   关闭数据表
  
  添加新单词
   // 实例化m_pSet
   m_pSet = new CWordDaoSet();
  
  void CMagicWordDlg::OnAddition() //添加函数
  {
   CWordInfoDlg WordInfoDlg; //添加对话框
   CWordDaoSet TempSet;//数据库表
   CString strSQL;//SQL查询
  
   // 如果点击了取消按钮,则不执行添加操作。
   if ( WordInfoDlg.DoModal() != IDOK )// 调用添加对话框
   return;
  
   // 查询当前单词是否已经被收录于数据库中
   if ( TempSet.IsOpen() )//关闭原有的记录集
   TempSet.Close();
   //查询功能,看添加的内容是否已经存在
   strSQL.Format( "SELECT * FROM WordList WHERE word = '%s'", 
   WordInfoDlg.m_word.operator LPCTSTR() );
  //创建一个新的纪录集对象
   TempSet.Open( AFX_DAO_USE_DEFAULT_TYPE, strSQL, 0 );
  
  
   if ( !TempSet.IsEOF() )
   {
   MessageBox( _T( "当前单词纪录已存在,没有添加的必要!" ),
   _T( "已经存在!" ), MB_OK | MB_ICONASTERISK );
   return;
   }
  
   if ( TempSet.IsOpen() )
   TempSet.Close();
  
   // 执行添加操作
   try
   {
   m_pSet->AddNew();
   //添加内容
   m_pSet->m_Word = WordInfoDlg.m_word;
   m_pSet->m_Explain0 = WordInfoDlg.m_explain0;
   m_pSet->m_Explain1 = WordInfoDlg.m_explain1;
   m_pSet->m_Explain2 = WordInfoDlg.m_explain2;
   m_pSet->m_Phrase0 = WordInfoDlg.m_phrase0;
   m_pSet->m_Phrase1 = WordInfoDlg.m_phrase1;
   m_pSet->m_Phrase2 = WordInfoDlg.m_phrase2;
   m_pSet->m_Sentence0 = WordInfoDlg.m_sentence0;
   m_pSet->m_Sentence1 = WordInfoDlg.m_sentence1;
   //更新数据库
   if ( m_pSet->CanUpdate() )
   {
   m_pSet->Update();
   MessageBox( _T( "添加新单词完成!" ), 
   _T( "添加成功!" ), MB_OK | MB_ICONASTERISK );
   }
   }
   catch( CDaoException *exception )//异常操作
   {
   exception->ReportError();
   // 否则指针会指向出现异常的纪录
   m_pSet->MoveNext();
   m_pSet->MovePrev();
   return;
   }
  }
  直接通过DAO读写Access文件
  CDaoDatabase db; //数据库
  CDaoRecordset RecSet(&db); //记录集
  void CRWAccessDlg::OnWriteAccess() //创建数据库,并向数据表中添加数据
  {
   //获取主程序所在路径,存在sPath中
   CString sPath;
   GetModuleFileName(NULL,sPath.GetBufferSetLength (MAX_PATH+1),MAX_PATH);
   sPath.ReleaseBuffer ();
   int nPos;
   nPos=sPath.ReverseFind ('//');
   sPath=sPath.Left (nPos);
  
   //默认创建数据名:Demo.mdb,内部表名:DemoTable,表内有二个字段:姓名、年龄
   CString lpszFile = sPath + "//Demo.mdb";
   
   CFileFind fFind;//查找文件
   BOOL bSuccess;
   bSuccess=fFind.FindFile(lpszFile);
  
   fFind.Close ();
   //是否已有创建好的Demo.mdb文件,没有则创建它
   if(!bSuccess)
   {
   db.Create(lpszFile);//创建数据库
  
   CString SqlCmd = "CREATE TABLE DemoTable(Name VARCHAR(20),Age VARCHAR(3));";
   db.Execute(SqlCmd);//创建数据表
   
   //打开已创建的数据表
   RecSet.Open(AFX_DAO_USE_DEFAULT_TYPE,
   "SELECT * FROM DemoTable", 0);
   //加入第一个记录,用SQL语句
   db.Execute("INSERT INTO DemoTable (Name,Age) VALUES ('徐景周',26)");
   
   //加入第二个记录,用DAO涵数
   RecSet.AddNew();
   RecSet.SetFieldValue("Name","徐志慧");
   RecSet.SetFieldValue("Age","21");
   RecSet.Update();
   
   //加入第三个记录,用DAO涵数
   RecSet.AddNew();
   RecSet.SetFieldValue("Name","郭徽");
   RecSet.SetFieldValue("Age","27");
   RecSet.Update();
   
   //关闭记录集及库
   RecSet.Close();
   db.Close();
  
   AfxMessageBox("Access文件写入成功!");
   }
   else
   AfxMessageBox("Demo.mdb数据库已经创建!");
   
  }
  void CRWAccessDlg::OnReadAccess() //直接读取数据库
  {
   COleVariant var; // 字段类型
   var.ChangeType(VT_BSTR, NULL);
   CString strName,strAge,strFile; 
  
   //清空列表框
   m_AccessList.ResetContent();
  
   //获取主程序所在路径,存在sPath中
   CString sPath;
   GetModuleFileName(NULL,sPath.GetBufferSetLength (MAX_PATH+1),MAX_PATH);
   sPath.ReleaseBuffer ();
   int nPos;
   nPos=sPath.ReverseFind ('//');
   sPath=sPath.Left (nPos);
  
   strFile = sPath + "//demo.mdb";
   db.Open(strFile); // 打开已创建的demo数据库及DamoTable表
   RecSet.Open(AFX_DAO_USE_DEFAULT_TYPE,"SELECT * FROM DemoTable",NULL);
  
   while(!RecSet.IsEOF()) // 有没有到表结尾
   {
   RecSet.GetFieldValue("Name",var);

    strName = (LPCSTR)var.pbstrVal;
   RecSet.GetFieldValue("Age",var);
   strAge = (LPCSTR)var.pbstrVal;
   m_AccessList.AddString( strName + " --> "+strAge );
  
   RecSet.MoveNext();
   }
  
   //关闭记录集及库
   RecSet.Close();
   db.Close();
  }


CString类的用法:
   IsEmpty()//字符串是否为空
  Empty()//置空
  Find( )//查找字符串 此为查找空格
  GetAt(0)//得到第一个字符
  SetAt( , )//
  WordSet.m_Word.SetAt( 0, WordSet.m_Word.GetAt( 0 ) - 32 ); 将第一个字母转换为大写状态
  MakeLower()//转化为小写状态
  MakeUpper()//
  GetLength()//得到字符串长度
  TrimRight()//
  MakeLower()//转换成小写字母
  MakeUpper()//转换成大写字母
  设置字体
  CString s;
   s = "<font color='255,255,255' face='宋体' size='12' align='center'><br><p>";
  s += "<font color='200,250,100' size='18' face='宋体' style='ui'>直接通过DAO读、写Access文件示例</font><br><br><p>";
   s += "<font color='200,250,100' size='14' face='宋体'>作者:徐景周</font><br><br><p>";
   s += "<font color='200,250,100' size='14' face='宋体'>未来工作室出品</font><br><p>";
  应用:
  1符匹配:
  匹配单个字符(不区分大小写)
  void CListItemDlg::MatchSingleCharacter()
  {
   CWordDaoSet WordSet;
   CString strLower;
   CString strUpper;
  
   try
   {
   if ( WordSet.IsOpen() )
   WordSet.Close();
   
   WordSet.Open();
   
   while ( !WordSet.IsEOF() )
   {
   m_word.MakeLower();
   strLower = m_word;
   m_word.MakeUpper();
   strUpper = m_word;
   
   // 对单个字符不区分大小写,只与单词的第一个字母比较
   if ( WordSet.m_Word.GetAt(0) == strLower || 
   WordSet.m_Word.GetAt(0) == strUpper )
   m_ListCtrl.InsertItem( 0, WordSet.m_Word );
  
   WordSet.MoveNext();
   }
   }
   catch ( CDaoException *exception )
   {
   exception->ReportError();
   return;
   }
  }
  、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、
   匹配字符串(区分大小写)
  void CListItemDlg::MatchString()
  {
   CWordDaoSet WordSet;
  
   try
   {
   if ( WordSet.IsOpen() )
   WordSet.Close();
   
   WordSet.Open();
   
   while ( !WordSet.IsEOF() )
   {
   if ( m_bChecked )//判断是否区分大小写
   {
   if ( WordSet.m_Word.Find( m_word ) != -1 )
   m_ListCtrl.InsertItem( 0, WordSet.m_Word );
   }
   else
   {
   // 将比较双方都转换为小写状态
   WordSet.m_Word.MakeLower();
   m_word.MakeLower();
  
   if ( WordSet.m_Word.Find( m_word ) != -1 )
   {
   // 匹配则将第一个字母转换为大写状态
   WordSet.m_Word.SetAt( 0, WordSet.m_Word.GetAt( 0 ) - 32 );
   m_ListCtrl.InsertItem( 0, WordSet.m_Word );
   }
   }
   WordSet.MoveNext();
   }
   }
   catch ( CDaoException *exception )
   {
   exception->ReportError();
   return;
   }
  }
  ///
  文件:
  查找文件:
  { 
  UpdateData();
  if(!m_strfile.GetLength())//得到输入文件名
  {
   AfxMessageBox("请输入要查找的文件");
   return ;
  } 
  WIN32_FIND_DATA fd;
  m_listfile.ResetContent();//m_listfile 用来保存查找结果 
  HANDLE hd=::FindFirstFile((LPCTSTR)m_strfile,&fd);// 它有两个参数,第一个是要查找的文件名,第二个是保存查找到的信息,类//型为WIN32_FIND_DAT,返回一个句柄。
  if(hd==INVALID_HANDLE_VALUE) 
   {return;}
  m_listfile.AddString(fd.cFileName);
  while(FindNextFile(hd,&fd)) //继续查找
  {
   m_listfile.AddString(fd.cFileName); 
  };
  FindClose(hd);//关闭查找
  }
  
  //
  其它:
  
  1// 此程序只能运行一次,用互斥来判断程序是否已经运行
  编译了可执行程序,不能再次编译,必须先关掉已执行文件
  若程序已执行完,则弹出对话框!
   BOOL CMagicWordApp::InitInstance()
  {
   AfxEnableControlContainer();
  
   // 此程序只能运行一次,用互斥来判断程序是否已经运行
   HANDLE m_hMutex = CreateMutex( NULL, TRUE, m_pszAppName );
  
   if ( GetLastError() == ERROR_ALREADY_EXISTS )
   {
   AfxMessageBox( "程序已经运行!" );
   return FALSE;
   }
  
  #ifdef _AFXDLL
   Enable3dControls();
  #else
   Enable3dControlsStatic();
  #endif
   //设置对话框背景和文本颜色
   SetDialogBkColor(RGB(160,180,220),RGB(0,0,0));
  2 // 删除最大化命令
   pSysMenu->DeleteMenu( 4, MF_BYPOSITION );
  3.查找注册表
  注册表使用类:E:/兴辉俊武/vc++学习笔记/注册表
  void CMyRegistryDlg::OnButton1() 
  {
   // TODO: Add your control notification handler code here
   CRegistry reg;
   BOOL bReturn;
   DWORD dw=10,dw2;
   CString s;
   int i=1,j;
   bReturn=reg.Open ("Software/0");
   bReturn= reg.CreateKey ("vckbase/0");
   bReturn= reg.Write ("name","xiaojin");//把xiaojin写入注册表
   bReturn= reg.Write ("age",i);
   bReturn= reg.Write ("sarary",dw);
   bReturn=reg.Read ("name",&s);//读出来
   AfxMessageBox(s);
  }
  
  // 跳转到上次退出时的记录
  void CMagicWordDlg::OnJump() 
  {
   HKEY hKey = 0;
   BYTE szBuffer[26] = { '/0' };
   DWORD dwType = REG_SZ;
   DWORD dwSize = 27;
  //查询指定的值
   memset( szBuffer, 0, dwSize );
  
   // 如果打开注册表成功,获取键值并实现跳转。
   //RegOpenKeyEx(注册表主键的名称,欲打开注册表项的地址,)
   // RegQueryValueEx(获得键值,欲设置值的名,NULL,定义读取数据类型,所查询注册表键值的内容,)
   //用&hKey获得键值
   if ( RegOpenKeyEx( HKEY_CURRENT_USER, "SOFTWARE//MagicWord",
   NULL, KEY_ALL_ACCESS, &hKey ) == ERROR_SUCCESS )
   {
   if ( RegQueryValueEx( hKey, "CurrentWord", NULL, &dwType, szBuffer, &dwSize ) == ERROR_SUCCESS )
   {
   CWordDaoSet TempSet;
   CString strSQL;
  
   if ( TempSet.IsOpen() )
   TempSet.Close();
   
   strSQL.Format( "SELECT * from WordList WHERE word = '%s'", szBuffer );
   TempSet.Open( AFX_DAO_USE_DEFAULT_TYPE, strSQL, 0 );
   
   // 没有找到则不移动m_pSet,保证了OnNext/OnModify()等可以正常操作
   if ( TempSet.IsEOF() )
   {
   MessageBox( _T( "单词库中没有这个单词!" ),
   _T( "跳转失败!" ), MB_OK | MB_ICONASTERISK );
   return;
   }
   }
   }
   
   // 找到的话,则m_pSet跳转到该处。
   m_pSet->MoveFirst();//从第一个开始找
   
   while ( !m_pSet->IsEOF() )
   {
   if ( m_pSet->m_Word == szBuffer )
   {
   PublicAssign();
   break;
   }
   m_pSet->MoveNext();
   }
  }
  /
  // 注册最后一个被显示的单词信息
  void CMagicWordDlg::RegCurrentRecord()
  {
   HKEY hKey = 0;
   char szStatus[26] = { '/0' };
   DWORD dwSize = 27;
  
   if ( RegOpenKeyEx( HKEY_CURRENT_USER, "SOFTWARE//MagicWord", 
   NULL, KEY_ALL_ACCESS, &hKey ) == ERROR_SUCCESS )
   {
   wsprintf( szStatus, "%s", m_pSet->m_Word );
   RegSetValueEx( hKey, "CurrentWord", 0, REG_SZ, (CONST BYTE*) szStatus, dwSize );
   RegCloseKey( hKey );
   }
   else
   {
   RegCreateKey( HKEY_CURRENT_USER, "SOFTWARE//MagicWord", &hKey );
   wsprintf( szStatus, "%s", m_pSet->m_Word );
   RegSetValueEx( hKey, "CurrentWord", 0, REG_SZ, (CONST BYTE*) szStatus, dwSize );
   RegCloseKey( hKey );
   }
  }
  
  4。定时器
  先请看SetTimer这个API函数的原型 
  UINT_PTR SetTimer(
   HWND hWnd, // 窗口句柄
   UINT_PTR nIDEvent, // 定时器ID,多个定时器时,可以通过该ID判断是哪个定时器
   UINT uElapse, // 时间间隔,单位为毫秒
   TIMERPROC lpTimerFunc // 回调函数
  );
   
  取消定时器
  不再使用定时器后,我们应该调用KillTimer来取消定时,KillTimer的原型如下
  BOOL KillTimer(
   HWND hWnd, // 窗口句柄
   UINT_PTR uIDEvent // ID
  );//在MFC程序中我们可以直接调用KillTimer(int nIDEvent)来取消定时器。
  void CGraphDlg::OnDestroy() 
  {
   CDialog::OnDestroy();
   KillTimer(1);
  }
  例如 
  int iInstallresult;
   iInstallresult=SetTimer(1, 50, NULL);
   if(iInstallresult==0)
   {
   MessageBox("cannot install timer!");
   }
  SetTimer(m_hWnd,1,1000,NULL); //一个1秒触发一次的定时器
  在MFC程序中SetTimer被封装在CWnd类中,调用就不用指定窗口句柄了,例如:
  UINT SetTimer(1,100,NULL); //函数反回值就是第一个参数值1,表示此定时器的ID号。
  第二个参数表示要等待100毫秒时间再重新处理一次。第三个参数在这种方法中一般用NULL。
  注意:设置第二个参数时要注意,如果设置的等待时间比处理时间短,程序就会出问题了。
  取得系统时间
   CString strTimeNow; //得到系统时间
   CTime now=CTime::GetCurrentTime();
   strTimeNow=now.Format(_T("%Y%m%d"));
  时钟显示:
  在 OninitDialog()的return TRUE 前面添加:// 完成定时器的安装
  int iInstallresult;
  iInstallresult=SetTimer(1,1000,NULL);
  if(iInstallresult==0)
  {
   MessageBox("fail to install the timer!");
  }
  else 
   CurrentTime();
  在OnTimer()里添加CurrentTime();
  void CClockDlg::CurrentTime()//得到系统时间并显示在文本框上
  {
   time_t tCurrentTime; ///声明
   char szBuffer [ 256 ];
   // 获取系统时间
   tCurrentTime = time ( ( time_t* ) NULL );
   strftime ( szBuffer, sizeof ( szBuffer ), "%H", localtime ( &tCurrentTime ) );
   m_hours = szBuffer;
   strftime ( szBuffer, sizeof ( szBuffer ), "%M", localtime ( &tCurrentTime ) );
   m_minutes = szBuffer;
   strftime ( szBuffer, sizeof ( szBuffer ), "%S", localtime ( &tCurrentTime ) );
   m_seconds = szBuffer;
   // 将各变量值赋给对话框相应ID号 对应的项
   ( GetDlgItem ( IDC_HOUR ) ) -> SetWindowText ( m_hours );
   ( GetDlgItem ( IDC_MINUTE ) ) -> SetWindowText ( m_minutes );
   ( GetDlgItem ( IDC_SECOND ) ) -> SetWindowText ( m_seconds );
  }
  //
  
   网络编程
   //
  超连接: m_Mail.SetURL(_T("mailto:jingzhou_xu@163.net"));
  
  在图形框中加入图片或动画――调用PictureEX.h类 在E:/兴辉俊武/vc++学习笔记/动画图片操作/加入图片
  CPictureEx m_Flag; //IDR_FLAG为图形框id
   if(m_Flag.Load(MAKEINTRESOURCE(IDR_FLAG),_T("GIF")))
   {
   m_Flag.SetBkColor(RGB(160,180,220));
   m_Flag.Draw(); 
   }
  求主机名和IP地址#include <afxsock.h> // MFC socket extensions
  void CGetIPDlg::OnQuery() 
  {
   char szHostName[128];
   char szT[20];
   
   if( gethostname(szHostName, 128) == 0 )
   {
   // Get host adresses
   m_HostName.SetWindowText(szHostName);
   struct hostent * pHost; 
   int i; 
   pHost = gethostbyname(szHostName); 
   for( i = 0; pHost!= NULL && pHost->h_addr_list[i]!= NULL; i++ ) 
   {
   char str[100]; 
   char addr[20];
   int j; 
   LPCSTR psz=inet_ntoa (*(struct in_addr *)pHost->h_addr_list[i]);
   m_IPAddr.AddString(psz);
   }
  
   }
  }
  简单的通信:
  服务器:发送一个圆的信息给客户端
   struct yuan
   {
   int x;
   int y;
   int r;
   int color;
   
   } yuan1,*p;
  void CFasonDlg::OnSend() 
  {
   // TODO: Add your control notification handler code here
   UpdateData(TRUE);
   CString m_Getstring;
   
   this->m_Cob.GetLBText(m_Cob.GetCurSel(),m_Getstring);
   if(m_Getstring==_T("Red"))
   yuan1.color=1;
   if(m_Getstring==_T("Green"))
   yuan1.color=2;
   if(m_Getstring==_T("Blue"))
   yuan1.color=3;
   
   
  
   yuan1.x=m_x;
   yuan1.y=m_y;
   yuan1.r=m_r;
  
   p=&yuan1;
  
   CDSocket m_hSocket;
   m_hSocket.Create(2330,SOCK_DGRAM);
   m_hSocket.SendTo( p,sizeof(yuan1),3550,"127.0.0.1");
  
   m_x=0;
   m_y=0;
   m_r=0;
   m_hSocket.Close();
   UpdateData(FALSE);
  }
  客户端:
  void CDASocket::OnReceive(int nErrorCode) 
  {
   // TODO: Add your specialized code here and/or call the base
   char buff[256];
   int ret=0;
   ret=Receive(buff,256);
   if(ret==ERROR)
   {
   TRACE("ERROR!");
   }
   else 
   m_pDoc->Presscessding(buff);
   class CAsyncSocket::OnReceive(nErrorCode);
  }
  CJieshouDoc::CJieshouDoc()
  {
   // TODO: add one-time construction code here
   
   m_hSocket=new CDASocket(this);
   m_hSocket->Create(3550,SOCK_DGRAM);
  
  }
  void CJieshouDoc::Presscessding(char* lbuff)
  {
   buff=(struct yuan*)lbuff;
   p.x=buff->x;
  
   p.y=buff->y;
   p.r=buff->r;
   p.color=buff->color;
   UpdateAllViews(NULL);
  }
  void CJieshouView::OnDraw(CDC* pDC)
  {
   CJieshouDoc* pDoc = GetDocument();
   ASSERT_VALID(pDoc);
   // TODO: add draw code for native data here
   x=pDoc->p.x;
   y=pDoc->p.y;
   r=pDoc->p.r;
   if(pDoc->p.color==1)
   pDC->SelectObject(new CBrush(RGB(255,0,0)));
   if(pDoc->p.color==2)
   pDC->SelectObject(new CBrush(RGB(0,255,0)));
   if(pDoc->p.color==3)
   pDC->SelectObject(new CBrush(RGB(0,0,255)));
   //if(pDoc->p.color==0)
   // pDC->SelectObject(new CBrush(RGB(255,255,255)));
   pDC->Ellipse(x-r,y-r,x+r,y+r);
   
  
  }
   
  //
  外观设计
  修改窗口标题栏
  void CMainFrame::OnUpdateFrameTitle(BOOL Nada)
  { //本函数用于修改窗口标题栏
   CString csAppName;
   csAppName.Format(AFX_IDS_APP_TITLE);
   SetWindowText("动画窗口程序的示例---作者:宁波陈萌 2001.06.17");
  }
  BOOL CMySqlPlusApp::InitInstance()
  {
   AfxEnableControlContainer();
   。。。。。。。。。。。。。。。。。。。。。。。
  // The one and only window has been initialized, so show and update it.
   m_pMainWnd->ShowWindow(SW_SHOW);
   m_pMainWnd->UpdateWindow();
   m_pMainWnd->SetWindowText ("窗口标题");
   return TRUE;
  }
  
  
  
  修改主窗口风格 
  AppWizard生成的应用程序框架的主窗口具有缺省的窗口风格,比如在窗口标题条中自动添加文档名、窗口是叠加型的、可改变窗口大小等。要修改窗口的缺省风格,需要重载CWnd::PreCreateWindow(CREATESTRUCT& cs)函数,并在其中修改CREATESTRUCT型参数cs。
  CWnd::PreCreateWindow 函数先于窗口创建函数执行。如果该函数被重载,则窗口创建函数将使用CWnd::PreCreateWindow 函数返回的CREATESTRUCT cs参数所定义的窗口风格来创建窗口;否则使用预定义的窗口风格。
  CREATESTRUCT结构定义了创建函数创建窗口所用的初始参数,其定义如下:
  
  typedef struct tagCREATESTRUCT { 
  LPVOID lpCreateParams; // 创建窗口的基本参数 
  HANDLE hInstance; // 拥有将创建的窗口的模块实例句柄 
  HMENU hMenu; // 新窗口的菜单句柄 
  HWND hwndParent; // 新窗口的父窗口句柄 
  int cy; // 新窗口的高度 
  int cx; // 新窗口的宽度 
  int y; // 新窗口的左上角Y坐标 
  int x; // 新窗口的左上角X坐标 
  LONG style; // 新窗口的风格 
  LPCSTR lpszName; // 新窗口的名称 
  LPCSTR lpszClass; // 新窗口的窗口类名 
  DWORD dwExStyle; // 新窗口的扩展参数 
  } CREATESTRUCT; 
   
  CREATESTRUCT结构的style域定义了窗口的风格。比如,缺省的MDI主窗口的风格中就包括FWS_ADDTOTITLE(在标题条中显示当前的工作文档名)、FWS_PREFIXTITLE(把文档名放在程序标题的前面)、WS_THICKFRAME(窗口具有可缩放的边框)等风格。由于多种风格参数由逻辑或(“|”)组合在一起的,因此添加某种风格,就只需用“|”把对应的参数加到CREATESTRUCT结构的style域中;删除已有的风格,则需用“&”连接CREATESTRUCT结构的style域与该风格的逻辑非值。
  CREATESTRUCT结构的x、y、cx、cy域分别定义了窗口的初始位置和大小,因此,在CWnd::PreCreateWindow 函数中给它们赋值,将能定义窗口的初始显示位置和大小。
  下例中的代码将主框窗口的大小将固定为1/4屏幕,标题条中仅显示窗口名,不显示文档名。
  
  BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs) 
  { 
  // TODO: Modify the Window class or styles here by modifying 
  // the CREATESTRUCT cs 
  // 修改主窗风格 
  cs.style &= ~FWS_ADDTOTITLE; //去除标题条中的文档名 
  cs.style &= ~WS_THICKFRAME; //去除可改变大小的边框 
  cs.style |= WS_DLGFRAME; //增加不能改变大小的边框 
  
  // 确定主窗的大小和初始位置 
  int cxScreen = ::GetSystemMetrics(SM_CXSCREEN);//获得屏幕宽 
  int cyScreen = ::GetSystemMetrics(SM_CYSCREEN); //获得屏幕高 
  cs.x = 0; // 主窗位于左上角 
  cs.y = 0; 
  cs.cx = cxScreen/2; // 主窗宽为1/2屏幕宽 
  cs.cy = cxScreen/2; // 主窗高为1/2屏幕高 
  return CMDIFrameWnd::PreCreateWindow(cs); 
  }
  
   //设置对话框背景和文本颜色
   SetDialogBkColor(RGB(160,180,220),RGB(0,0,0));
  //对话框居中显示
   CRect dlgRect; 
   GetWindowRect(dlgRect); 
   CRect desktopRect; 
   GetDesktopWindow()->GetWindowRect(desktopRect); 
   MoveWindow( 
   (desktopRect.Width() - dlgRect.Width()) / 2, 
   (desktopRect.Height() - dlgRect.Height()) / 2, 
   0, 
   0 );
  文档设置背景色
  public:
   CBrush m_wndbkBrush;
   COLORREF m_crBackground;
  CAnimatewindowView::CAnimatewindowView()
  { // TODO: add construction code here
   m_crBackground=RGB(146,177,231);
   m_wndbkBrush.CreateSolidBrush(m_crBackground);
  }
  BOOL CAnimatewindowView::OnEraseBkgnd(CDC* pDC) 
  { // TODO: Add your message handler code here and/or call default
   CView::OnEraseBkgnd(pDC);
   CRect rect;
GetClientRect(&rect);
   pDC->FillRect(&rect,&m_wndbkBrush);//设置背景色
   return TRUE;
  }
  菜单------CMenu CToolBar
  取得菜单项指针:
   CWnd*pParent=GetParent();//得到指向主窗口的指针
   CMenu*pMenu=pParent->GetMenu();//得到系统菜单
   CMenu*SubMenu=pMenu->GetSubMenu(0);//得到子菜单
   初始化函数
   菜单操作函数
   菜单项操作函数
   UINT CheckMenuItem(UINT nEDCheckItem, UINT nCheck)
   nEDCheckItem---指定要被复选的菜单项,它既可以是常规菜单项,也可以是弹出菜单项。
   nCheck------指定复选方式:
   MF_BYCOMMAND:通过ID号选择菜单该值为默认值,Windows检查CMenu对象拥有的所有的弹出式菜单项。因此,除非存在完全相同的菜单项,否则使用菜单栏的CMenu对象完全可以,而不必区分弹出式菜单和菜单栏菜单。
   MF_BYPOSITION:菜单项的位置如果为第一项,则nEDCheckItem 为0
   MF_CHECKED:复选指定菜单项。
   MF_ENABLED:解除指定菜单项的选择
  例:SubMenu-> CheckMenuItem(ID_LXC, MF_CHECKED);
  UINT EnableMenuItem(UNIT nIDEnableItem,UINT nEnable)
  函数将使能、禁止、加灰指定菜单项
  返回值:调用成功,返回非零值,否则返回零值。函数将返回菜单项先前的状态。
  nIDEnableItem:指定了将要操作的菜单项
  nEnable:指定了将要采取的操作,
  MF_BYCOMMAND:通过ID号选择菜单项
  MF_BYPOSITION:
  MF_DISABLED:使菜单项无效,即使菜单不能被选中,但并不用灰色显示。
  MF_ENABLED:使菜单项有效
  MF_GRAYED:除去菜单项前的检查标记
  CToolBar
  构造函数:
  。SetSizes:调用该函数设置工具栏按钮大小,原型:
   Void SetSizes(SIZE sizeButton,SIZE sizeImage);
   sizeButton:指定了工具栏按钮的尺寸。
  sizeImage:指定了工具栏位图中按钮图像的尺寸。
  属性操作函数:
   。SetButtonText:设置工具栏按钮的文本。
  BOOL SetButtonText()
  1、定制工具条
  很酷的功能,:-)....
  首先在Create时使用 CCS_ADJUSTABLE风格。
  调用CToolBar::Customize(void);
  此外记得使用RestoreState,SaveState。
  2、增加文字
  调用CToolBar::SetButtonText(...)
  调用CToolBar::SetSizes(...)将按钮尺寸放大到适当大小。
  3、TrueColor image on ToolBar,生成和初始化工具栏,方法很简单有些不可思议。
  m_bmToolbarHi为框架窗口的成员变量。CToolBar m_wndToolBar;
  在OnCreate中
   if (!m_wndToolBar.Create(this) ||
  
   !m_wndToolBar.LoadToolBar(IDR_MAINFRAME))
  
   {
  。。。。。。。。。//增加工具栏的其它功能
   TRACE0("Failed to create toolbar/n");
  
   return -1; // fail to create
  
  }
  4、增加工具栏按钮停放功能,可以改变工具栏的位置。
  m_wndToolBar.EnableDocking(CBRS_ALIGN_ANY);// CBRS_ALIGN_ANY使工具栏停放在四个窗口边的任意边框。调用CControlBar中的EnableDocking函数,允许工具栏本身的停放
   EnableDocking(CBRS_ALIGN_ANY);//调用CFrameWnd中的EnableDocking函数,允许主窗口停放
   DockControlBar(&m_wndToolBar);
  m_wndToolBar.SetBarStyle(m_wndToolBar.GetBarStyle() | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC);// CBRS_TOOLTIPS:激活工具栏提示特性;CBRS_FLYBY:使光标放在键上时 显示命令提示。
   CenterWindow();//使窗口运行时居于屏幕正中央
  动画(图片、声音)
  CListBox:列表框控件类,管理列表框的显示和选择
  CListBox m_AccessList; m_AccessList.ResetContent();//清空列表框
  m_AccessList.AddString( strName + " --> "+strAge );//向列表框中添加数据
  CDC 设备情景对象类,是其它设备情景的基类
  CpaintDC:它的构造函数调用BeginPaint,它的析构函数调用
  EndPaint。
  
  生成自定义的绘图工具:
   CPaintDC dc(this);
   CPen MyNewPen;
   COLORREF mm_color=dlg.m_color;//颜色对话框选择的颜色
   MyNewPen.CreatePen(PS_SOLID,10,mm_color);//RGB(255,0,0)初始化
  //调用CDC::SelectObject把生成的对象调入设备情景
   CPen* pOriginalPen;
   pOriginalPen=dc.SelectObject(&MyNewPen);
  
   CRect MyRectangle(30,10,20+m_Radius*2,10+m_Radius*2);
   //通过m_Radius的大小显示动态圆:右图
   dc.Ellipse(&MyRectangle);//画圆
   dc.SelectObject(pOriginalPen);
   CDialog::OnPaint();
  设置文本的颜色
  void CAnimatewindowView::OnDraw(CDC* pDC)
  {
   CAnimatewindowDoc* pDoc = GetDocument();
   ASSERT_VALID(pDoc);
   // TODO: add draw code for native data here
   CRect rect;
   GetClientRect(&rect); //取客户区尺寸大小
   pDC->SetBkMode(RGB(255,255,255));//设置背景颜色模式为透明色
   pDC->SetTextColor(RGB(255,255,0));//设置文本前景色为黄色
   pDC->TextOut((rect.Width()-280)/2,(rect.Height()-30)/2,"用一点点动画装饰您的程序,祝您好运!");
   //输出文本,同时用客户区宽度与高度计算文本输出位置,280为文本长度,
   //30为文本高度,这个值为经验值并不专业,可以用别的方法精确计算,
   //但对于本文没有必要。
  }
  设置文档的背景颜色:
  public:
   CBrush m_wndbkBrush;
   COLORREF m_crBackground;
  CAnimatewindowView::CAnimatewindowView()//初始化
  {
   // TODO: add construction code here
   m_crBackground=RGB(146,177,231);
   m_wndbkBrush.CreateSolidBrush(m_crBackground);
  }
  BOOL CAnimatewindowView::OnEraseBkgnd(CDC* pDC) //以CView为基类
  {
   // TODO: Add your message handler code here and/or call default
   CView::OnEraseBkgnd(pDC);
   CRect rect;
   GetClientRect(&rect);
   pDC->FillRect(&rect,&m_wndbkBrush);//设置背景色
   return TRUE;
  }
  HBRUSH CKechengView::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor) // 以CFormView为基类
  {
   HBRUSH hbr = CFormView::OnCtlColor(pDC, pWnd, nCtlColor);
   
   // TODO: Change any attributes of the DC here
  // if (nCtlColor==CTLCOLOR _ DLG )
   return (HBRUSH) m_wndbkBrush.GetSafeHandle ( );
   //return CFormView : : OnCtlColor (pDC, pWnd , nCtlColor);
  
   // TODO: Return a different brush if the default is not desired
   return hbr;
  }
  CBitmap类:提供对位图的操作。
   用绘图函数生成位图,基本过程如下:
  1. 创建空白位图对象;
  2. 创建内存设备描述表DC对象
  3. 将位图选入内存DC
  4. 利用内存DC对象的成员函数在位图内绘制位图
  LoadBitmap:从资源加载位图,并将它连接到CBitmap对象
  GetBitmap:取得CBitmap对象的信息赋给一个BITMAP结构体
   CDC MemDC; //创建内存DC
   BITMAP bm; //创建位图结构变量
   CBitmap m_bitmap; //创建位图对象
   CBitmap *old_bitmap; //创建位图对象指针
  m_bitmap.LoadBitmap(IDB_BITMAP1);//拷贝资源位图
   m_bitmap.GetBitmap(&bm);//得到位图结构中的大小信息
  制作闪烁效果:
  #include "LjxWnd.h"//在E:/兴辉俊武/vc++学习笔记/动画图片操作/闪屏图形特技效果的实现
  BOOL CAnimatesplashApp::InitInstance()
  {
   AfxEnableControlContainer();
  
  #ifdef _AFXDLL
   Enable3dControls(); // Call this when using MFC in a shared DLL
  #else
   Enable3dControlsStatic(); // Call this when linking to MFC statically
  #endif
   //增加的代码
   CLjxWnd *ljxljx=new CLjxWnd; //建立一个新窗口对象
   ljxljx->CreatLjxWnd (); //创建窗口――函数中重载功能
  // CWnd类功能
   ljxljx->CenterWindow (); //在屏幕中央
   ljxljx->ShowWindow (SW_SHOW); //显示窗口
   ljxljx->UpdateWindow (); //更新窗口,激活OnPait函数
   Sleep(2000); //等待函数指定秒钟
   if (ljxljx!=NULL) ljxljx->SendMessage (WM_CLOSE); //关闭窗口
   //增加的代码结束
   CAnimatesplashDlg dlg; //显示对话框
   m_pMainWnd = &dlg;
   int nResponse = dlg.DoModal();
   if (nResponse == IDOK)
   {
   // TODO: Place code here to handle when the dialog is
   // dismissed with OK
   }
   else if (nResponse == IDCANCEL)
   {
   // TODO: Place code here to handle when the dialog is
   // dismissed with Cancel
   }
  
   // Since the dialog has been closed, return FALSE so that we exit the
   // application, rather than start the application's message pump.
   return FALSE;
  }
  控件类添加背景位图基本过程如下:
  在树型控件中使用背景位图
   CMyTreeCtrl继承类 CTreeCtrl
  CMyTreeCtrl m_CtrlTree;//控件变量
  BOOL CTreeDlg::OnInitDialog()
  {
  ……….
  m_CtrlTree.SetBKImage("cibas.bmp");// SetBKImage为实现背景位图的函数在CMyTreeCtrl中实现
  ……….
  }
  在MFC程序中显示JPG/GIF图像
  在“E:/兴辉俊武/vc++学习笔记/动画图片操作/JPG图像加载及超连接”定义了所需的类
  CPictureCtrl 使你可以在任何对话框或窗口中把图像作为子窗口显示。
  例如: 关于对话框中加载IDC_MYIMAGE图像
  class CAboutDialog : public CDialog {
  protected:
   CPictureCtrl m_wndPict;
   virtual BOOL OnInitDialog();
  };
  BOOL CAboutDialog::OnInitDialog()
  {
   m_wndPict.SubclassDlgItem(IDC_MYIMAGE,this);// IDC_MYIMAGE和变量m_wndPict建立联系
   return CDialog::OnInitDialog();
  } 
  在文档/视图中加载JPG/GIF图像
  在doc.h中
  #pragma once
  #include "Picture.h"
  protected:
   CPicture m_pict;
  public:
   CPicture* GetPicture() {
   return &m_pict;
  doc.cpp
  #include <afxdisp.h>
  #include <afxpriv2.h>
  void CPictureDoc::Serialize(CArchive& ar)//打开图片在文档中显示
  {
   if (ar.IsLoading()) {
   VERIFY(m_pict.Load(ar));
   } else { }
  }
  BOOL CPictureDoc::OnNewDocument()/*为了使程序更实用,CPictureDoc::OnNewDocument从程序资源数据加载了一幅图像。为了显示这幅图像,CPictureView::OnDraw要调用CPicture::Render。这样程序一启动便会显示一幅默认的图像。*/
  {
   m_pict.Load(IDR_MAINFRAME);
   return TRUE;
  }
  void CPictureView::OnDraw(CDC* pDC)
  {
   CPictureDoc* pDoc = GetDocument();
   ASSERT_VALID(pDoc);
   CPicture* ppic = pDoc->GetPicture();
   ASSERT(ppic);
   if (*ppic) {
   CRect rc;
   GetImageRect(rc);// GetImageRect是CPictureView类的一个成员函数
   ppic->Render(pDC,rc);
   }
  }
  AnimateWindow函数:实现动画效果
  函数原型:BOOL AnimateWindow(HWND hWnd,DWORD dwTime,DWORD dwFlags)。 
  
  函数功能:该函数能在显示与隐藏窗口时产生两种特殊类型的动画效果:滚动动画和滑动动画。 
  
  参数含义: 
  hWnd:指定产生动画的窗口的句柄。 
  dwTime:指明动画持续的时间(以微秒计),完成一个动画的标准时间为200微秒。 
  dwFags:指定动画类型。这个参数可以是一个或多个下列标志的组合。标志描述: 
  AW_SLIDE:使用滑动类型。缺省则为滚动动画类型。当使用AW_CENTER标志时,这个标志就被忽略。 
  AW_ACTIVATE:激活窗口。在使用了AW_HIDE标志后不能使用这个标志。 
  AW_BLEND:实现淡出效果。只有当hWnd为顶层窗口的时候才可以使用此标志。 
  AW_HIDE:隐藏窗口,缺省则显示窗口。 
  AW_CENTER:若使用了AW_HIDE标志,则使窗口向内重叠,即收缩窗口;若未使用AW_HIDE标志,则使窗口向外扩展,即展开窗口。 
  AW_HOR_POSITIVE:自左向右显示窗口。该标志可以在滚动动画和滑动动画中使用。当使用AW_CENTER标志时,该标志将被忽略。 
  AW_VER_POSITIVE:自顶向下显示窗口。该标志可以在滚动动画和滑动动画中使用。当使用AW_CENTER标志时,该标志将被忽略。 
  AW_VER_NEGATIVE:自下向上显示窗口。该标志可以在滚动动画和滑动动画中使用。当使用AW_CENTER标志时,该标志将被忽略。 
  返回值:如果函数成功,返回值为非零;如果函数失败,返回值为零。在下列情况下函数将失败: 
  
  窗口使用了窗口边界;窗口已经可见仍要显示窗口;窗口已经隐藏仍要隐藏窗口。
  实例:动画窗口的实现
  在工程里的StdAfx.h文件靠前位置加上如下定义 
  #undef WINVER
  #define WINVER 0X500
  int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
  { 
   ……
   AnimateWindow(GetSafeHwnd(),1000,AW_CENTER);
   return 0;
  }
  void CMainFrame::OnClose() 
  {
   // TODO: Add your message handler code here and/or call default
   AnimateWindow(GetSafeHwnd(),1000,AW_HIDE|AW_CENTER);
  //AnimateWindow(GetSafeHwnd(),1000,AW_HIDE|AW_BLEND);
   CFrameWnd::OnClose();
  }
  实现对话框的分块消失:E:/兴辉俊武/vc++学习笔记/动画图片操作/实现窗体分块消失
  void CRWAccessDlg::OnOK() 
  {
   CWindowAnima wa(this); //CWindowAnima类在上文件夹中
   //将窗体分为6块动画窗体效果
   wa.Scatter6(90,10);
   CDialog::OnOK();
  }
   
  窗口
  CSplitterWnd类
  CSplitterWnd m_wndSpMain;
  BOOL CMainFrame::OnCreateClient(LPCREATESTRUCT lpcs, CCreateContext* pContext) //在此生成分割函数
  {
   // TODO: Add your specialized code here and/or call the base class
   if (!m_wndSpMain.CreateStatic(this, 1, 2)) //创建一行两列的分割窗口
   {
   TRACE0("Failed to create splitter window/n");
   return FALSE;
   }
   
   // Get the client rect first for calc left pane size
   // create the left tree view first.
   if (!m_wndSpMain.CreateView(0, 0, RUNTIME_CLASS(CPppView),CSize(200, 200), pContext))
   { //在0行0列加入CPppView视图
   TRACE0("Failed to create left pane view/n");
   return FALSE;
   }
  
   // The right pane is a frame which and contain several different views.
   if (!m_wndSpMain.CreateView(0, 1, RUNTIME_CLASS(CShengView), CSize(100,100), pContext))
   { //在0行1列加入CShengView函数
   TRACE0("Failed to create right pane frame/n");
   return FALSE;
   }
   
   return TRUE;
  }

  • 0
    点赞
  • 0
    评论
  • 0
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

©️2021 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值