【mfc】利用到MFC菜单、字体对话框、OnSize函数实现简易记事本

经过了之前大量mfc已经明白了许多功能,但是之前的项目一直没有使用到mfc的菜单功能,菜单是Win32功能很常见的东西,这个也必须要懂。其实菜单的建立也很简单,配合之前的文件操作功能,已经能够把开始->附件->记事本,就是那个notepad.exe写出来了。

一、基本目标

首先,这个记事本能够最大化,最小化,里面的编辑框也能够跟住最大化最小化,就是记事本里面组件不会失真,这个也不是理所当然的时候,要对OnSize进行写作,否则里面的组件是不会跟着最大化的,这大概就是mfc比vb艰难的原因吧!

之后,这个记事本的窗体大小与平常Windows的窗口一样,能够自由调整大小,里面有相应的餐单。按帮助->关于,能够显示版权信息。其实这里已经把记事本模仿得很像了,要不是那个版权信息太丑的话~

点击“新建”按钮会弹出提示框,告诉用户如果继续执行这个命令,所有没有保存的信息会丢失,如果用户点“是”,则新建一个文件

之后是打开与保存、另存为功能,这里就不再介绍是什么样了,如下图,就是跟你平常用的记事本一模一样

最后是设置字体功能,能够设置记事本显示的字体,这与Windows里面的记事本是一模一样,毕竟记事本从头到尾都是一个纯文本的编辑器,设计字体只是设置其显示字体而已!用户选择相应的字体之后,记事本里面的字体就会以用户选择的字体显示。

二、准备过程

1、首先还是新建一个简单的mfc工程,里面什么都没有,我们之后再添加,主要是windows自带的东西太渣了,我们自己写出来更加漂亮。如果你连mfc的创建都不会,也没有关系,可以看我之前的文章

2、新建出来的工程与之前的《【mfc】用对话框的切换实现重新登录》(点击打开链接)一样,把确定按钮的OnOk函数注释掉,免得这个对话框一按回车就没有

3、之后把对话框里面的组件拉成如下图的形式,同时把各个组件的样式设置好:

4、之后,我们就开始为这个对话框建立菜单,如下图,为这个工程插入资源,如《【mfc】对于对话框程序的优化与为程序创建图标》(点击打开链接)中的图标一样,菜单也是资源的一种,只是菜单的编辑方式不同而已。

5、菜单的编辑如下图所示,里面还有“分隔符”选项,如果一点分隔符,组件中的所有东西都会变灰,系统自动识别这是“分隔符”而不是一个有功能的子菜单

6、长按一个子菜单拖拽可以改变子菜单的位置

7、按照上面的方式,建立如下图的菜单,然后切换的主对话框CxxDlg,其中xx为你的工程名,在这个主对话框中的样式添加菜单

8、之后,如下图为各个菜单中添加相应的类函数

9、把这个菜单的子菜单的消息映射函数与对话框关联起来,则设置其函数名,最后才能添加函数

10、对子菜单创建完消息映射函数则与组件的函数一样,能够在ClassView看到,当然,双击ClassView里面的函数也一样能够编辑,为所有子菜单,也就是那些"新建"、"打开"……添加完消息映射函数,我们则可以正式进行程序的写作。

三、各个子菜单的功能制作

虽然上面的准备功能很多,但是之后的函数就很简单,组件的布局完毕,之后写一些简短的函数就完成了,这就是微软旗下的编程的特点,它不像java中的Swing,单单是布局都要写一大堆代码。现在做微软编程的人看不起写Java的,说写一大段然后才能实现一个功能,写java看不起写微软的,说是拖控件的,谁也看不起谁。其实,无知者才是最可怕的,各有各特点,控件你不懂也不拖,代码你不懂你才觉得写一大段才能实现自己的功能,主要是自己废,不关人家编程语言的事情。你两方面都懂才是王道。好了,废话不多说了,回到这个功能里面来。

(一)编辑框的大小随同窗口的大小变化而变化

1、首先你要为这个主功能添加一个窗口消息处理函数,在里面找到WM_SIZE添加,这个与《【mfc】利用文件的读写,theApp全局变量来现实登录帐号管理系统》(点击打开链接)中添加OnInitDialog与OnDestory一样。不多说了,不明白可以翻翻我之前的日志。

2、之后对这个OnSize函数写上如下代码,这个函数主要是对用户调整窗口大小时做出的响应,包括最大化,但不包括最小化。最小化的功能系统自己就能够实现,但是它会把自身的窗口坐标变成负数,导致下面基于窗口尺寸的控件大小,出现负值,程序就崩溃。所以正确的做法是,一旦窗口的坐标变成负数,就不要执行这段代码。

