MFC 日常使用总结 <50>

文章目录

1. DDX_TEXT()

DDX_TEXT()的作用可以理解为把字符串变量和控件的文本(WindowText)关联起来, 
DDX_Control()的作用可以理解为把变量和控件本身关联起来, 
DoDataExchange(pDX)就是处理所有变量与其关联控件交换数据的函数。

void CView::DoDataExchange(CDataExchange* pDX)
{
	CFormView::DoDataExchange(pDX);
	DDX_Text(pDX, IDC_ID_VALUE, m_strID);
	DDX_Control(pDX, IDC_ID_VALUE, m_editID);
}
在程序中
通过update(TRUE)取得控件上的值到m_strID,处理修改后通过update(FALSE)传回控件,界面显示
通过m_editID.GetWindText(str),取得值,处理后,通过m_editID.SetWindText(str)传回控件界面显示

1.1 DoDataExchange( )作用

void CDlgSelectCS::DoDataExchange(CDataExchange* pDX)
{
    CDialog::DoDataExchange(pDX);
    DDX_Text(pDX, IDC_EDIT_SCR, m_ScrCS_Name);
    DDX_Text(pDX, IDC_EDIT_DEST, m_DestCS_Name);
}

MSDN是这样描述的:Called by the framework to exchange and validate dialog data.大意是框架调用此函数来改写与确认对话框数据。

简单地说,通过VC的向导,你可以为每个控件定义一个变量,这段代码就是让变量和控件绑定在一起.

DoDataExchange会被框架调用,用来改变和验证对话框的数据。在这个函数中一般是将控件和某些变量关联,当在其它地方改变量的值,通过UpdateData 进行双向交换。如:

UpdateData();//将控件的值传给变量
m_ScrCS_Name = "Xian 1980.prj";//分别为控件的变量赋值
UpateData(FALSE);//将变量的值传给控件

UpdataData函数内部调用了DoDataExchange。该函数只有一个布尔型参数,它决定了数据传送的方向。调用UpdateData(TRUE)将数据从对话框的控件中传送到对应的数据成员中,调用UpdateData(FALSE)则将数据从数据成员中传送给对应的控件。

UpdateData(false)是将变量的值传到控件.
UpdateData(TRUE)是从控件中取值到关联的变量

关于对话框数据交换及验证

对话框的数据交换和验证机制(DDX、DDV)可以使对话框上控件与对象数据成员间协调工作。

包括控件窗口与控件对象间的连接,控件窗口与对话框数据成员间的连接,以及数据成员的合法性验证等等。
原文链接:https://blog.csdn.net/xdrt81y/article/details/11898735

2. LRESULT

c++中的函数前面加个LRESULT表示函数的返回值是LRESULT类型。
需要注意的是LRESULT是一个数据类型:
MSDN: 32-bit value returned from a window procedure or callback function
指的是从窗口程序或者回调函数返回的32位值
在winnt.h中typedef long LONG;
在windef.h中typedef LONG LRESULT;
所以LRESULT就是longresult,也就是长整型
之所以取名类LRESULT,是因为L即long,result表示结果,说明这个函数的返回值是某个结果。

3. 套接字

套接字是一套网络通信接口,对传输层及以下各层都进行了封装,很多网络协议大多是应用层协议,传输层都是基于tcp或者udp实现的(如果不理解这句话去看一下网络分层模型就明白了)

4. unsigned int 用法

unsigned int是无符号整型,要求定义的整数一定是正整数。

当把一个负数赋值给无符号整型的变量的时候,会自动把最高位的符号位看成整数的一部分。

5. 什么是COLORREF?

COLORREF类型用来描绘一个RGB颜色。其定义如下:

typedef DWORD COLORREF;

typedef DWORD *LPCOLORREF;

6. Windows数据类型

1.简单重定义Windows变量
BOOL类型:TRUE (#define TRUE 1)
		 FALSE(#define FALSE 0)
		 
INT UINT (32位,4字节)
LONG DWORD (32位,4字节)
LPARAM WPARAM (32位,4字节)

SHORT (2字节,16位,用FFFF表示)
typedef unsigned short   WORD;
typedef short SHORT;

LPSTR LPCSTR(字符串指针,可写和只读)    
CHAR* 和 CONST CHAR* 

2.句柄类型
HANDLE of Windows => HANDLE
HANDLE of Instance => HINSTANCE
HANDLE of Icon => HICON

3.结构体类型
POINT,SIZE,RECT

7. 输入,输出;% 、 / 含义;&

cout进行输出时需要紧接着使用“<<”操作符,

使用cin进行输入时需要紧接着使用“>>”操作符

% 为: 整数取余

/ 为:整数取整

& 为: 与运算时,只有都为 1 时,才为 1

8. 符号位是0/1

当该符号位为 0 时,表示的是正数;为 1 时表示负数。

bool类型的数值
0是 false(假)
非0 是 true(真) 1

typedef int BOOL
#define TRUE 1
BOOL EnableWindow(BOOL bEnable = TRUE);  //启用

当代绝大多数计算机表示浮点数都是采用IEEE标准的,这里简化一下,我们只关心符号位,
那么对于一个数,计算机其实是以下面的式子来描述的:(-1)的 s 次幂 * X ,这里的
指数 s 就是用来决定数值 X 是正数还是负数,显而易见,当 s = 0 时,则 X 为正数
(因为任何数的 0 次幂都是 1 );当 s = 1 时,则 X 为负数(因为 -1 的 1 次幂为 -1 ),
至此我们就了解了为什么符号位为 0 时表示正数,为 1 时表示负数了。

9. MFC中GetDlgItem以及SetDlgItem详解

MFC的GetDlgItem()主要是获取对话框上的句柄,通过获取对话框上的句柄可以获取句柄上的信息等
GetDlgItem() 有一个参数,即对话框所要获取的句柄点的ID号
应用如下,比如,获取句柄后可以获取句柄的文本信息,以及设置文本信息
CString str;
GetDlgItem(IDC_NUMBER1) -> GetWindowText(str);      // 获取对话框上句柄的文本信息
GetDlgItem(IDC_NUMBER1) -> SetWindowText(" 数值 ");  // 设置对话框上句柄的文本信息

10. 工具栏停靠问题

m_wndToolBar.EnableDocking(CBRS_ALIGN_ANY); //使工具栏可以停靠 
EnableDocking(CBRS_ALIGN_ANY); //使主框架可以被停靠 
DockControlBar(&m_wndToolBar); //使工具栏停靠在主框架窗口上.

原文链接:https://blog.csdn.net/qq_32203693/article/details/52220189

11.【MFC】EnableWindow:启用/禁用控件或窗口

02、EnableWindow函数
2.1 函数原型
2.2 参数及返回值
02、EnableWindow函数
启用和禁用控件或者窗口(设置个控件或窗口可用或不可用)可以调用CWnd::EnableWindow()函数。

2.1 函数原型
//原型
BOOL EnableWindow(
  HWND hWnd,
  BOOL bEnable
);

2.2 参数及返回值
HWND: 要启用或禁用的窗口的句柄。
bEnable:指示是启用还是禁用该窗口。如果此参数是千真万确,窗口已启用。如果参数是假的窗口被禁用。
返回值

如果该窗口先前已被禁用,则返回值为非零。
如果以前没有禁用该窗口,则返回值为零。
如果窗口被禁用,系统将发送Wm_CANCELMODE留言。如果窗口的启用状态正在更改,系统将发送Wm启用之后的消息。Wm_CANCELMODE留言。(这些消息是在此之前发送的。EnableWindow)如果窗口已经禁用,则其子窗口将隐式禁用,尽管它们不会被发送到Wm启用留言。

在激活窗口之前,必须启用它。例如,如果应用程序正在显示无模式对话框并已禁用其主窗口,则应用程序必须在销毁该对话框之前启用主窗口。否则,另一个窗口将接收键盘焦点并被激活。如果禁用子窗口,则当系统试图确定哪个窗口应接收鼠标消息时,该窗口将被忽略。

默认情况下,在创建窗口时启用该窗口。若要创建初始禁用的窗口,应用程序可以指定WS禁用的样式CreateWindow或CreateWindowEx功能。在创建窗口之后,应用程序可以使用EnableWindow若要启用或禁用窗口,请执行以下操作。

应用程序可以使用此函数在对话框中启用或禁用控件。禁用控件无法接收键盘焦点,用户也无法访问它。

BOOL EnableWindow(BOOL bEnable = TRUE);

判断控件是否可用可以调用 CWnd::IsWindowEnable函数

BOOL IsWindowEnable();

栗子:
C++代码

//第一种写法:
CWnd *pWnd = GetDlgItem(IDC_EDIT1);
pWnd->EnableWindow(FALSE);
pWnd->EnableWindow(TRUE); //启用

//第二种写法:
GetDlgItem(IDC_EDIT1)->EnableWindow(FALSE); //FALSE变灰(不可用)
GetDlgItem(IDC_EDIT1)->EnableWindow(TRUE); //TRUE变亮(可用),默认是TRUE

IsWindowEnable同理,一样的调用方式,这里不写。
————————————————
原文链接:https://blog.csdn.net/m0_43458204/article/details/107916149

12. C++ STL:vecotr的at()函数

arr.at(n)与arr[n]的含义一样,返回arr中第n个元素,唯一的区别在于at()函数比[]运算符更安全,因为at()不会去访问越界的元素。

at()函数在使用进行了是否越界的判断,越界则抛出异常。

at()函数:
vector<_Tp,_Allocator>::at(size_type _ _n)
{
	if(_ _n >= size())
		this -> _ _throw_out_of_range();
	return this -> _ _begin_[_ _n];
}

13. VS2015调试时快捷键不起作用,可以这样解决

使用 VS2019 时,运行调试需要按 ctrl + F5,但是快捷键没有反应,这时候按 Fn + Ctrl + F5 就有效果
这时候按下 Fn+Esc,然后就可以直接按下 F1 ~ F12 使用 VS 的快捷键了。
使用完毕,按下 Fn+Esc ,又变回了系统的快捷键。

14. VS2015快捷键

1. 整行上移 或 下移: Alt + 上下键      
2. 整行删除: ctrl + L    
3. 多行快速编辑: Alt + 左键上拉 或 下拉
4. 快速补全: Tab
5. 调试: F5
6. 不调试直接运行: ctrl + F5
7. 查找和替换: ctrl + F
8. 整行复制: ctrl + d
9. 改成大写:ctrl + shift + U   改成小写: ctrl + U
10. 选择当前单词: ctrl + W
11. 调整代码缩进混乱: 将需要调整的代码全部选中,同时按下ctrl + K ,再同时按下 ctrl + D 

15. EnterCriticalSection和LeaveCriticalSection 函数

多线程中用来确保同一时刻只有一个线程操作被保护的数据的操作函数。

为了让CRITICAL_SECTION发挥作用,我们必须在访问dwTime的任何一个地方都加上 EnterCriticalSection(&cs)和LeaveCriticalSection(&cs)语句。

再次强调一次,没有任何资源被“锁定”,CRITICAL_SECTION这个东东不是针对于资源的,而是针对于不同线程间的代码段的!我们能够用它来进 行所谓资源的“锁定”,其实是因为我们在任何访问共享资源的地方都加入了EnterCriticalSection和 LeaveCriticalSection语句,使得同一时间只能够有一个线程的代码段访问到该共享资源而已(其它想访问该资源的代码段不得不等待)。

————————————————
原文链接:https://blog.csdn.net/qq_15267341/article/details/79387608

16. VC++控件工具箱

VC++6.0控件工具箱: 

2 图形控件(picture):常用于显示位图(Bitmap)和图标(Icon)

3 静态文本(Static Text):用来在指定的位置显示特定的字符串,一般用来标识附近另一个控件的内容。显示在静态文本控件中的字符串一般不再改变,但是在需要的时候,也可以通过调用相应的函数来进行设置。MFC提供了CStatic类支持静态控件。

4 编辑框(Edit Box):用来接收用户输入的字符串。通过选择编辑框的选项,编辑框可以接收字符串、数字、密码等;编辑框还可以设置成接收多行字符串的模式;可以自动进行大小写转换。编辑框可能向其父窗口发送多种控件通知,如果用户需要,可以对这些控件通知进行处理。MFC提供了CEdit类支持编辑框控件。

5 组成框(Group Box):用来包围具有逻辑关系的一组控件,在这些控件的周围加上边界和标题。需注意的是,组成框仅仅是在视觉效果上对控件进行“成组”,真正的“成组”工作还需要另外一些工作。

6 按钮(Button):用来接收用户的命令,应用程序在接收到用户命令后,通常需要进行一些后台工作。按钮可以响应单击或双击动作,在按钮接收到鼠标动作后,向其父窗口发送相应的控件通知,用户可以对这些控件通知进行消息映射,从而进行相应的处理。在一个对话框中,可以定义一个默认按钮,这只要选中按钮属性中的“Default”选项。如果在对话框活动的时候按下了Enter键,则等同于单击了默认按钮。MFC提供了CButton类支持按钮控件。

7 复选框(Check Box):用来显示某种可能的选择,该项选择是独立的,用户可以选中或取消该选项。在选项被选中的时候核选标记出现,选项被取消时核选标记消失。MFC中由CButton类对核选框进行支持,用户可以通过SetCheck()函数和GetCheck()函数设置或获取核选框当前的状态。

8 单选按钮(Radio Button):用来选择某种可能的选择,与核选框不同,该选项不是独立的。一般是几个单选按钮组成一组,同组中的单选按钮可以有也只能有一个按钮被选中。MFC同样使用CButton类对单选按钮控件进行支持,SetCheck()函数和GetCheck()函数对单选按钮也是适用的。

9 组合框(Combo Box):列表框和编辑框的组合,用户除了可以在列表中对已经存在的选项进行选择外,还可以输入新的选择。MFC提供了CComboBox类对组合框控件进行支持。

10 列表框(List Box):用来选择一系列的可能选择,用户通过滚动条可以在这些选择中浏览。在列表框中,可以进行单项选择,也可以进行多项选择,这取决于用户在控件属性对话框中的设置。MFC提供了CListBox类对列表框控件进行支持。

11、12 滚动条(Scroll Bar):这包括水平滚动条和垂直滚动条,除了在视觉效果上的方向不同外,水平滚动条在被滚动时发生WM_HSCROLL消息,而垂直滚动条在被滚动时发送WM_VSCROLL消息。MFC提供了CScrollBar进行支持。

13 微调按钮(Spin Button):包括一对紧靠在一起的上下箭头,使用微调按钮可以增大或者缩小某个特定的数值。微调按钮往往都需要一个“伙伴”控件,这通常都是一个编辑框。当微调按钮的向上箭头被单击时,编辑框中的数字就增大;反之则减小。MFC提供了CPinButtonCtrl类进行支持。

14 进度条(Progress):在进行一项需要占有较长时间的操作时来反应当前的进度。当操作的进度不断前进时,进度条就用特色颜色填充进度条框。用户可以设定进度条的范围和当前位置。MFC提供了CProgressCtrl类进行支持。

15 滑块控件(Slider):通常用来在程序中接受一系列离散的数值。用户可以设置滑块控件的取值范围,并可以为控件加上刻度标记以显示特定位置的含义。MFC提供了CSliderCtrl类进行支持。

16 热键控制(Hot Key):热键控件看起来就像一个编辑框,但是在热键控件中能够立刻反应用户刚刚按下的键组合,这在设置程序的热键时特别有用。热键控件只是在“视觉”上显示了按键组合,设置热键的工作还需要用户添加代码完成。MFC提供了CHotKey类进行支持。

17 列表控制(List Control):按一定的排列顺序显示一系列带图标的字符串,列表控件提供了四种显示模式:大图标、小图标、列表和详细信息。用户可以向列表控件中添加新的项,也可以控制列表控件的显示模式。MFC提供了CListCtrl类进行支持。

18 树形控件(Tree Control):用来显示一系列项目的层次关系,最典型的例子是显示磁盘上的文件与文件夹。如果有子项目的话,单击树形控件中的项目可以展开或者收缩其子项目。MFC提供了CTreeCtrl类进行支持。

19 属性表控件(Tab Control):用来包含大量的控件,可以满足用户显示或者获取大量数据的要求。每个属性表又分为好几个属性页,这些属性页由各自的标签进行区分,这些属性页中都可以包容其他控件。在显示属性表的时候,一次只能够显示一个属性页的全部内容,同时显示其他属性页的标签,用户通过单击标签打开相应的属性页。MFC提供了CTabCtrl类进行支持。

20 动画控件(Animation):用来播放一段AVI格式的视频剪辑。用户可以控制视频剪辑的播放、停止和定位,但也仅限于这些功能。动画控件设置不能播放音频剪辑,如果用户需要更高层次的视频或者音频的支持,请选用MCIWnd控件。MFC提供了CAnimateCtrl类对动画控件进行支持。

21 高级编辑框(Rich Edit):编辑控件功能的扩展。在高级编辑框中,除了简单的输入和编辑字符串外,用户还可以为字符或段落指定特定的格式,用户甚至还可以向高级编辑框中插入OLE项。高级编辑框基本上实现了一个带格式的文本编辑器功能,而只需要用户添加少量的接口。MFC提供了CRichEditCtrl类进行支持。

22 日历控件(Month Calender):看似与真正的日历类似,操作也类似,直观的为用户提供了观察和显示当前日期的途径。MFC提供了CMonthCalCtrl类进行支持。

23 日期/时间选择器(Date Time Picker):向用户提供了一种直观的选择日期和时间的方法、日期/时间选择器在外观上类似于一个组合框,但是当用户单击下拉箭头时就会展开一个日历控件供用户选择,而一旦用户做出了选择,日期/时间选择器会自动显示新的日期/时间。MFC提供了CDateTimeCtrl类进行支持。

24 IP地址控件(IP Adress):IP地址控件用来输入和编辑IP地址。该控件外观类似于一个编辑框,但是可以自动对输入的字符按3个一组进行区分和加间隔圆点。IP地址控件为开发支持Internet技术的程序提供了方便。MFC提供了CIPAddressCtrl类进行支持。

26 扩展组合框(Extended Combo Box):在普通组合框的基础上还支持图像列表。即,可以在组合框中显示特定的图标表示相应的选择,而不仅仅是显示文本。MFC提供了CComboBoxEx类进行支持。

17. 控件的公共属性

所有控件的公共属性:

ID:控件的资源标识。

Visiable:控件是否可见。

Disabled:控件是否被禁止、被禁止的控件无法接受键盘和鼠标输入。

Group:是否从这个空间开始一个新组。

Tab stop:在程序中是否可以用【Tab】键切换到这个控件。

Help ID:是否给控件分配一个帮助标识,帮助标识基于控件本身的资源标识。

Client edge:给控件增加一个凹陷的边界,使整个控件看起来像是凹下去的一样。

Static edge:给控件增加一个边界。

Modal frame:给控件增加一个3维的框架,与Client edge相反,它是凸出来的。

Transparent:拥有此属性的窗口是透明的,它下面的窗口不会被它遮掩住。

Accept files:拥有此属性的窗口可以接收拖放文件,如果一个文件被拖动到这个控件上面,控件会收到WM_DROPFILES消息。

No parent notify:表示控件不向其父窗口发送WM_PARENTNOTIFY消息。

Right aligned text:表示文本右对齐。

以上属性可通过控件的属性对话框进行设置,在属性对话框中按【F1】键可以查看属性的帮助信息。

 
 
每一种控件都由一个MFC控件类来管理,当通过资源编辑器在对话框上添加一个控件时,visualC++会自动为控件类生成一个实例,即对象,并调用构造函数,当对话框关闭时,其各个子控件对象被自动销毁。

也可以不使用资源编辑器,自己在程序中写代码创建、显示控件并设置控件的属性。

所有的控件类都继承自CWnd,控件的某些操作和属性设置需要用到CWnd本身的成员函数,CWnd某些函数经常用来操纵控件和设置控件属性。

SetWindowText:设置控件上要显示的标题文本,即用来设置控件的caption属性

GetWindowText:得到控件的标题文本

EnableWindow:设置控件的Disabled属性,即社会自控件是否可以接收键盘和鼠标的输入

SetWindowPos:改变窗口的大小、位置和Z轴次序。

MoveWindow:改变窗口的大小和位置

GetWindowRec:得到窗口的大小、位置(信息存放在一个矩形结构中)。

GetClientRect:得到窗口客户区的大小(信息存放在一个矩形结构中 )

ShowWindow:设置窗口的可见性(即窗口是否可见)

SetWindowText/GetWindowText还可以用来设置/得到对话框的标题文本。

原文链接:https://blog.csdn.net/netanimals/article/details/6587831

18. VC++中获取DC的方法

HDC hdc;
//GetDc()获取设备描述表     //CWnd类有一个成员变量(m_hWnd)用于保存窗口句柄
hdc=::GetDc(m_hWnd);加两个冒号表示我们用的是全局SDK的函数,否则表示我们用的是CWND中的函数
//释放设备描述表
::ReleaseDc(m_hWnd,hdc);

19. MFC文件操作、对象序列化

一、MFC文件的操作
  1.相关类
    CFile - 文件操作类,封装了关于硬盘文件读写操作的API函数,父类CObject
    CFileFind - 文件查找类,封装了关于文件遍历操作的API函数
  2.CFile类的使用
    2.1文件内容读写
     (1)创建或打开硬盘文件,CFile::Open
     (2)读写文件,CFile::Read / CFile::Write
     (3)设置文件位置,CFile::Seek / CFile::SeekToBegin / CFile::SeekToEnd
     (4)关闭文件,CFile::Close

    2.2文件属性的获取和设置
      (1)CFile::GetStatus
     (2)CFile::SetStatus     
  3.CFileFind类的使用
   (1)利用CFileFind::FindFile函数,开始查找指定目录,如果成功返回TRUE,失败返回FALSE
    (2)利用CFileFind::FindNextFile函数,找到第一个文件,同时通过返回值获取下一个文件是否存在
      存在返回TRUE,不存在返回FALSE
   (3)可以利用一系列CFileFind::GetXXX获取文件信息
   (4)可以利用一系列CFileFind::IsXXX判断文件属性
   (5)结束查找,CFileFind::Close
   
二、序列化
  1.概念
    将数据以二进制流的方式依次写入到文件或从文件中读取的过程
  2.CArchive类
   2.1 打开或新建文件,CFile::Open
   2.2 读写文件,CFile::Read / CFile::Write
    (1)定义CArchive对象
    (2)具体的数据读写
        <<  写操作 ,>>  读操作
    (3)关闭CArchive对象
   2.3 关闭文件,CFile::Close  
   
三、对象的序列化(第6个机制,MFC其余5大机制:程序启动、窗口创建、消息映射、动态创建、运行时类信息)
  1.概念
   序列化对象 - 将对象的类的信息和对象的成员变量以二进制流的方式依次写入到文件的过程。         
   反序列化对象 - 首先读取类的信息,创建对象,然后读取文件中的成员变量赋值给对象的过程。
 2.使用
  2.1 定义支持序列化的类 ★
   (1)派生自CObject类
   (2)在类的内部添加序列化声明宏 DECLARE_SERIAL
     在类的外部添加序列化的实现宏 IMPLEMENT_SERIAL
   (3)重写virtual void Serialize( CArchive & ar )函数,在函数中完成类的成员变量的序列化
   2.2 使用
    读写时,与基本类型的数据一样方便,但是,参数是对象的地址
  2.3 实现原理
   (1)展开宏
   (2)成员
      _init_CStudent,全局的变量,类型是AFX_CLASSINIT
      operator>>,全局函数,作用是读取对象
   (3)结构的说明   
      struct  AFX_CLASSINIT
      {
        AFX_CLASSINIT( CRuntimeClass*  pNewClass )
        {
          AfxClassInit( pNewClass )
          {
            //将classCStudent的地址保存到应用程序的链表m_classList中
            pModuleState->m_classList.AddHead( pNewClass );
          }
        }
      };  
   (4)写对象的过程    
      _AFX_INLINE  CArchive&  AFXAPI  operator<<( CArchive&  ar,  const  CObject*  pOb )
      {
        ar.WriteObject( pOb )
        {     
          //获取classCStudent变量
          CRuntimeClass*  pClassRef  =  pOb->GetRuntimeClass( );  
          //将类信息写入到文件
          WriteClass( pClassRef )  
          {         
            *this  <<  wNewClassTag;
            pClassRef->Store( *this )  //将类的版本、类名称长度、类名称依次写入到文件
            {           
              WORD nLen  =  ( WORD )AtlStrLen( m_lpszClassName ); 
              ar  <<  ( WORD )m_wSchema  <<  nLen;  
              ar.Write( m_lpszClassName,  nLen*sizeof( char ) );
            }
          }
          //根据多态的特性,将成员变量依次写入到文件
          ( ( CObject* )pOb )->Serialize( *this )   //this为ar的地址
          {
            CObject::Serialize( ar ); 
            if ( ar.IsStoring( ) )
              ar << m_sName << m_nAge;
            else
              ar >> m_sName >> m_nAge;
          }
        }
         return ar;
      }
   (5)读对象过程  
      CArchive& AFXAPI operator>>(CArchive& ar, CStudent* &pOb)
      {
        pOb  =  ( CStudent* )ar.ReadObject( RUNTIME_CLASS( CStudent ) )
        {         
          UINT  nSchema;
          DWORD  obTag;
          //读取类的信息
          CRuntimeClass*  pClassRef  =  ReadClass( RUNTIME_CLASS( CStudent ),  &nSchema,  &obTag )
          {
            pClassRef  =  CRuntimeClass::Load( *this,  &nSchema ) )  //this为ar的地址
            {    
              //依次读取类的版本、类名长度、类名         
              WORD  nLen;
              char  szClassName[ 64 ];
              ar  >>  wTemp;  
              ar  >>  nLen;
              ar.Read( szClassName,  nLen*sizeof( char ) )
              //根据类的名称查找并返回对应的classCStudent运行时类信息
              CRuntimeClass*  pClass =  FromName( szClassName );  
              return  pClass;
            }
            return  pClassRef;
          }
        }
        pOb->Serialize( *this )     
        {        
          CObject::Serialize( ar );
          if  ( ar.IsStoring( ) )
            ar  <<  m_sName  <<  m_nAge;
          else
            ar  >>  m_sName  >>  m_nAge;
        }
        return  ar;
      }
 例子:1.自定义一个地址类型,支持序列化,能够序列化该类的对象
      class  CAddress
      {
        CString  m_sProvince;
        CString  m_sCity;
      };
    2.修改CStudent类,增加CAddress类型的成员变量,能够序列化该类的对象

20. 下拉框列表控件的使用

1. 获取下拉框内容:
	//利用如下API,第一个参数为索引,第二个为储存索引值对应数据的CString类型的buf。
	m_cbx.GetLBText(1,str);
	//利用事件获取:
	右键下拉框属性,选择“控件事件”,再选择SELCHANGE:
	该事件的作用是,只要一切换,就会触发该事件。
	void CcomboBoxCtrDlg::OnCbnSelchangeCombo1()
	{
		// TODO: 在此添加控件通知处理程序代码
		//拿到索引位置
		int index = m_cbx.GetCurSel();
		CString str;
		m_cbx.GetLBText(index, str);
		MessageBox(str);
	}

2. 设置下拉框默认显示的数据:
	m_cbx.SetCurSel(0);
	使用如下API,参数为上述数据的索引,从0开始。

3. 修改为不可修改的下拉框:
	属性里选择类型,改为下拉列表。

4. 添加数据
	右键选择下拉框,点击属性,里面有一个“数据选项”。
	输入数据,用分号“;”(英文的分号)来分割数据。
	//也可以在初始化中添加数据,通过添加变量,往下拉框里添加数据;在OnInitDialog中添加变量初始化代码:
	//AddString(TEXT("唐僧"));

5. 插入删除列表数据
	插入: 参数为索引和要插入的字符;
	//m_cbx.InsertString(4, TEXT("白龙马"));
	删除: 参数为索引;
	//m_cbx.DeleteString(3);

6.按照自己输入的数据顺序排序
	下拉框默认按照ASCⅡ码的首字母排序,要按照自己输入的顺序排序需要修改属性:
	排序改为False即可

21. CString 常见用法:

1. CString Right( int nCount ) const;
    从右取字串
    例:csStr="abcdef";
        cout<<csStr.Right(3);   //def
    //当nCount等于0时,返回空。
    //当nCount为负数时,返回空。
    //当nCount大于对象长度时,返回值与对象相同。
    
2. CString::Empty
	void Empty(	);
	返回值:没有返回值,清空操作
	
3. Format函数详解:
	Format是CString类的一个成员函数,它通过格式操作使任意类型的数据转换成一个字符串。

22. IsDirectory和IsDots用法:

IsDirectory判断是否为目录,IsDots判断是否为点

每个目录下都有缺省的两个目录,名称分别为'.'和'..',分别代表上一层目录和本层目录。
因此,当我们在遍历目录下文件时,需要过滤掉这两个缺省目录。

23. Vector 构造对象 :

1. 默认初始化vector对象,创建一个指定类型空vector:
   vector<string> svec;   //默认初始化,svec不含任何元素

2. 允许把一个vector对象的元素拷贝给另外一个vector对象:
    vector<int> ivec;//初始状态为空
	vector<int> ivec2(ivec);//把ivec的元素拷贝给ivec2
	vector<int> ivec3 = ivec;//把ivec的元素拷贝给ivec3
	vector<string> svec(ivec2);//错误:sevc的元素是string对象,不是int
	
3. 列表初始化vector对象
	列表初始化,用花括号括起来的0个或多个初始值被赋予给vector对象:
	vector<string> articles = {"a","an","the"};
	//提供的是初始元素值的列表,只能把初始值都放在花括号里进行列表初始化,而不能放在圆括号里。
	
4. 创建指定数量的元素
    vector对象容纳的元素数量和所有元素的统一初始值来初始化vector对象:
	vector<int> ivec(10,-1);	//10个int类型的元素,每个都被初始化为-1
	vector<string> svec(10, "hi");	//10个string类型的元素,每个都被初始化为"hi!"
	
5. 值初始化
	只提供vector对象容纳的元素数量而略去初始值,库会创建一个值初始化的元素初值,并把它赋给容器中的所有元素,	   初值由vector对象中元素的类型决定:
	vector<int> ivec(10);	//10个元素,每个都初始化为0
	vector<string> svec(10);	//10个元素,每个都是空string对象
	
6.  为什么需要vector?
	封装任何类型的动态数组,自动创建和删除。
	数组下标越界检查。
	
7. vector对象的定义
	vector可以容纳任何类型的数组
	vector<元素类型> 数组对象名(数组长度);
	//vector<int> arr(5);  //建立一个大小为5,名为arr的int类型数组
	
8. vector对象的使用
	对数组元素的引用:与普通数组具有相同形式:
	vector对象名 [ 下标表达式 ]
	arr[1]  //访问arr的一个元素
	vector数组对象名不表示数组首地址
	获得数组长度:用size函数
	数组对象名.size()
	
9. vector应用举例:
    #include <iostream>
    #include <vector>
    using namespace std;
    //计算数组arr中元素的平均值
    double average(const vector<double> &arr)
    {
        double sum = 0;
        for (unsigned i = 0; i < arr.size(); i++)
            sum += arr[i];
        return sum / arr.size();
    }
    int main() {
        unsigned n;
        cout << "n = ";
        cin >> n;
        vector<double> arr(n); //创建数组对象
        cout << "Please input " << n << " real numbers:" << endl;
        for (unsigned i = 0; i < n; i++)
            cin >> arr[i];
        cout << "Average = " << average(arr) << endl;
        return 0;
    }

24. VC++ MFC CFile.Open()的使用说明:

cfile:: open
文件操作,有多个选项,也就是不只是字面上的【打开】,还可以【创建】文件

函数原型
virtual BOOL Open( LPCTSTR lpszFileName, UINT nOpenFlags, CFileException* pError = NULL );

返回值
成功为非0,否则为0,仅当返回值为0时pError参数才有意义

参数
lpszFileName   需要打开文件的路径字符串,这个路径可以是相对路径也可以是绝对路径,或者是网络名字(UNC)

nOpenFlags   一个UINT定义文件的存取共享模式。它指定文件打开时可以采取的操作。你可以使用”|"号来组合多个选项。文件的一个存取权限和一个共享选项是必须要指定的。而modeCreate 和modeNoInherit是可选的。

具体如下:
nOpenFlags	 							说明
CFile::modeCreate			让构造器创建一个新文件,如果那个文件已经存在,把那个文件的长度重设为0
CFile::modeNoTruncate		可以同modeCreate. 一起用,如果要创建的文件已经存在,并不把它长度设置为0,因而这个文件获取或者作为一个新建文件或者作为一个							   已存在文件打开。这个功能往往很好用,比如说,当你需要打开一个设置文件,但是你并不清楚这个文件是否已经存在。
CFile::modeRead				打开文件仅仅供读
CFile::modeReadWrite		打开文件供读写
CFile::modeWrite			打开文件只供写
CFile::modeNoInherit		阻止这个文件被子进程继承
CFile::shareDenyNone		打开这个文件同时允许其它进程读写这个文件。如果文件被其它进程以incompatibility模式打开,这是create操作会失败。
CFile::shareDenyRead		打开文件拒绝其它任何进程读这个文件。如果文件被其它进程用compatibility模式或者是读方式打开,create操作失败。
CFile::shareDenyWrite		打开文件拒绝其它任何进程写这个文件。如果文件被其它进程用compatibility模式或者是写方式打开,create操作失败。
CFile::shareExclusive		以独占方式打开这个文件,不允许其它进程读写这个文件。 Construction fails if the file has been opened in any 								other mode for read or write access, even by the current process.
CFile::shareCompat			这个标志在32位的MFC中无效。 This flag maps to CFile::shareExclusivewhen used in CFile::Open.
CFile::typeText				设置成对回车换行对有特殊处理的文本模式(仅用在派生类中)
CFile::typeBinary			设置二进制模式(仅用在派生类中)

pError    一个指向一个已经存在的file-exception类的指针,它会接收文件失败操作的具体状态。

注明:
OPEN默认是用在CFILE的构造器中,这两个函数提供了一个对文件的安全访问方式,即使发生了错误也会正确的回报错误。

————————————————
原文链接:https://blog.csdn.net/tcjy1000/article/details/46947615

25. UpdateData( )

1.UpdateData()
        UpdateData(FALSE):将变量中的值更新到控件中;
        UpdateData(TRUE):将控件中的值更新到变量中;
        UpdateData()函数的参数默认为TRUE;

26. int InsertColumn( )

2.int InsertColumn( int nCol, LPCTSTR lpszColumnHeading, int nFormat =  LVCFMT_LEFT, int nWidth = -1, int nSubItem = -1 )
              
           nCoL:要插入列的序数
           lpszColumnHeading:要插入的字符串
           nFormat:单位格字体的风格,LVFMT_LEFT表示左对齐, LVFMT_CENTER表示居中对齐, LVFMT_RIGHT表示右对齐

27. int FindItem( )

3.int FindItem(LPCTSTR lpszText)
           该函数返回与指定字符串匹配的在列表框第一列的索引,若返回的是-1,说明没有与第一列匹配的项目

28. int GetItemCount( )

4.int GetItemCount( ):
      int nLine = m_enumDataStyle.GetItemCount(); 
	  int nCol = m_enumDataStyle.GetHeaderCtrl()->GetItemCount(); 
	 二者有什么区别
	 第一个是列表的里面的条目数量, 横着的  行
	 第二个是列的数量. 竖着的  列

29. int InsertItem( )

5.int InsertItem(int nPos,LPCTSTR lpszItem )
  	如果新的项目成功插入,则返回新项目的序号,否则返回-1
 	 nPos:第nPos行开始插入新元素 
  	 lpszItem:插入的字符串内容

30. BOOL SetItemText( )

6.BOOL SetItemText(int nItem ,int nSubItem ,LPCTSTR lpszText )         
          nItem:在第nItem行插入元素     
          nSubItem:第nSubItem列的位置插入元素
          lpszText:要插入的字符串内容

31. MFC中CFileDialog的用法

CFileDialog::CFileDialog( BOOL bOpenFileDialog, 
						LPCTSTR lpszDefExt = NULL, 
						LPCTSTR lpszFileName = NULL, 	
						DWORD dwFlags = OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, 
						LPCTSTR lpszFilter = NULL, 
						CWnd* pParentWnd = NULL );
参数意义如下:
// bOpenFileDialog 	为TRUE则显示打开对话框,为FALSE则显示保存对话文件对话框
// lpszDefExt 指定默认的文件扩展名。
// lpszFileName 指定默认的文件名。
// dwFlags 指明一些特定风格。{ OFN_HIDEREADONLY 表示隐藏文件对话框上的“Read Only"复选框,
						   OFN_OVERWRITEPROMPT 表示在保存文件对话框中如果你选择的文件存在了,就弹出一个消息对话框,要求确定是否要覆盖此文件 }