void CNotepadDlg::OnSize(UINT nType, int cx, int cy)
{
	CDialog::OnSize(nType, cx, cy);
	//最小化以后,控件的窗口坐标值都会变成负数,再还原,此时,lastwindowrect为负,
	//需要你把下面的代码进行判断,否则程序会出错
	if(nType!=SIZE_MINIMIZED){
		CWnd *pWnd;
		//获取ID为i的空间的句柄
		pWnd = GetDlgItem(IDC_EDIT1);
		CRect rect;   //获取控件变化前的大小
		//判断是否为空,因为对话框创建时会调用此函数,而当时控件还未创建
		if(pWnd){
			pWnd->GetWindowRect(&rect);
			ScreenToClient(&rect);//将控件大小转换为在对话框中的区域坐标
			//cx/m_rect.Width()为对话框在横向的变化比例
			//cy/m_rect.Height()为对话框在纵向的变化比例
			rect.left=rect.left*cx/rect.Width();//调整控件大小
			rect.right=rect.right*cx/rect.Width();
			rect.top=rect.top*cy/rect.Height();
			rect.bottom=rect.bottom*cy/rect.Height();
			pWnd->MoveWindow(rect);//设置控件大小
		}
		GetClientRect(&rect);//将变化后的对话框大小替换旧大小
	}
}

(二)版权信息

这个就不多说,这个与《【mfc】利用文件的读写,theApp全局变量来现实登录帐号管理系统》(点击打开链接)中也多个对话框中切换一模一样,先画好CopyrightDlg这个对话框,再为这个对话框新建类向导,然后因为CopyrightDlg除了显示与自带的关闭功能以外没有任何功能,CopyrightDlg完全不用写东西,只需要在主函数里面的“帮助”->“关于...”类函数,引入头文件,写入打开“关于……”对话框的代码即可

#include "CopyrightDlg.h"

void CNotepadDlg::OnCopyright()
{
	// TODO: Add your command handler code here
	CCopyrightDlg dlg;
	dlg.DoModal();

}

之后的代码都涉及到文件操作,所以首先在notepadDlg.cpp这个文件的开头,也就是包含一堆子菜单这个cpp的开头,引入CString filename;这个全局变量,就在#endif这行系统自带的代码的下方,让"新建"、“打开”、"保存"等命名共享这个文件变量,因为这里仅有一个对话框,所以也没必要大题小做地,如《【mfc】使用系统文件对话框打开文件与保存文件、利用StdAfx.h设置全局变量》(点击打开链接),把变量写到StdAfx.h里面,又不用多个对话框共享这个变量。

(三)文件->新建

代码如下,很简单:

void CNotepadDlg::OnFileNew()
{
	// TODO: Add your command handler code here
	if(IDNO==MessageBox("所有没有保存的信息,将会丢失,是否继续?","记事本",MB_YESNO))
		return;
	SetDlgItemText(IDC_EDIT1,"");
	SetWindowText("记事本");
	filename="";

}

首先弹窗提示用户是否继续,然后把文本框、标题栏、操作的文件路径清空即可。

(四)文件->打开

这个有点难,虽然基本原理与《【mfc】使用系统文件对话框打开文件与保存文件、利用StdAfx.h设置全局变量》(点击打开链接)一样,但是这里是对编辑框进行操作,而不是列表空间,因此,你首先要把文件的所有内容读入一个字符数组里面,再读到编辑框里面。注意打开文件之后,把标题栏、当前控制文件的路径更新一样。

void CNotepadDlg::OnFileOpen()
{
	if(IDNO==MessageBox("所有没有保存的信息,将会丢失,是否继续?","记事本",MB_YESNO))
		return;
	CFileDialog dlg(TRUE,"txt","",OFN_HIDEREADONLY,"文本文件(*.txt)|*.txt||");
	if(IDCANCEL==dlg.DoModal()){
		return;
	}
	filename=dlg.GetPathName();
	SetWindowText(filename);
	CFile file;
	if(!file.Open(filename,CFile::modeRead|CFile::shareDenyNone)){
		AfxMessageBox("打开文件失败");
		return;
	}
	//读取要打开文件的大小
	//然后根据打开文件的大小创建一个相应大小的字符数组
	CFileStatus stat;
	file.GetStatus(stat);
	//+1是因为我们要对这个字符数组,后补\0
	char *pText=new char[stat.m_size+1];
	//file.Read的返回值是读到的文件大小
	int nRet=file.Read(pText,stat.m_size);
	pText[nRet]='\0';
	//把读出来的东西放到文本框里面,然后删除这个字符串数组
	SetDlgItemText(IDC_EDIT1,pText);
	delete []pText;
	file.Close();
}