/* 
lpszFilter 是最重要的一个参数,它指明可供选择的文件类型和相应的扩展名。参数格式如:
"Chart Files (*.xlc) | *.xlc 
| Worksheet Files (*.xls) | *.xls	
| Data Files (*.xlc ; *.xls) | *.xlc ; *.xls 
| All Files (*.*) | *.* 
|| " ;
文件类型说明和扩展名间用 | 分隔,同种类型文件的扩展名间可以用 ; 分割,每种文件类型间用 | 分隔,末尾用 || 指明。
*/

代码案例:
 void CFoxitDlg::OnBtn3()   
{  
     // TODO: Add your control notification handler code here  
     CString filter;  
     filter = "文本文档(*.txt) | *.txt 
    		 | PDF文档(*.pdf) | *.pdf 
    		 ||";  
     CFileDialog dlg(TRUE,
     				NULL,
     				NULL,
     				OFN_HIDEREADONLY,
     				filter);  
     if(dlg.DoModal() == IDOK)  
     {  
     	 CString str;  
      	 str=dlg.GetPathName();  
      	 MessageBox(str);  
     }  
}  

//****************************************************
文件对话框也是模态对话框,所以在打开时也需要调用CFileDialog类的DoModal()成员函数。
在打开文件对话框中点了“打开”或者在保存文件对话框中点了“保存”以后,
我们可以使用CFileDialog类的成员函数GetPathName()获取选择的文件路径。

下面列出几个CFileDialog类的成员函数,我们可以使用它们获得文件对话框中的各种选择。

GetFileExt():获得选定文件的后缀名。
GetFileName():获得选定文件的名称,包括后缀名。
GetFileTitle():获得选定文件的标题,即不包括后缀名。
GetFolderPath():获得选定文件的目录。
GetNextPathName():获得下一个选定的文件的路径全名。
GetPathName():获得选定文件的路径全名。
GetReadOnlyPref():获得是否“以只读方式打开”。
GetStartPosition():获得文件名列表中的第一个元素的位置
————————————————
原文链接:https://blog.csdn.net/m0_37863832/article/details/80112923
//******************************************************

32. GetCurSel()函数的应用

本函数用于MFC编程时,取得组合框中当前选中的项的下标。

33. MFC :: check box 的用法

在界面设计中,我们经常会用到Check Box这个控件,Check Box 的使用方法与Radio Button 的用法相似,但比它要简单得多。
一、设定Check Box为 选中状态
((CButton*)GetDlgItem(ID号))->SetCheck(TRUE);
(SetCheck(FALSE)) 为不选中,如果想初始化为选中状态,则在InitDlg函数中加入下面这段语句。
( (CButton*)GetDlgItem(IDC_RADIO1))->SetCheck(TRUE);