(五)文件->保存

首先读取当前控制的文件路径,也就是定义在开头的那个filename,如果读不了,证明用户还没有打开文件,就选择“保存”按钮,直接拖去“另存为”的处理,使用一个CString作为编辑框的内容与文件的过渡,把这个CString的内容写入文件,就完事了。

void CNotepadDlg::OnFileSave()
{
	// TODO: Add your command handler code here
	CFile file;
	if(!file.Open(filename,CFile::modeCreate|CFile::modeWrite)){
		CNotepadDlg::OnFileSaveas();
		return;
	}
	CString string;
	GetDlgItemText(IDC_EDIT1,string);
	file.Write(string,string.GetLength());
	file.Close();
}

(六)文件->另存为

你自然要弹出一个“另存为”的CFileDialog给用户爽吧,然后这个通过CFileDialog,如《【mfc】使用系统文件对话框打开文件与保存文件、利用StdAfx.h设置全局变量》(点击打开链接)一样获取到文件路径,然如上面“保存”那样对文件进行写入操作。注意这里还要更新一下标题栏。

void CNotepadDlg::OnFileSaveas()
{
	// TODO: Add your command handler code here
	CFileDialog dlg(FALSE,"txt","",OFN_OVERWRITEPROMPT,"文本文件(*.txt)|*.txt||");
	if(IDCANCEL==dlg.DoModal()){
		return;
	}
	CFile file;
	filename=dlg.GetPathName();
	if(!file.Open(filename,CFile::modeCreate|CFile::modeWrite)){
		AfxMessageBox("保存文件失败");
		return;
	}
	CString string;
	GetDlgItemText(IDC_EDIT1,string);
	file.Write(string,string.GetLength());
	file.Close();
	SetWindowText(filename);
}

(七)格式->字体

主要是设置显示字体,为了使设置的字体的辉煌仅仅停留在OnFontSet这个函数那样段,这里,你还要在开头像写入CString filename;那样写入CFont font;之后,则如下面的代码所示

void CNotepadDlg::OnFontSet()
{
	// TODO: Add your command handler code here

	//lf是指向字体的指针
	LOGFONT lf={0};
	//如果现在已经存在字体了,那么获取当前字体的信息
	if(font.GetSafeHandle()){
		font.GetLogFont(&lf);
	}
	//字体设置需要到系统的字体编辑对话框,里面的参数是lf所指向的字体
	//一打开字体编辑对话框自动选中这个字体
	CFontDialog dlg(&lf);
	if(IDCANCEL==dlg.DoModal()){
		return;
	}
	//这样就能获取到,用户选中的字体保存到名为font的CFont对象中
	//其中CFont font;已经在本文件的文件开头就定义成本cpp的全局变量了
	dlg.GetCurrentFont(&lf);
	font.DeleteObject();
	font.CreateFontIndirect(&lf);
	//取出操作文字输入框的句柄m_edit,以后m_edit就是操作这个对话框的句柄
	CEdit* m_edit=(CEdit*)GetDlgItem(IDC_EDIT1);
	m_edit->SetFont(&font);
}

四、总结与展望

至此,整个高仿记事本就制作完毕了。当然,还有“编辑”中的撤销功能,这个估计要设计一个链表记录用户的操作,剪切、复制、粘贴设计MFC中的对剪切板ClipBoard.exe的操作,估计应该有自带的函数,还没有研究。查找与替换与CFileDialog、CFontDialog一样,有自带的对话框,利用这个对话框获取到用户输入的内容,把当前编辑框的文本拿个CString存起来,再进行C语言那样的对CString进行遍历,查找与替换的操作……

时间: 2024-12-28 20:33:14

【mfc】利用到MFC菜单、字体对话框、OnSize函数实现简易记事本的相关文章

(转载)VS2010/MFC编程入门之十八(对话框:字体对话框)

鸡啄米在上一节为大家讲解了文件对话框的使用,本节则主要介绍字体对话框如何应用. 字体对话框的作用是用来选择字体.我们也经常能够见到.MFC使用CFontDialog类封装了字体对话框的所有操作.字体对话框也是一种模态对话框. CFontDialog类的构造函数 我们先来了解CFontDialog类.它的常用构造函数原型如下: CFontDialog(   LPLOGFONT lplfInitial = NULL,   DWORD dwFlags = CF_EFFECTS | CF_SCREENF

VS2010/MFC对话框:字体对话框

字体对话框) 在上一节为大家讲解了文件对话框的使用,本节则主要介绍字体对话框如何应用. 字体对话框的作用是用来选择字体.我们也经常能够见到.MFC使用CFontDialog类封装了字体对话框的所有操作.字体对话框也是一种模态对话框. CFontDialog类的构造函数 我们先来了解CFontDialog类.它的常用构造函数原型如下: CFontDialog(   LPLOGFONT lplfInitial = NULL,   DWORD dwFlags = CF_EFFECTS | CF_SCR

MFC编程入门之十八(对话框:字体对话框)

在上一节为大家讲解了文件对话框的使用,本节则主要介绍字体对话框如何应用. 字体对话框的作用是用来选择字体.我们也经常能够见到.MFC使用CFontDialog类封装了字体对话框的所有操作.字体对话框也是一种模态对话框. CFontDialog类的构造函数 我们先来了解CFontDialog类.它的常用构造函数原型如下: CFontDialog( LPLOGFONT lplfInitial = NULL. DWORD dwFlags = CF_EFFECTS | CF_SCREENFONTS, C

(转载)VS2010/MFC编程入门之十三(对话框:属性页对话框及相关类的介绍)

前面讲了模态对话框和非模态对话框,本节开始鸡啄米讲一种特殊的对话框--属性页对话框.另外,本套教程所讲大部分对VC++各个版本均可适用或者稍作修改即可,但考虑到终究还是基于VS2010版本的,所以将<VC++/MFC编程入门>改为<VS2010/MFC编程入门>. 属性页对话框的分类 属性页对话框想必大家并不陌生,XP系统中桌面右键点属性,弹出的就是属性页对话框,它通过标签切换各个页面.另外,我们在创建MFC工程时使用的向导对话框也属于属性页对话框,它通过点击"Next&

2015.3.3 VC++6制作MFC dll并在其中使用对话框、引入类的操作

上例建立的dll为非MFC的,不能使用MFC框架,如CString.对话框等类型,使用起来有一定限制.可以建立MFC的Dll来改进.建立MFC Dll的方法: 1.在VC6中新建工程时选择:MFC AppWizard(dll) 2.保持默认的 Regular Dll using shared MFC DLL完成. 3.此时生成的App具有.h .cpp两个文件,与上面只有.cpp有所不同 4.相同的是在.cpp文件中 添加函数 extern "C" __declspec(dllexpo

MFC 利用checkbox 做成切换开关按钮

我们在做MFC程序时候经常会一个切换式的按钮,之前我的做法是利用buttion类的一个SetState()函数,但是返现效果不佳.而且容易出现点1按钮,焦点跑到另外一个按钮上去了  .后来看到别人一个程序.我发现他的切换效果做的很好 ,经过看代码发现,他用的控件根本不是buttion控件而是check box 控件.我就很奇怪,如何将check box变成了一个按钮的,经查看代码发现,原来是他将控件的属性------push lisk  (我的翻译是按下去像  纯字面理解)设置成true  如图

VS2010修改菜单字体

用过VS2005,VS2008,再用VS2010的会发现,VS2010中MFC向导生成的单文档/多文档菜单字体与VS2005和VS2008不同:VS2005和VS2008中看起来很清晰,但是在VS2010版本中字体就很小,不清楚,下面提供解决方案: 在CMainFrame类的OnCreate函数中,系统生成的代码之后添加如下代码即可 int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct) { #pragma region 修改菜单字体 LO

QT学习 之 对话框 (四) 字体对话框、消息对话框、文件对话框、进程对话框(超详细中文注释)

QMessageBox类: 含有Question消息框.Information消息框.Warning消息框和Critical消息框等 通常有两种方式可以来创建标准消息对话框: 一种是采用“基于属性”的API,一种是使用QMessageBox的静态方法. 后者书写容易,但缺少灵活性,针对用户给出的提示的信息不够丰富,并且不能自定义消息对话框里面的按钮提示信息.因此推荐第一种写法. [cpp] view plaincopy <span style="font-size:18px;"&

MFC中的Invalidate、OnDraw、OnPaint函数的作用

MFC中的Invalidate.OnDraw.OnPaint函数的作用 CWnd::Invalidate voidInvalidate( BOOL bErase = TRUE ); 该函数的作用是使 整个窗口客户区无效.窗口的客户区无效意味着需要重绘,例如,如果一个被其它窗口遮住的窗口变成了前台窗口,那么原来被遮住的部分就是无效的,需要重绘. 这时Windows会在应用程序的消息队列中放置WM_PAINT消息.MFC为窗口类提供了WM_PAINT的消息处理函数 OnPaint,OnPaint负责