二、检查Check Box是否为选中状态
可使用GetCheck()这个函数,如下:
if(BST_CHECKED==((CButton*)GetDlgItem(IDC_RADIO1))->GetCheck()) 判断是否选中;
if(BST_UNCHECKED==((CButton*)GetDlgItem(IDC_RADIO3))->GetCheck()) 判断是否未选中。

34. MFC中如何判断对话框显示 or 隐藏

使用CWnd的成员函数
IsWindowVisible();
就能返回一个窗口是否可见了。

35. MFC :: SHOWControlBar( )

类: CFrameWnd
头文件: afxwin.h
功能: 显示或隐藏一个控件条。
语法:
void ShowControlBar(CControlBar *pBar,BOOL bShow,Bool bDelay);
参数:
pBar 指向要显示或隐含的控件条
bShow 如果为TRUE,指定控件条将显示; 如果为FALSE,则隐藏。
bDelay 如果为TRUE,延迟显示控件条;如果为FALSE,则立即显示。
说明:
调用该函数显示或隐藏一个控件条。

示例:
演示函数原型:pFrameWnd->ShowControlBar( pBar,FALSE,TRUE);
程序功能说明:隐藏指定的控件条。
************************************************************/
//在框架的控件条列表中获得一个控件条的指针
CControlBar* pBar=(CControlBar*)pFrameWnd->m_listcontrolBars.GetNext(pos);
//如果控件条可见则隐藏该控件条
if(pBar->IsVisible())
pFrameWnd->ShowControlBar( pBar,FALSE,TRUE);

36. MFC通用控件初始化 ——InitCommonControlsEx()


MFC工程中,在InitInstance()函数(一般在工程名.cpp文件中)中有这样一段代码:
*************************************************************************************
 // 如果一个运行在 Windows XP 上的应用程序清单指定要
 // 使用 ComCtl32.dll 版本 6 或更高版本来启用可视化方式,
 //则需要 InitCommonControlsEx()。否则,将无法创建窗口。
  INITCOMMONCONTROLSEX InitCtrls;
 InitCtrls.dwSize = sizeof(InitCtrls);
  // 将它设置为包括所有要在应用程序中使用的
 // 公共控件类。
  InitCtrls.dwICC = ICC_WIN95_CLASSES;
  InitCommonControlsEx(&InitCtrls);
**************************************************************************************
这些代码的作用,注释里已经说的很清楚了,我们先来看下这写代码是什么意思。
我们从InitCommonControlsEx函数下手,其函数原型为:

BOOL InitCommonControlsEx(
LPINITCOMMONCONTROLSEX lpInitCtrls
);

其有一个参数lpInitCtrls,是一个指向结构体INITCOMMONCONTROLSEX的长指针,上面的代码先创建一个INITCOMMONCONTROLSEX结构体对象 InitCtrls,然后将其地址作为InitCommonControlsEx函数的参数。INITCOMMONCONTROLSEX结构体的定义在commctrl.h文件中,下面的代码节选自commctrl.h文件,其中包括InitCommonControls和InitCommonControlsEx函数的声明以及tagINITCOMMONCONTROLSEX 结构体的定义。
  INITCOMMONCONTROLSEX结构体包含两个参数dwSize和dwICC,参数说明请看注释。_WIN32_IE和_WIN32_WINNT的定义请看stdafx.h文件。
  InitCommonControlsEx函数的调用效果是累加的,例如你先以ICC_TAB_CLASSES标志调用InitCommonControlsEx,然后以ICC_BAR_CLASSES 标志调用,那么tab和bar通用控件类都将被注册并在你的程序中是可用的。InitInstance()函数中采用的ICC_WIN95_CLASSES其实是上面那些标志的组合。

***********************commctrl.h**********************

WINCOMMCTRLAPIvoidWINAPI InitCommonControls(void);

#if(_WIN32_IE >= 0x0300)
typedefstructtagINITCOMMONCONTROLSEX {
DWORD dwSize; //size of this structure 结构体的大小
DWORD dwICC; //标志位用来决定那些通用控件类将从DLL中加载,值可以是下面那些ICC_的组合
} INITCOMMONCONTROLSEX,*LPINITCOMMONCONTROLSEX;
#defineICC_LISTVIEW_CLASSES 0x00000001//listview, header
#defineICC_TREEVIEW_CLASSES 0x00000002//treeview, tooltips
#defineICC_BAR_CLASSES 0x00000004//toolbar, statusbar, trackbar, tooltips
#defineICC_TAB_CLASSES 0x00000008//tab, tooltips
#defineICC_UPDOWN_CLASS 0x00000010//updown
#defineICC_PROGRESS_CLASS 0x00000020//progress
#defineICC_HOTKEY_CLASS 0x00000040//hotkey
#defineICC_ANIMATE_CLASS 0x00000080//animate
#defineICC_WIN95_CLASSES 0x000000FF
#defineICC_DATE_CLASSES 0x00000100//month picker, date picker, time picker, updown
#defineICC_USEREX_CLASSES 0x00000200//comboex
#defineICC_COOL_CLASSES 0x00000400//rebar (coolbar) control
#if(_WIN32_IE >= 0x0400)
#defineICC_INTERNET_CLASSES 0x00000800
#defineICC_PAGESCROLLER_CLASS 0x00001000 //page scroller
#defineICC_NATIVEFNTCTL_CLASS 0x00002000 //native font control
#endif
#if(_WIN32_WINNT >= 0x501)
#defineICC_STANDARD_CLASSES 0x00004000
#defineICC_LINK_CLASS 0x00008000
#endif
WINCOMMCTRLAPI BOOL WINAPI InitCommonControlsEx(LPINITCOMMONCONTROLSEX);

#endif // _WIN32_IE >= 0x0300
**************************************************************************

ICC_BAR_CLASSES——注册工具栏、状态栏、Trackbar和Tooltip类。(Trackbar滑动条 ;Tooltip提示工具条 )
ICC_COOL_CLASSES——注册Rebar类。
ICC_DATE_CLASSES——注册Date and Time Picker类。
ICC_HOTKEY_CLASS——注册Hot Key类。
ICC_INTERNET_CLASSES——注册IP Address Picker类。
ICC_LISTVIEW_CLASSES——注册ListView和Header类。
ICC_PAGESCROLLER_CLASS——注册Pager类。
ICC_PROGRESS_CLASS——注册Progress Bar类。
ICC_TAB_CLASSES——注册Tab和Tooltip类。
ICC_TREEVIEW_CLASSES——注册TreeView和Tooltip类。
ICC_UPDOWN_CLASS——注册Up-Down类。
ICC_USEREX_CLASSES——注册ComboBoxEx类。
ICC_WIN95_CLASSES——注册InitCommonControls函数注册的所有类。

原文链接:
http://t.csdn.cn/fGFsi

37. GetPrivateProfileString()函数

利用 GetPrivateProfileString 读取配置文件 (.ini)

我们写的程序当中,总有一些配置信息需要保存下来,以便完成程序的功能,最简单的办法就是将这些信息写入INI文件中,程序初始化时再读入。

配置文件中经常用到ini文件,在VC中其函数分别为:
写入 .ini 文件:
bool WritePrivateProfileString(
LPCTSTR   lpAppName		//INI文件中的一个字段名
,LPCTSTR  lpKeyName		//lpAppName 下的一个键名,也就是里面具体的变量名
,LPCTSTR  lpString		//是键值,也就是变量的值,必须为LPCTSTR 或 CString类型
,LPCTSTR  lpFileName);	//完整的INI文件名

***********************************************************
读取 .ini 文件:
DWORD GetPrivateProfileString(
 LPCTSTR  lpAppName		//配置文件的section名
,LPCTSTR  lpKeyName		//配置文件的Key名
,LPCTSTR  lpDefaut		//如果ini文件中没有前两个参数指定的字段名或键名,则将此值赋给变量
,LPSTR    lpReturnedString	//接收INI文件中的值的CString对象,即接收缓冲区
,DWORD    nSize			//接收缓冲区的大小
,LPCTSTR  lpFileName);  //完整的ini文件名(完整路径)

GetPrivateProfileString()函数:
GetPrivateProfileString :为初始化文件中指定的条目取得字串,这个字串不区分大小写。

示例:
例如配置文件如下:
1  [测试section]
2  测试key = 测试value

具体用法:
CString csIniFile = _T("C:\\Users\\Administrator\\Desktop\\测试.ini")
TCHAR szValue[MAX_PATH+1] = _T("");
::GetPrivateProfileString(_T("测试section"), _T("测试key"), _T("Default"), szValue, MAX_PATH, csIniFile);
//szValue即为获得的值: 测试value

原文链接:
http://t.csdn.cn/QA7z1
*******************************************************************

读取整形值:
UINT GetPrivateProfileInt(
LPCTSTR   lpAppName
,LPCTSTR  lpKeyName
,INT      nDefault
,LPCTSTR  lpFileName);

示例如下
写入:
CString StrName,Strtemp;
int nAge;
StrName = “jacky”;
nAge = 13;
WritePrivateProfileString(“Student”, “Name”, StrName, “c:\setting.ini”);
结果:(INI文件中显示如下:)
[Student]
Name=jacky

读取:
CString SName;
GetPrivateProfileString(“Student”, “Name”, “DefaultName”, SName.GetBuffer(MAX_LENGTH), MAX_LENGTH, “c:\setting.ini”);
结果:SName =“jacky”;
这里需要注意点就是用完GetBuffer函数后一定要释放(用SName.ReleaseBuffer()函数),不然后面再用到SName的其他子函数就会失灵。

读整数比较简单,如下
int Result = GetPrivateProfileInt(“Student”,“nAge”,0,“c:\setting.ini”)返回值即为所读取的结果。
在GetPrivateProfileString最后一个参数是配置文件路径的参数,此路径只能是绝对路径,不能是相对路径,但现在我需要是我的exe文件能和我的配置文件在一起。因此我使用了GetCurrentDirectory函数。

原代码如下:
CString server_ip;
CString des="";
::GetCurrentDirectory(MAX_PATHLENGTH,des.GetBuffer(MAX_PATHLENGTH));
des.ReleaseBuffer();
des += "\config.ini";
GetPrivateProfileString(“PhoneDemo”, “Server_IP”, "", server_ip.GetBufferSetLength(15), 15, des);
server_ip.ReleaseBuffer();
注意:在这里使用CString变量时,在使用完GetBuffer后,紧接着一定要使用ReleaseBuffer()函数,才可以进行其他的诸如字符串+操作

更多说明:
获取路径:
GetCurrentDirectory只是返回当前进程的当前目录,而并不是进程的镜像文件(.exe)所在的目录
GetCurrentDirectory()适用于XP等系统,在WinCE上不能使用
GetModuleFileName()适用于WinCE2.0以后

原文链接:
http://t.csdn.cn/tQUQs

38. GetModuleFileName()函数

WINAPI DWORD GetModuleFileName(
	HMODULE hModule,		// 模块的句柄,或者设置为NULL 表示当前模块(获取当前程序可执行文件路径名)
	LPWSTR lpFilename,		// 保存路径的字符串缓冲区,得到的文件名
	DWORD nSize				// 接收路径的字符串缓冲区的大小,一般MAX_PATH 就可以
);

GetModuleFileName()得到模块的完整路径名。
GetModuleFileName 函数指定当前进程模块的路径.它仅仅操作当前进程下的模块.
如果想获取其他进程下的模块信息, 则需使用 GetModuleFileNameEx 函数

示例:
TCHAR strExePath[_MAX_PATH];
GetModuleFileName(NULL, strExePath, _MAX_PATH);
PathRemoveFileSpec(strExePath);    //去掉名称

如果当前执行程序的位置为 c:\test.exe, 
GetModuleFileName 获取的 strExePath 即为c:\test.exe,
通过去掉名称,函数最终获得的 strExePath 为 c: 
(注意 PathRemoveFileSpec 系统 API 函数调用时必须包含#include"Shlwapi.h"作为头文件) 

TCHAR strExePath[_MAX_PATH];
GetCurrentDirectory(_MAX_PATH, strExePath);  // 获取当前的系统目录,可能是 c: 也可能是其他值。

*********************************************
在开发工程中,往往需要知道当前程序本身所在目录。
一种方法是在程序安装的时候利用安装程序把文件路径写入注册表。在较大的程序中,这种方法比较常用
另一种,就是在程序得到路径。这样,程序随便移动到哪里,都可以得到正确的路径。这也是本文介绍的方法。
方法一:
CString strFullName = AfxGetApp() -> m_pszHelpFilePath; //得到的是:X:\XXXX\XXX.hlp
//解析路径,得到当前运行程序所在目录
char drive[_MAX_DRIVE];
char dir[_MAX_DIR];
_splitpath(strAppName,drive,dir,NULL,NULL);
CString strPath;
strPath.Format("%s%S",drive,dir);  //strPath 即为得到的当前运行程序所在目录

另外,AfxGetApp()->m_pszAppName 得到应用程序名称
AfxGetApp()->m_pszExeName 得到程序文件名,不包括扩展名

方法二:
TCHAR exeFullPath[MAX_PATH]; //MAX_PATH
GetMoudleFileName[NULL,exeFullPath,MAX_PATH]; //得到程序模块名称,全路径也就是当前运行程序的全路径
利用 方法一 的解析路径的方法,即可得到程序所在路径。

*********************************************

示例:
下面的一段代码主要是获得当前程序的运行目录(.exe)所在的目录
{
	CString strExePath;
	CString strPath;
	GetMoudleFileName(NULL,strPath.GetBufferSetLength(MAX_PATH + 1),MAX_PATH);
	AfxMessageBox(strPath);     //“d:\我的文档\Visual Studio 2005\Projects\test\Debug\test.exe”
	strPath.RealeaseBuffer();
	int pos = strPath.ReverseFind('\\');
	strExePath = strPath.Left(pos + 1);   
	AfxMessageBox(strExePath);	//"d:\我的文档\Visual Studio 2005\Projects\test\Debug\" 
}

MAX_PATH宏为编译器所支持的最长全路径名的长度,VC++6.0下为260。
注意点:
int pos=str.ReverseFind('\\'); //查找倒数最后一个“\”符号
str=str.Left(pos+1); //str只获取exe所在文件夹路径; str为:"E:\MyTest\Debug\"
reversefind()函数中使用的是单引号;
'\'即为''。

原文链接 1:
http://t.csdn.cn/tQUQs
原文链接 2:
https://blog.csdn.net/qq_38082146/article/details/118407885

39. GetCurrentDirectory() 函数

DWORD GetCurrentDirectory(
    DWORD nBufferLength,
    LPTSTR lpBuffer
);

The GetCurrentDirectory function retrieves the current directory for the current process.
GetCurrentDirectory()函数说明:
返回当前进程的当前目录,并不一定返回你的应用程序的目录。
如果你在应用程序中调用了打开文件对话框,你选择了一个文件,那么,这个文件所在的目录就成了当前进程的当前目录了。

Parameters (参数说明):
nBufferLength: 接收保存路径的字符串缓存长度, 缓存必须有一个保存结束的空字符的位置。
lpBuffer:指向接收字符串的缓存,收到的非空字符串指定了当前目录的绝对路径。

40. GetBuffer() 和 ReleaseBuffer() 函数

GetBuffer 和 ReleaseBuffer是一套需要配合使用的函数,与GetBufferSetLength相比,优点是如果分配的空间大于实际保存的字符串(0结尾),
ReleaseBuffer会把多余申请的空间释放, 归还给系统; 

GetBuffer 这个函数是为一个CString对象重新获取其内部字符缓冲区的指针;
但使用时需要注意以下问题:
如果要保存的字符串为 abc(0结尾),则 GetBuffer 参数应至少为3; 
如果要保存的内容不是以 0 结尾, 比如是读取文件数据,则GetBuffer参数如果大于文件长度时,ReleaseBuffer参数一定要为文件长度
(如果GetBuffer参数为文件长度的话不存在问题,ReleaseBuffer参数可以为默认-1)。

GetBuffer()主要作用是将字符串的缓冲区长度锁定,releaseBuffer则是解除锁定,使得CString对象在以后的代码中继续可以实现长度自适应增长的功能。

示例 1:
CString csStr;
LPTSTR lpsz = csStr.GetBuffer(100);
lpsz[0] = 'a';
lpsz[1] = 'b';
lpsz[2] = '/0';
csStr.ReleaseBuffer();
int nLength = csStr.GetLength();
// nLength 的值为 2 

GetBufferSetLength相对比较容易理解, 它申请一个指定长度的空间,即使里面最终保存的字符串长度小于申请的空间长度, 也不会将多余空间释放。

示例 2:
CString csStr;
LPTSTR lpsz = csStr.GetBufferSetLength(100);
lpsz[0] = 'a';
lpsz[1] = 'b';
lpsz[2] = '/0';
int nLength = csStr.GetLength();
// n的值还是为100 

示例 3:
CString str="abcdefg";
LPTSTR pstr=str.GetBuffer();
strcpy(pstr,"ab");
str.ReleaseBuffer();
此时调用str.GetLength()获取的值是2,正确无误。
但如果注释掉str.ReleaseBuffer()这一行,str.GetLength()获取的值则是7。
怎么会这样呢,我们来看看MFC中ReleaseBuffer的代码:
 void ReleaseBuffer( int nNewLength = -1 )
 {
      if( nNewLength == -1 )
      {
          nNewLength = StringLength( m_pszData );
      }
      SetLength( nNewLength );
 }
    很明显ReleaseBuffer只有一个作用,就是更新字符串的长度。CString内,GetLength获取字符串长度并不是动态计算的,而是在赋值操作后计算并保存在一个int变量内的,当通过GetBuffer直接修改CString时,那个int变量并不可能自动更新,于是便有了ReleaseBuffer。
    其实,计算长度还能用strlen(),这个就算不ReleaseBuffer也不会出错,但如果不ReleaseBuffer,在 += 这种赋值时字符串很可能会跟想要得到的不同。
————————————————---------------------------------------------------
原文链接:https://blog.csdn.net/shiwei0124/article/details/4579767

41. C++变量命名规范

变量命名规则是为了增强代码的可读性和容易维护性。以下为C++必须遵守的变量命名规则:
	1. 变量名只能是字母(A-Z,a-z)和数字(0-9)或者下划线(_)组成。
	2. 第一个字母必须是字母或者下划线开头。
	3. 不能使用C++关键字来命名变量,以免冲突。
	4. 变量名区分大小写。
变量命名规则:
一. 用最短字符表示最准确的意义。
二. 使用变量前缀
1. 类的成员变量以 m_ 开头,后面为变量,变量同时还要加前缀
	CString m_strName; // m_ 开头 + 类型前缀 + 名称
	
2. 全局变量一律以 g_ 开头,后面为变量,变量同时还有加前缀
	int g_ID;  // global
	
3. 定义结构体,保证C和C++兼容,采用typedef语句,并且结构体类型全部大写,以T_开头,指针形式以PT_开头。
	typedef struct tag TSTUDENT
   {
    int nId;
    CString strName;
   }STUDENT, *PSTUDENT;
   STUDENT tXiaoZhang;   //完整定义结构体

4. 变量由多个单词组成,则每个单词的首个字母大写。
  int nStudentID;
  CString strStudentName;

5. 定义一个类以C或者T做为类名前缀。
	class CMyListCtrl;
   class TMyListCtrl;

6. MFC控件绑定值类别或者控件类类别,需要以m_开头并且加前缀。
   CEdit m_EDT_strValue;    //Edit绑定控件类别
  CListBox m_LB_nName;    //ListBox
  CListCtrl m_LC_Name;     //ListCtrl;
  CComboBox m_CB_Name;   //ComboBox

7. 控件ID尽量简化并表明控件类型和意义。
  Button IDC_BTN_NAME;
  Edit IDC_EDT_NAME;
  ListBox IDC_LB_NAME;
  ListCtrl IDC_LC_NAME;
  
8. STL容器前缀
  vector vecValue;   //vector容器前缀:vec
  
9. 数组前缀
  int arrnNum[];     //数组前缀:arr
  CString arrstrName[]; //数组前缀+类型前缀+名称
  
10. 结构体前缀
   STUDENT tXiaoZhang; //结构体前缀:t
   
11. 字符型前缀
   char chChar;   //char前缀:ch

12. 字符串前缀
  char szPath;      //char字符串前缀:sz
  string strPath;     //string字符串前缀:str
  CString strPath;    //MFC CString类前缀:str
  
原文链接:
http://t.csdn.cn/fapt3

42. C++ atoi()函数用法

1. 功能
	atoi()函数将数字格式的字符串转换为整数类型。例如,将字符串“12345”转换成数字12345。
2. 格式	
	int atoi(const char* str)
	其中,参数 str 是要转换的字符串,返回值是转换后的整数
3. 注意事项
	3.1 关于参数的注意事项
	  atoi()函数的参数是要转换的字符串。该字符串的格式为
        [空格][符号][数字]
        其中,空格可以是键盘中的空格字符或者是Tab字符;符号可以是表示正数的“+”,也可以是表示负数的“-”;
        数字即为数字字符串。所以,atoi()函数参数可以是
        “ +123”
        “ -456”
        需要注意的是,空格和“+”可以省略。所以,atoi()函数参数还可以是
        “123”
        “-456”
     3.2 关于返回值的注意事项
        如果atoi()函数转换成功,则该函数的返回值是转换后的整型。
        如果atoi()函数转换失败,例如要转换的类型超过了int表示的范围,
        如果要转换的是正数,则返回INT_MAX(2147483647),
        如果要转换的是负数,则返回INT_MIN(-2147483648)。代码如下所示
            str1 = " 3336402735171707160320";
            value1 = atoi(str1);
            if (INT_MAX == value1)
            {
            printf("要转换的值超出了int的上边界。\n");
            }
            str2 = " -3336402735171707160320";
            value2 = atoi(str2);
            if (INT_MIN == value2)
            {
            printf("要转换的值超出了int的下边界。\n");
            }
       需要注意的是,atoi()函数在stdlib.h中定义,所以在使用atoi()函数时,需要包含该头文件。
       atoi()函数当读取到参数中的'\0'字符时,停止读取并返回。
      3.3 判断转换是否成功
      	虽然atoi()函数的参数和返回值中不包含转换是否成功的标志,
      	但是可以通过系统变量errno的值来判断转换是否成功。
      	相关链接:
        系统变量errno:errno 是记录系统的最后一次错误代码。代码是一个int型的值,在errno.h中定义。
        查看错误代码errno是调试程序的一个重要方法。
        在调用atoi()函数时,如果转换成功,则errno的值是0;
        如果遇到“3.2 关于返回值的注意事项”中提到的超出范围错误时,errno的值将会被设置为ERANGE。
        if (errno == ERANGE)
        {
            printf("要转换的数字超出int范围.\n");
        }
4. 宽字符的转换
	atoi()函数的宽字符串版本是_wtoi()函数。该函数的格式为
    int _wtoi(const wchar_t* str);
    其参数与返回值的含义与atoi()函数相似。

43. LPCTSTR 的含义

1. 定义文件中声明
	typedef LPCSTR PCTSTR, LPCTSTR, PCUTSTR, LPCUTSTR ;
2. 百度百科显示
	LPCTSTR用来表示你的字符是否使用UNICODE, 如果你的程序定义了UNICODE或者其他相关的宏,
	那么这个字符或者字符串将被作为UNICODE字符串,否则就是标准的ANSI字符串。
	L表示long指针 这是为了兼容Windows 3.1等16位操作系统遗留下来的,在win32中以及其他的32位操作系统中, 
	long指针和near指针及far修饰符都是为了兼容的作用。没有实际意义。
	P 表示这是一个指针
	C 表示是一个常量
	T 表示在Win32环境中, 有一个_T宏
	STR 表示这个变量是一个字符串
	
3. LPCTSTR 解释:
    表示指向字符/字符串的指针。WINDOWS 下面的程序设计可以支持MBCS和UNICODE两种编码的字符串,
    具体用那种就看你定义了MBCS宏还是UNICODE宏。
    MBCS宏对应的字符串指针 是char*也就是LPSTR,UNICODE对应的指针是unsigned short*也就是LPWSTR,
    为了写程序方便微软定义了类型LPTSTR,在MBCS下它就是char*,在UNICODE下它是unsigned char*,
    这样你就可以重定义一个宏进行不同字符集的转换了。
    LP:长指针(long pointer)。
    T: win32环境中有一个_T宏,用来标识字符是否采用Unicode编码(两字节表示一个字符),
    若程序中定义了Unicode,该字符/字符串被作为Unicode字符串,
    否则就是标准的ANSI(单字节表示一个字符)字符串。
    STR: 表示这个变量是一个字符串。
    C 表示一个常量,const
    
————————————————-------------------------------------------------------
原文链接:https://blog.csdn.net/sinat_26398509/article/details/123436129	

43.1 C++ 中 LPTSTR

LPTSTR:

如果定义了 UNICODE 宏,则 LPTSTR 被定义为 LPWSTR 。
	typedef  LPTSTR  LPWSTR ;
否则 LPTSTR 被定义为 LPSTR 。
	typedef  LPTSTR  LPSTR;

下面列出一些常用的typedefs:

类型 MBCS( Multi-Byte Character System ) 多字节字符集
	Unicode 统一的字符编码标准;采用双字节对字符进行编码
	
类型    		 MBCS    	   Unicode
WCHAR 		 wchar_t	     wchar_t

LPSTR  		char* 			  char*

LPCSTR 		const char*	   const char*

LPWSTR      wchar_t* 	    wchar_t*

LPCWSTR 	const wchar_t*   const wchar_t*

TCHAR       char            wchar_t

LPTSTR    TCHAR*(或char*)   TCHAR* (或wchar_t*)

LPCTSTR   const TCHAR*       const TCHAR*

所以结论,在VS2005系统中,为提高可移植性,定义字符串时用 TCHAR,转化为 UNICODE 时用 _T 而不用 L。

44. Unicode 数据类型

1. 什么是Unicode ?
	统一码(Unicode),也叫万国码、单一码,是计算机科学领域里的一项业界标准,包括字符集、编码方案等。Unicode是为了解决传统的字符编码方案的局限而产生的,它为每种语言中的每个字符设定了统一并且唯一的二进制编码,以满足跨语言、跨平台进行文本转换、处理的要求。1990年开始研发,1994年正式发布1.0版本,2021年9月14日发布14.0版本。统一码(Unicode)包含ASCII码,'\u0000'到'\u007F'对应全部128个ACSII字符。

     Unicode是一种字符编码方法,它占用两个字节(0000H—FFFFH),容纳65536个字符,这完全可以容纳全世界所有语言文字的编码。在Unicode里,所有的字符被一视同仁,汉字不再使用“两个扩展ASCII”,而是使用“1个Unicode”,也就是说,所有的文字都按一个字符来处理,它们都有一个唯一的Unicode码

BYTE data_utf8[] = {0xE6, 0xB1, 0x89, 0xE5, 0xAD, 0x97}; // UTF-8编码

WORD data_utf16[] = {0x6c49, 0x5b57}; // UTF-16编码

DWORD data_utf32[] = {0x6c49, 0x5b57}; // UTF-32编码

    Windows NT是使用Unicode进行开发的,因此整个系统都是基于Unicode的。如果调用一个API函数并给它传递一个ANSI(ASCII字符集以及由此派生并兼容的字符集,如:GB2312,通常称为ANSI字符集)字符串,那么系统首先要将字符串转换成Unicode,然后将Unicode字符串传递给操作系统。如果希望函数返回ANSI字符串,系统就会首先将Unicode字符串转换成ANSI字符串,然后将结果返回给您的应用程序。进行这些字符串的转换需要占用系统的时间和内存。如果用Unicode来开发应用程序,就能够使您的应用程序更加有效地运行。
    
2. Windows 定义的 Unicode 数据类型    
    WCHAR Unicode字符;
    PWSTR 指向Unicode字符串的指针;
    PCWSTR 指向一个恒定的Unicode字符串的指针;
    对应的 ANSI 数据类型为 CHAR,LPSTR 和 LPCSTR;
    ANSI/Unicode 通用数据类型为 TCHAR,PTSTR,LPCTSTR。
        
————————————————
原文链接:https://blog.csdn.net/sinat_26398509/article/details/123436129

45. GetCheckedRadioButton() 函数

CWnd::GetCheckedRadioButton

  函数功能:在给定的一组单选框ID中获得当前被选中的单选按钮的ID

  函数原型:int GetCheckedRadioButton( int nIDFirstButton, int nIDLastButton );

  返回值: 当有被选中的单选框时返回被选中的单选框的ID ,如果所给的组中都没被选中则返回0

  参数:

  nIDFirstButton 单选框组中第一个整形值的ID

  nIDLastButton 单选框组中最后一个整形值ID

  以下是MFC的实现,循环迭代,找出被check的button。有时我们可以通过查看MFC的实现来学习具体函数。

  int CWnd::GetCheckedRadioButton(int nIDFirstButton, int nIDLastButton) const
  {
  		for (int nID = nIDFirstButton; nID <= nIDLastButton; nID++)
  		{
  			if (IsDlgButtonChecked(nID))
  			return nID;   
  		}
  		return 0;   // invalid ID
  }
********************************************  
一组单选按钮,只有组属性的可以映射一个变量。
通过按 Ctrl + D 查看 Tab 键顺序可以快速确定 组外 的第一个控件。
  
————————————————-------------------------------------------
原文链接:
https://blog.csdn.net/jidongdong66/article/details/6333189

46. MFC中复选框check控件用法

动态设置复选框状态:
CButton *pBtn = (CButton*)GetDlgItem(IDC_CHECK); //获得复选框控件的句柄
int state = pBtn -> GetCheck(); // 判断复选框控件当前状态:勾选 或 不勾线
if(state == 0)
{
	MessageBox(_T("勾选"));
}
else
{
	MessageBox(_T("不勾选"));
}
设置选择状态:
((CButton*)GetDlgItem(IDC_CHECK)) ->SetCheck(1);  //设置复选框当前状态为勾选(0为未勾选)

参考链接:
http://t.csdn.cn/DemWl

47. MFC ListBox控件 滚动条 自动向下滚动

MFC ListBox控件 滚动条 自动向下滚动,显示出最后一行内容。
方法1:
	int nCount=m_List.AddString(str);
	m_List.SetTopIndex(nCount);
	
方法2:
	//ListBox 的Control型关联变量 m_List;
	int count = 0;
	count = m_List.GetCount ();
	m_List.SetCurSel (count - 1);

48. %.0f 的意思

%.0f 是输出 float 型或 double 型数据,按定点格式,小数点以下占0位。
也就是输出浮点数的整数部分,不输出小数点和小数点以下部分。小数部分 4 舍 5 入。
例如:
printf("%.0f %.0f ",123.5,123.4);
输出 124 123

49. CString 和 int 互换

CString str = _T("123");
int i = _ttoi(str); // Cstring 向 int 转换
///
int ---> CString
int i = 123;
CString str ;
str.Format(_T("%d"), i);// int 向Cstring 转换
vs 2010 试过了,可以转换。

50. 使用 CString 时注意 头文件

VS中使用CString
需要 包含头文件 #include<atlstr.h>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值