IDR_MAINFRAME字符串的使用

zyrr159487 2010-11-16 04:16:09
文档打开和保存,还有另存为时的文件类型过滤可以通过IDR_MAINFRAME这个字符串来设置,
问题1:要如何设置打开多种格式的过滤器。
问题2:可否打开时可选的格式是那几个,保存和另存为又是另外几个。

...全文
507 32 打赏 收藏 转发到动态 举报
写回复
用AI写文章
32 条回复
切换为时间正序
请发表友善的回复…
发表回复
DowTowne 2011-12-15
  • 打赏
  • 举报
回复
大家说的很对,我也找不到设置多个文件类型过滤的方法
zyrr159487 2010-11-19
  • 打赏
  • 举报
回复
有没有高手能再给点建议呢,这样不行吧
zyrr159487 2010-11-19
  • 打赏
  • 举报
回复
有没有高手能再给点建议呢,这样不行吧
zyrr159487 2010-11-19
  • 打赏
  • 举报
回复
[Quote=引用 30 楼 visualwind 的回复:]
LZ还是不要死扣这个问题,因为微软给的示例都是单个过滤条件的。多个的话还是自己用CFileDialog写吧。
[/Quote]
我想也是,所以我最后的解决方法是在重载了保存和打开文档的函数,在里面用CFileDialog自己定义了另存为对话框
visualwind 2010-11-19
  • 打赏
  • 举报
回复
LZ还是不要死扣这个问题,因为微软给的示例都是单个过滤条件的。多个的话还是自己用CFileDialog写吧。
visualwind 2010-11-19
  • 打赏
  • 举报
回复
我感觉IDR_MAINFRAME可能不能做多个过滤条件,因为过滤条件和后缀是分开的部分,如果写多个过滤条件的话容易造成不匹配。
zyrr159487 2010-11-18
  • 打赏
  • 举报
回复
从异常中跳转到它对IDR_MAINFRAME字符串处理的地方,发现它应该是只对;起作用
AFX_STATIC void AFXAPI _AfxAppendFilterSuffix(CString& filter, OPENFILENAME& ofn,
CDocTemplate* pTemplate, CString* pstrDefaultExt)
{
ENSURE_VALID(pTemplate);
ASSERT_KINDOF(CDocTemplate, pTemplate);

CString strFilterExt, strFilterName;
if (pTemplate->GetDocString(strFilterExt, CDocTemplate::filterExt) &&
!strFilterExt.IsEmpty() &&
pTemplate->GetDocString(strFilterName, CDocTemplate::filterName) &&
!strFilterName.IsEmpty())
{
if (pstrDefaultExt != NULL)
pstrDefaultExt->Empty();

// add to filter
filter += strFilterName;
ASSERT(!filter.IsEmpty()); // must have a file type name
filter += (TCHAR)'\0'; // next string please

int iStart = 0;
do
{
CString strExtension = strFilterExt.Tokenize( _T( ";" ), iStart );

if (iStart != -1)
{
// a file based document template - add to filter list

// If you hit the following ASSERT, your document template
// string is formatted incorrectly. The section of your
// document template string that specifies the allowable file
// extensions should be formatted as follows:
// .<ext1>;.<ext2>;.<ext3>
// Extensions may contain wildcards (e.g. '?', '*'), but must
// begin with a '.' and be separated from one another by a ';'.
// Example:
// .jpg;.jpeg
ASSERT(strExtension[0] == '.');
if ((pstrDefaultExt != NULL) && pstrDefaultExt->IsEmpty())
{
// set the default extension
*pstrDefaultExt = strExtension.Mid( 1 ); // skip the '.'
ofn.lpstrDefExt = const_cast< LPTSTR >((LPCTSTR)(*pstrDefaultExt));
ofn.nFilterIndex = ofn.nMaxCustFilter + 1; // 1 based number
}

filter += (TCHAR)'*';
filter += strExtension;
filter += (TCHAR)';'; // Always append a ';'. The last ';' will get replaced with a '\0' later.
}
} while (iStart != -1);

filter.SetAt( filter.GetLength()-1, '\0' );; // Replace the last ';' with a '\0'
ofn.nMaxCustFilter++;
}
}
zyrr159487 2010-11-18
  • 打赏
  • 举报
回复
[Quote=引用 25 楼 fangongdalu7148 的回复:]
mark下。
[/Quote]
3Q,总算没有沉掉
zyrr159487 2010-11-17
  • 打赏
  • 举报
回复
[Quote=引用 11 楼 visualeleven 的回复:]
引用 10 楼 zyrr159487 的回复:
引用 9 楼 visualwind 的回复:
引用 7 楼 zyrr159487 的回复:
我在网上看到的也是这个,跟孙鑫老师书里讲的是一样的。没有说到如何再加入一个类型该怎么写,意思就是除了"所有文件(*.*)","Text File(*.txt)",如果我还想再加个“Dwg File(*.dwg)"该怎么加呢


这个和CFileDi……
[/Quote]
试了下载onSaveDocument()
下自己使用cFileDialog来生成另存为对话框,但是如何屏蔽文档自己的另存为对话框呢,出现的情况就是单击菜单中的另存为,先出现了原先的另存为对话框,然后是我自己定义的
visualwind 2010-11-17
  • 打赏
  • 举报
回复
[Quote=引用 10 楼 zyrr159487 的回复:]

引用 9 楼 visualwind 的回复:
引用 7 楼 zyrr159487 的回复:
我在网上看到的也是这个,跟孙鑫老师书里讲的是一样的。没有说到如何再加入一个类型该怎么写,意思就是除了"所有文件(*.*)","Text File(*.txt)",如果我还想再加个“Dwg File(*.dwg)"该怎么加呢


这个和CFileDialog的过滤字符串的语法是一样的,查一下楼上的……
[/Quote]

Text Files(*.txt)\0*.txt\0All Files(*.*)\0*.*\0
拼对了没有,\0不能多不能少
mayudong1 2010-11-17
  • 打赏
  • 举报
回复
[Quote=引用 10 楼 zyrr159487 的回复:]
引用 9 楼 visualwind 的回复:
引用 7 楼 zyrr159487 的回复:
我在网上看到的也是这个,跟孙鑫老师书里讲的是一样的。没有说到如何再加入一个类型该怎么写,意思就是除了"所有文件(*.*)","Text File(*.txt)",如果我还想再加个“Dwg File(*.dwg)"该怎么加呢


这个和CFileDialog的过滤字符串的语法是一样的,查一下楼上的文……
[/Quote]

我也试了半天,什么都不好使
怀疑是不是就不支持这个呢,这个是文档类中的东西,MFC会不会就认为每个文档就对应一种文件类型来做的呢
Eleven 2010-11-17
  • 打赏
  • 举报
回复
[Quote=引用 10 楼 zyrr159487 的回复:]
引用 9 楼 visualwind 的回复:
引用 7 楼 zyrr159487 的回复:
我在网上看到的也是这个,跟孙鑫老师书里讲的是一样的。没有说到如何再加入一个类型该怎么写,意思就是除了"所有文件(*.*)","Text File(*.txt)",如果我还想再加个“Dwg File(*.dwg)"该怎么加呢


这个和CFileDialog的过滤字符串的语法是一样的,查一下楼上的文……
[/Quote]
自己实现保存文件机制
zyrr159487 2010-11-17
  • 打赏
  • 举报
回复
[Quote=引用 9 楼 visualwind 的回复:]
引用 7 楼 zyrr159487 的回复:
我在网上看到的也是这个,跟孙鑫老师书里讲的是一样的。没有说到如何再加入一个类型该怎么写,意思就是除了"所有文件(*.*)","Text File(*.txt)",如果我还想再加个“Dwg File(*.dwg)"该怎么加呢


这个和CFileDialog的过滤字符串的语法是一样的,查一下楼上的文章或者百度一下,灵活一点。
[/Quote]
CFileDialog的写法是在字符串间加入\0来添加新的类型,我试了下不行
visualwind 2010-11-17
  • 打赏
  • 举报
回复
[Quote=引用 7 楼 zyrr159487 的回复:]
我在网上看到的也是这个,跟孙鑫老师书里讲的是一样的。没有说到如何再加入一个类型该怎么写,意思就是除了"所有文件(*.*)","Text File(*.txt)",如果我还想再加个“Dwg File(*.dwg)"该怎么加呢
[/Quote]

这个和CFileDialog的过滤字符串的语法是一样的,查一下楼上的文章或者百度一下,灵活一点。
zyrr159487 2010-11-17
  • 打赏
  • 举报
回复
[Quote=引用 6 楼 visualwind 的回复:]
引用 5 楼 zyrr159487 的回复:
因为是修改他人的代码,之前用的写法是用这个字符串来作为过滤器,所以我想尽量能延续这个思路来修改

引自网上:

IDR_MAINFRAME字符串资源中包含7个子串,分别以\n结束,即如下格式:
<windowTitle>\n<docName>\n<fileNewName>\n<filterName>\n<filterExt>\n<regFi……
[/Quote]
我在网上看到的也是这个,跟孙鑫老师书里讲的是一样的。没有说到如何再加入一个类型该怎么写,意思就是除了"所有文件(*.*)","Text File(*.txt)",如果我还想再加个“Dwg File(*.dwg)"该怎么加呢
visualwind 2010-11-17
  • 打赏
  • 举报
回复
[Quote=引用 18 楼 xiaohuh421 的回复:]

1.设置多个过虑器
只要在CFileDiag的构造函数的第5个参数加入过虑串就可以,格式如下.
LPCTSTR strFilter=TEXT("文本文件(*.txt)|*.txt|图片文件|*.bmp;*.jpg;*.gif;*.tif|所有文件(*.*)|*.*||");//最后要以"||"结束.
调用的时候
CFileDialog dlg(TRUE,NULL,NULL,OFN_H……
[/Quote]

'|'在CFileDialog创建的时候内部会转成\0,否则CString遇到\0就结束了,后面的传不进去。



[Quote=引用 17 楼 zyrr159487 的回复:]

引用 16 楼 visualwind 的回复:
引用 15 楼 zyrr159487 的回复:
如果在IDR_MAINFRAME中这么写,它会将\0作为字符串结束符,所以从第一个\0之后的字符就都无法保存了


把\0换成\n

这样改的话,一点打开就出现异常了,直接崩溃掉。
它这里总共7个字符串,各有含义,如果加入两个\n就有9条了,肯定出错
[/Quote]

用'|'或','分割,就类似于("文本文件(*.txt)|*.txt|图片文件|*.bmp;*.jpg;*.gif;*.tif|所有文件(*.*)|*.*||
zyrr159487 2010-11-17
  • 打赏
  • 举报
回复
自己顶下先
zyrr159487 2010-11-17
  • 打赏
  • 举报
回复
[Quote=引用 18 楼 xiaohuh421 的回复:]
1.设置多个过虑器
只要在CFileDiag的构造函数的第5个参数加入过虑串就可以,格式如下.
LPCTSTR strFilter=TEXT("文本文件(*.txt)|*.txt|图片文件|*.bmp;*.jpg;*.gif;*.tif|所有文件(*.*)|*.*||");//最后要以"||"结束.
调用的时候
CFileDialog dlg(TRUE,NULL,NULL,OFN_HI……
[/Quote]
1 确实可以通过CFileDialog 来打开文档,我是加在onOpenDocument里的,文档类还是会先调用自己那个,然后再调用我写的这个
2 修改第5个参数,怎么修改才能加多个文档呢
xiaohuh421 2010-11-17
  • 打赏
  • 举报
回复
1.设置多个过虑器
只要在CFileDiag的构造函数的第5个参数加入过虑串就可以,格式如下.
LPCTSTR strFilter=TEXT("文本文件(*.txt)|*.txt|图片文件|*.bmp;*.jpg;*.gif;*.tif|所有文件(*.*)|*.*||");//最后要以"||"结束.
调用的时候
CFileDialog dlg(TRUE,NULL,NULL,OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT,strFilter);
dlg.DoModal();

这时候你就可以看到"文件类型"列表框中就有 "文本文件(*.txt)" "图片文件" "所有文件(*.*)"这三个选项.

2.至于打开对话框和保存对话框,你可以在构造函数里面修改第5个参数传入的串, 就可以设置不同类型的文件了

2.
zyrr159487 2010-11-17
  • 打赏
  • 举报
回复
[Quote=引用 16 楼 visualwind 的回复:]
引用 15 楼 zyrr159487 的回复:
如果在IDR_MAINFRAME中这么写,它会将\0作为字符串结束符,所以从第一个\0之后的字符就都无法保存了


把\0换成\n
[/Quote]
这样改的话,一点打开就出现异常了,直接崩溃掉。
它这里总共7个字符串,各有含义,如果加入两个\n就有9条了,肯定出错
加载更多回复(8)
支持wce下实现ping指令 // PingExampleDlg.cpp : implementation file // #include "stdafx.h" #include "PingExample.h" #include "PingExampleDlg.h" #include #include #include #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif ///////////////////////////////////////////////////////////////////////////// // CPingExampleDlg dialog CPingExampleDlg::CPingExampleDlg(CWnd* pParent /*=NULL*/) : CDialog(CPingExampleDlg::IDD, pParent) { //{{AFX_DATA_INIT(CPingExampleDlg) m_ipAddr = _T(""); //}}AFX_DATA_INIT // Note that LoadIcon does not require a subsequent DestroyIcon in Win32 m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME); } void CPingExampleDlg::DoDataExchange(CDataExchange* pDX) { CDialog::DoDataExchange(pDX); //{{AFX_DATA_MAP(CPingExampleDlg) DDX_Control(pDX, IDC_LIST_RECV, m_lstRecv); DDX_Text(pDX, IDC_EDIT_IP, m_ipAddr); //}}AFX_DATA_MAP } BEGIN_MESSAGE_MAP(CPingExampleDlg, CDialog) //{{AFX_MSG_MAP(CPingExampleDlg) ON_BN_CLICKED(IDC_BTNCLEAR, OnBtnclear) ON_BN_CLICKED(IDC_BTNPING, OnBtnping) //}}AFX_MSG_MAP END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // CPingExampleDlg message handlers BOOL CPingExampleDlg::OnInitDialog() { CDialog::OnInitDialog(); // Set the icon for this dialog. The framework does this automatically // when the application's main window is not a dialog SetIcon(m_hIcon, TRUE); // Set big icon SetIcon(m_hIcon, FALSE); // Set small icon CenterWindow(GetDesktopWindow()); // center to the hpc screen // TODO: Add extra initialization here return TRUE; // return TRUE unless you set the focus to a control } /* *函数介绍:CE下Ping方法 *入口参数:cIPAddr : IP地址 pWnd : CWnd对象,用于指定窗体对象 *出口参数:pListBox : CListBox对象,用于显示Ping信息 *返回值:(无) */ void CEPing(CString cIPAddr,CListBox * pListBox,CWnd * pWnd) { WSAData wsaData; //初始化Socket动态链接库 if (WSAStartup(MAKEWORD(1, 1), &wsaData) != 0) { return ; } /*将IP地址转换成单字节*/ char szDestIPAddr[255]; ZeroMemory(szDestIPAddr,255); WideCharToMultiByte(CP_ACP,WC_COMPOSITECHECK ,cIPAddr.GetBuffer(cIPAddr.GetLength()),cIPAddr.GetLength() ,szDestIPAddr,cIPAddr.GetLength(),NULL,NULL); IPAddr ipAddr; //将目标字符串IP地址转换成IPAddr结构 ipAddr = inet_addr(szDestIPAddr); if (ipAddr == INADDR_NONE) { AfxMessageBox(_T("地址无效")); return ; } // 打开ping服务 HANDLE hIP = IcmpCreateFile(); if (hIP == INVALID_HANDLE_VALUE) { AfxMessageBox(_T("不能打开Ping服务")); return ; } // 构造ping数据包 char acPingBuffer[64]; memset(acPingBuffer, '*', sizeof(acPingBuffer)); PICMP_ECHO_REPLY pIpe = (PICMP_ECHO_REPLY)GlobalAlloc( GMEM_FIXED | GMEM_ZEROINIT, sizeof(ICMP_ECHO_REPLY) + sizeof(acPingBuffer)); if (pIpe == 0) { AfxMessageBox(_T("分配ping包缓冲区失败")); return ; } CString m_recv; // 发送ping数据包 m_recv = "ping "+cIPAddr+" with 64 Bytes"; pListBox->AddString(m_recv); for (int i=0;i<4;i++) { //发送ping服务包,等待接收时间为1秒 DWORD dwStatus = IcmpSendEcho(hIP,ipAddr, acPingBuffer, sizeof(acPingBuffer), NULL, pIpe, sizeof(ICMP_ECHO_REPLY) + sizeof(acPingBuffer), 1000); //当dwStatus不等于0,代表接收到回应 if (dwStatus != 0) { m_recv.Format(_T("Reply From %d.%d.%d.%d :bytes=%d time=%d TTL") ,int(LOBYTE(LOWORD(pIpe->Address))) ,int(HIBYTE(LOWORD(pIpe->Address))) ,int(LOBYTE(HIWORD(pIpe->Address))) ,int(HIBYTE(HIWORD(pIpe->Address))) ,int(pIpe->DataSize) ,int(pIpe->RoundTripTime) ,int(pIpe->Options.Ttl)); pListBox->AddString(m_recv); Sleep(500); } else { pListBox->AddString(_T("Error obtaining info from ping packet.")); } pWnd->UpdateWindow(); } //释放已分配的内存 GlobalFree(pIpe); //关闭Ping服务 IcmpCloseHandle(hIP); //释放Socket资源 WSACleanup(); } void CPingExampleDlg::OnBtnclear() { int nCount = m_lstRecv.GetCount(); for (int i=0;i < nCount;i++) { m_lstRecv.DeleteString(0); } } void CPingExampleDlg::OnBtnping() { UpdateData(TRUE); CEPing(m_ipAddr,&m_lstRecv,this); UpdateWindow(); }
学生成绩管理 ============================================ MICROSOFT 基础类库: StudentScore 项目概述 ============================================ 应用程序向导已为您创建了此 StudentScore 应用程序。此应用程序 不仅介绍了使用 Microsoft 基础类的基本知识, 而且是编写应用程序的起点。 此文件包含组成 StudentScore 应用程序的每个文件的内容摘要。 StudentScore.vcproj 这是使用“应用程序向导”生成的 VC++ 项目的主项目文件。 它包含有关生成文件的 Visual C++ 版本的信息,以及 有关用“应用程序向导”所选择的平台、配置和 项目功能的信息。 StudentScore.h 这是应用程序的主头文件。 它包含其他 项目特定的头文件(包括 Resource.h),并声明 CStudentScoreApp 应用程序类。 StudentScore.cpp 这是包含应用程序 类 CStudentScoreApp 的主应用程序源文件。 StudentScore.rc 这是程序使用的所有 Microsoft Windows 资源 的列表。 它包含存储在 RES 子目录中 的图标、位图和光标。 可直接在 Microsoft Visual C++ 中编辑此文件。 项目资源包含在 2052 中。 resStudentScore.ico 这是一个图标文件,用作应用程序的图标。 此 图标包含在主资源文件 StudentScore.rc 中。 resStudentScore.rc2 此文件包含不由 Microsoft Visual C++ 编辑的资源。 应将所有不能由 资源编辑器编辑的资源放在此文件中。 StudentScore.reg 这是一个 .REG 文件示例,向您显示 框架将为您设置的注册设置类型。 可以将它用作 .REG 文件,以与应用程序一起使用,或干脆删除它而依赖 默认的 RegisterShellFileTypes 注册。 ///////////////////////////////////////////////////////// 对于主框架窗口: 项目将包含标准的 MFC 界面。 MainFrm.h, MainFrm.cpp 这些文件包含框架类 CMainFrame,该类派生自 CMDIFrameWnd 并控制所有的 MDI 框架功能。 resToolbar.bmp 此位图文件用于创建工具栏的平铺图像。 初始工具栏和状态栏在 CMainFrame 类中构造。 使用资源编辑器编辑此工具栏位图,并 更新 StudentScore.rc 中的 IDR_MAINFRAME TOOLBAR 数组以添加 工具栏按钮。 ////////////////////////////////////////////////////////// 对于子框架窗口: ChildFrm.h、ChildFrm.cpp 这些文件定义和实现 CChildFrame 类,此类 支持 MDI 应用程序中的子窗口。 ////////////////////////////////////////////////////////// 应用程序向导将创建一种文档类型和一个视图: StudentScoreDoc.h、StudentScoreDoc.cpp - 文档 这些文件包含 CStudentScoreDoc 类。 编辑这些文件 以添加特殊的文档数据并实现文件的保存和加载 (通过 CStudentScoreDoc::Serialize)。 此文档将具有下列字符串: 文件扩展名: sc 文件类型 ID: StudentScore.Document 主框架标题: StudentScore 文档类型名称: StudentScore 筛选器名称: StudentScore Files (*.sc) 文件的新简称: StudentScore 文件类型全称: StudentScore.Document StudentScoreView.h、StudentScoreView.cpp - 文档视图 这些文件包含 CStudentScoreView 类。 CStudentScoreView 对象用于查看 CStudentScoreDoc 对象。 resStudentScoreDoc.ico 这是一个图标文件,用作 CStudentScoreDoc 类 MDI 子窗口的图标。 此图标包含在主 资源文件 StudentScore.rc 中。 ///////////////////////////////////////////////////////// 其他功能: ActiveX 控件 应用程序支持使用 ActiveX 控件。 ///////////////////////////////////////////////////////// 其他标准文件: StdAfx.h、StdAfx.cpp 这些文件用于生成名为 StudentScore.pch 的预编译头文件 (PCH) 和名为 StdAfx.obj 的预编译类型文件。 Resource.h 这是标准头文件,它定义新资源 ID。 Microsoft Visual C++ 将读取并更新此文件。 ///////////////////////////////////////////////////////// 其他说明: 应用程序向导使用“TODO:” 来指示 应添加或自定义的源代码部分。 如果应用程序在共享 DLL 中使用 MFC,且应用程序使用的语言不是 操作系统的当前语言,则需要从 Microsoft Visual C++ 光盘上 WinSystem 目录下将相应的本地化资源 MFC70XXX.DLL 复制到计算机的 system 或 system32 目录下, 并将其重命名为 MFCLOC.DLL。 (“XXX”代表 语言缩写。 例如,MFC70DEU.DLL 包含翻译成 德语的资源。) 如果不这样做,应用程序的某些 UI 元素 将保留为操作系统的语言。 //////////////////////////////////////////////////////////
MFC计算器课程设计报告 地信091 指导老师: 2010.11.15 一.题目:利用MFC框架编写简易计算器 要求使用MFC框架在Visual Studio 6.0环境下编写一个简易的计算器,支持任意位数的加减乘数,正负转换,并且实现BackSpace CE C功能。 二.设计过程 1. Windows消息处理机制的理解 首先编写程序需要对Windows程序的消息处理机制(Message Handle)有个比较清晰的了解。Windows的程序都是通过消息来传送数据,有不需要用户参与的系统消息,比如异常处理等。还有用户消息,比如鼠标的单击,双击,键盘的键入等。 2. 界面的设计 仿照Windows附件里面的计算器,在资源视图中画好界面,如图: 主要使用到Layout菜单中的Align功能对各个按钮进行对其,使界面更加整洁。拖出的控件有上面的一个Edit控件用于显示数字,Button控件用于处理鼠标的消息。 3. 建立的变量,控件的命名,对应的消息处理函数对应表 ID CAPTION Message Handler IDD_CALC_DIALOG 简易计算器 1.0 Beta1版 N/A IDC_NUM0 0 OnNum0 IDC_NUM1 1 OnNum1 IDC_NUM2 2 OnNum2 IDC_NUM3 3 OnNum3 IDC_NUM4 4 OnNum4 IDC_NUM5 5 OnNum5 IDC_NUM6 6 OnNum6 IDC_NUM7 7 OnNum7 IDC_NUM8 8 OnNum8 IDC_NUM9 9 OnNum9 IDC_NEG +/- OnNeg IDC_PT . OnPt IDC_DIV / OnDiv IDC_MUL * OnMul IDC_MIN - OnMin IDC_ADD + OnAdd IDC_BACKSPACE BACK OnBackspace IDC_CE CE OnCe IDC_CLEAR C OnClear IDC_EQU = OnEqu IDC_DIS N/A N/A OnCal(double num) 变量定义: double poz; //保存小数点的位置,初始化为1,表示poz-1个小数点。 double m_Dis; //Edit控件上需要显示的数字 BOOL point_flag; //小数点表示位,判定是否是小数,是小数为1,不是小数为0。 double numfirst; //保存计算过程中的前一个数字, double numsecond;//保存计算过程中的第二个数字 char op;//记录当前的计算符号,可以为’+’,’-’,’*’,’/’,’=’,’c’,’n’ 变量初始化: poz=1; m_Dis = 0.0; numfirst=0; numsecond=0; op=0; 4. 设计思路 a) 首先考虑对所有按键分为两类,数字类和符号类,0,1,2,3,4,5,6,7,8,9为数字类,+,-,*,/,=为符号类。数字在计算的过程中最多需要保存两个,所以定义了两个double型变量numfirst和numsecond来进行存储。符号需要一个char op来存储。 b) 然后考虑在计算的过程中,numfirst和numsecond的存储状态有三种,一种是numfirst==0 && numsecond==0 也就是程序刚开始运行还没有开始录入数字的状态。二种是numfirst!=0 && numsecond==0 也就是第一个数字已经录入,符号也已经录入时候把m_Dis的值直接赋值给numfirst,第三种是numfirst!=0 &&numsecond!=0,表示可以通过op来把两数合并为一个数。 c) 考虑到该计算器支持连续的计算,比如3.33+1.33*88/96= ?。所以必须在点符号Button也要计算出之前的结果,通过判断op,来计算,把两个数字合并为一个数字,方便下一次运算,功能近似于点=,所以把=也划分到符号类。 d) 因为数字全部使用的是double,键入的数字必须通过一定的处理达到累加的效果,加上小数和整数的处理差异性大,所以分别用point_flag来判断,分别出来小数和整数。 5. 成员函数及其释义 因为对OnNum0()到OnNum9()的处理函数差异仅在一个数字上,可以通过调用一个共同的函数OnCal(double num)来简化源代码长度,增加模块性。 void CCalcDlg::OnCal(double num) { //分三种状态来处理 if(numfirst!=0 && numsecond!=0) { if(point_flag==TRUE) //判定为小数 { poz*=0.1; //小数进位 m_Dis=m_Dis+poz*num;//递增 UpdateData(false); //把结果从内存传递到屏幕 } else { m_Dis=m_Dis*10+num; UpdateData(false); } } if(numfirst!=0 && numsecond==0) { if(point_flag==TRUE) { poz*=0.1; m_Dis=m_Dis+poz*num; UpdateData(false); } else//判定为整数 { m_Dis=m_Dis*10+num;//递增 UpdateData(false); } } if(numfirst==0 && numsecond==0) { if(point_flag==TRUE) { poz*=0.1; m_Dis=m_Dis+poz*num; UpdateData(false); } else { m_Dis=m_Dis*10+num; UpdateData(false); } } } 以OnAdd()为例子讲解符号的处理函数,函数的功能是先判定之前按下字符时op的值,更具op的值来进行相应的运算。 void CCalcDlg::OnAdd() { //根据numfirst和numsecond和op的值分为5种状态。 if(numfirst!=0 && numsecond==0&&op=='+') { numsecond=m_Dis; numfirst=numfirst+numsecond; //之前按的是加把两个数赋值到前一个数 m_Dis=numfirst;//赋值给屏幕 numsecond=0; //从新赋值为0,清空,不影响下一次判断 UpdateData(FALSE); m_Dis=0; //屏幕的值同时清空 } if(numfirst!=0 && numsecond==0&&op=='-') { numsecond=m_Dis; numfirst=numfirst-numsecond; m_Dis=numfirst; numsecond=0; UpdateData(FALSE); m_Dis=0; } if(numfirst!=0 && numsecond==0&&op=='*') { numsecond=m_Dis; numfirst=numfirst*numsecond; m_Dis=numfirst; numsecond=0; UpdateData(FALSE); m_Dis=0; } if(numfirst!=0 && numsecond==0&&op=='/') { numsecond=m_Dis; numfirst=numfirst/numsecond; m_Dis=numfirst; numsecond=0; UpdateData(FALSE); m_Dis=0; } if(numfirst==0 && numsecond==0) { //该状态为程序启动还没有开始录入输入的状态 numfirst=m_Dis; //屏幕的值赋值到numfirst UpdateData(FALSE); m_Dis=0; } op='+'; //最后记录最后一个操作是+ poz=1;//小数点位置归位 point_flag=FALSE;//默认小数点标志为整数,也就是0,也就是FALSE } “+/-“按钮的处理函数 void CCalcDlg::OnNeg() { m_Dis=-m_Dis;//换个符号,其他都一样 UpdateData(FALSE); poz=1; point_flag=FALSE; } ‘.’按钮的处理函数 void CCalcDlg::OnPt() { point_flag=TRUE; //把标志位改为“小数点”状态 } “Backspace”按钮的处理 void CCalcDlg::OnBackspace() { //主要通过_gcvt()和strtod()函数进行字符串和浮点数之间的转换 char buffer[30]; //定义个装字符的数组 _gcvt(m_Dis,sizeof(m_Dis),buffer); //把m_Dis存的数字转换为string for(int i=0;i<30;i++) { if(buffer[i]=='.'&& buffer[i+1]==0)//判断是否为整数 { point_flag=FALSE; //标志位设置为“整数位” break; } } if(point_flag==TRUE) //如果是小数 { for(int j=0;jmessage,pMsg->wParam,pMsg->lParam); return CDialog::PreTranslateMessage(pMsg); } // CalculatorDlg.cpp : implementation file // #include "stdafx.h" #include "Calculator.h" #include "CalculatorDlg.h" #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif ///////////////////////////////////////////////////////////////////////////// // CAboutDlg dialog used for App About class CAboutDlg : public CDialog { public: CAboutDlg(); // Dialog Data //{{AFX_DATA(CAboutDlg) enum { IDD = IDD_ABOUTBOX }; //}}AFX_DATA // ClassWizard generated virtual function overrides //{{AFX_VIRTUAL(CAboutDlg) protected: virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support //}}AFX_VIRTUAL // Implementation protected: //{{AFX_MSG(CAboutDlg) //}}AFX_MSG DECLARE_MESSAGE_MAP() }; CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD) { //{{AFX_DATA_INIT(CAboutDlg) //}}AFX_DATA_INIT } void CAboutDlg::DoDataExchange(CDataExchange* pDX) { CDialog::DoDataExchange(pDX); //{{AFX_DATA_MAP(CAboutDlg) //}}AFX_DATA_MAP } BEGIN_MESSAGE_MAP(CAboutDlg, CDialog) //{{AFX_MSG_MAP(CAboutDlg) // No message handlers //}}AFX_MSG_MAP END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // CCalculatorDlg dialog CCalculatorDlg::CCalculatorDlg(CWnd* pParent /*=NULL*/) : CDialog(CCalculatorDlg::IDD, pParent) { //{{AFX_DATA_INIT(CCalculatorDlg) poz=1; numfirst=0; numsecond=0; op=0; m_Dis = 0.0; // num=0; //}}AFX_DATA_INIT // Note that LoadIcon does not require a subsequent DestroyIcon in Win32 m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME); } void CCalculatorDlg::DoDataExchange(CDataExchange* pDX) { CDialog::DoDataExchange(pDX); //{{AFX_DATA_MAP(CCalculatorDlg) DDX_Text(pDX, IDC_EDIT, m_Dis); //}}AFX_DATA_MAP } BEGIN_MESSAGE_MAP(CCalculatorDlg, CDialog) //{{AFX_MSG_MAP(CCalculatorDlg) ON_WM_SYSCOMMAND() ON_WM_PAINT() ON_WM_QUERYDRAGICON() ON_BN_CLICKED(IDC_NUM0, OnNum0) ON_BN_CLICKED(IDC_NUM1, OnNum1) ON_BN_CLICKED(IDC_NUM2, OnNum2) ON_BN_CLICKED(IDC_NUM3, OnNum3) ON_BN_CLICKED(IDC_NUM4, OnNum4) ON_BN_CLICKED(IDC_NUM5, OnNum5) ON_BN_CLICKED(IDC_NUM6, OnNum6) ON_BN_CLICKED(IDC_NUM7, OnNum7) ON_BN_CLICKED(IDC_NUM8, OnNum8) ON_BN_CLICKED(IDC_NUM9, OnNum9) ON_BN_CLICKED(IDC_ADD, OnAdd) ON_BN_CLICKED(IDC_NEG, OnNeg) ON_BN_CLICKED(IDC_PT, OnPt) ON_BN_CLICKED(IDC_BACKSPACE, OnBackspace) ON_BN_CLICKED(IDC_CE, OnCe) ON_BN_CLICKED(IDC_CLEAR, OnClear) ON_BN_CLICKED(IDC_MIN, OnMin) ON_BN_CLICKED(IDC_MUL, OnMul) ON_BN_CLICKED(IDC_DIV, OnDiv) ON_BN_CLICKED(IDC_EOU, OnEou) //}}AFX_MSG_MAP END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // CCalculatorDlg message handlers BOOL CCalculatorDlg::OnInitDialog() { CDialog::OnInitDialog(); // Add "About..." menu item to system menu. // IDM_ABOUTBOX must be in the system command range. ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX); ASSERT(IDM_ABOUTBOX AppendMenu(MF_SEPARATOR); pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu); } } // Set the icon for this dialog. The framework does this automatically // when the application's main window is not a dialog SetIcon(m_hIcon, TRUE); // Set big icon SetIcon(m_hIcon, FALSE); // Set small icon // TODO: Add extra initialization here return TRUE; // return TRUE unless you set the focus to a control } void CCalculatorDlg::OnSysCommand(UINT nID, LPARAM lParam) { if ((nID & 0xFFF0) == IDM_ABOUTBOX) { CAboutDlg dlgAbout; dlgAbout.DoModal(); } else { CDialog::OnSysCommand(nID, lParam); } } // If you add a minimize button to your dialog, you will need the code below // to draw the icon. For MFC applications using the document/view model, // this is automatically done for you by the framework. void CCalculatorDlg::OnPaint() { if (IsIconic()) { CPaintDC dc(this); // device context for painting SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0); // Center icon in client rectangle int cxIcon = GetSystemMetrics(SM_CXICON); int cyIcon = GetSystemMetrics(SM_CYICON); CRect rect; GetClientRect(&rect); int x = (rect.Width() - cxIcon + 1) / 2; int y = (rect.Height() - cyIcon + 1) / 2; // Draw the icon dc.DrawIcon(x, y, m_hIcon); } else { CDialog::OnPaint(); } } // The system calls this to obtain the cursor to display while the user drags // the minimized window. HCURSOR CCalculatorDlg::OnQueryDragIcon() { return (HCURSOR) m_hIcon; } void CCalculatorDlg::OnCal(double num) {//分三种状态来处理 if(numfirst!=0 && numsecond!=0) { if(point_flag==TRUE) //判定为小数 { poz*=0.1; //小数进位 m_Dis=m_Dis+poz*num;//递增 UpdateData(false); //把结果从内存传递到屏幕 } else { m_Dis=m_Dis*10+num; UpdateData(false); } } if(numfirst!=0 && numsecond==0) { if(point_flag==TRUE) { poz*=0.1; m_Dis=m_Dis+poz*num; UpdateData(false); } else//判定为整数 { m_Dis=m_Dis*10+num;//递增 UpdateData(false); } } if(numfirst==0 && numsecond==0) { if(point_flag==TRUE) { poz*=0.1; m_Dis=m_Dis+poz*num; UpdateData(false); } else { m_Dis=m_Dis*10+num; UpdateData(false); } } } void CCalculatorDlg::OnNum0() { // TODO: Add your control notification handler code here OnCal(0); } void CCalculatorDlg::OnNum1() { // TODO: Add your control notification handler code here OnCal(1); } void CCalculatorDlg::OnNum2() { // TODO: Add your control notification handler code here OnCal(2); } void CCalculatorDlg::OnNum3() { // TODO: Add your control notification handler code here OnCal(3); } void CCalculatorDlg::OnNum4() { // TODO: Add your control notification handler code here OnCal(4); } void CCalculatorDlg::OnNum5() { // TODO: Add your control notification handler code here OnCal(5); } void CCalculatorDlg::OnNum6() { // TODO: Add your control notification handler code here OnCal(6); } void CCalculatorDlg::OnNum7() { // TODO: Add your control notification handler code here OnCal(7); } void CCalculatorDlg::OnNum8() { // TODO: Add your control notification handler code here OnCal(8); } void CCalculatorDlg::OnNum9() { // TODO: Add your control notification handler code here OnCal(9); } void CCalculatorDlg::OnAdd() { // TODO: Add your control notification handler code here { //根据numfirst和numsecond和op的值分为5种状态。 if(numfirst!=0 && numsecond==0&&op=='+') { numsecond=m_Dis; numfirst=numfirst+numsecond; //之前按的是加把两个数赋值到前一个数 m_Dis=numfirst;//赋值给屏幕 numsecond=0; //从新赋值为0,清空,不影响下一次判断 UpdateData(FALSE); m_Dis=0; //屏幕的值同时清空 } if(numfirst!=0 && numsecond==0&&op=='-') { numsecond=m_Dis; numfirst=numfirst-numsecond; m_Dis=numfirst; numsecond=0; UpdateData(FALSE); m_Dis=0; } if(numfirst!=0 && numsecond==0&&op=='*') { numsecond=m_Dis; numfirst=numfirst*numsecond; m_Dis=numfirst; numsecond=0; UpdateData(FALSE); m_Dis=0; } if(numfirst!=0 && numsecond==0&&op=='/') { numsecond=m_Dis; numfirst=numfirst/numsecond; m_Dis=numfirst; numsecond=0; UpdateData(FALSE); m_Dis=0; } if(numfirst==0 && numsecond==0) { //该状态为程序启动还没有开始录入输入的状态 numfirst=m_Dis; //屏幕的值赋值到numfirst UpdateData(FALSE); m_Dis=0; } op='+'; //最后记录最后一个操作是+ poz=1;//小数点位置归位 point_flag=FALSE;//默认小数点标志为整数,也就是0,也就是FALSE } } void CCalculatorDlg::OnNeg() { // TODO: Add your control notification handler code here m_Dis=-m_Dis;//换个符号,其他都一样 UpdateData(FALSE); poz=1; point_flag=FALSE; } void CCalculatorDlg::OnPt() { // TODO: Add your control notification handler code here point_flag=TRUE; //把标志位改为"小数点"状态 } void CCalculatorDlg::OnBackspace() { // TODO: Add your control notification handler code here //主要通过_gcvt()和strtod()函数进行字符串和浮点数之间的转换 char buffer[30]; //定义个装字符的数组 _gcvt(m_Dis,sizeof(m_Dis),buffer); //把m_Dis存的数字转换为string for(int i=0;i<30;i++) { if(buffer[i]=='.'&& buffer[i+1]==0)//判断是否为整数 { point_flag=FALSE; //标志位设置为"整数位" break; } } if(point_flag==TRUE) //如果是小数 { for(int j=0;j<30;j++) { if(buffer[j]==0) { buffer[j-1]=0; //把'\0'之前的字符赋值为'\0',就相当于剪掉最后一位 break; } } } else //如果是整数 { buffer[i-1]=0; //剪掉'.'之前那位 } m_Dis=strtod(buffer,NULL);//再用strtod弄成浮点数 UpdateData(FALSE); poz=1; } void CCalculatorDlg::OnCe() { // TODO: Add your control notification handler code here if(numfirst!=0 && numsecond==0)//CE只能修改第二个数字 { m_Dis=0; //把屏幕的值赋值为0 UpdateData(FALSE);//并显示出来 } } void CCalculatorDlg::OnClear() { // TODO: Add your control notification handler code here op=NULL; //清空符号 numfirst=0;//清空第一个数字 numsecond=0;//清空第二个数字 point_flag=FALSE;//改为默认整数位 poz=1;//小数点归位 m_Dis=0; UpdateData(FALSE); //屏幕显示归0 } void CCalculatorDlg::OnMin() { // TODO: Add your control notification handler code here { //根据numfirst和numsecond和op的值分为5种状态。 if(numfirst!=0 && numsecond==0&&op=='+') { numsecond=m_Dis; numfirst=numfirst+numsecond; //之前按的是加把两个数赋值到前一个数 m_Dis=numfirst;//赋值给屏幕 numsecond=0; //从新赋值为0,清空,不影响下一次判断 UpdateData(FALSE); m_Dis=0; //屏幕的值同时清空 } if(numfirst!=0 && numsecond==0&&op=='-') { numsecond=m_Dis; numfirst=numfirst-numsecond; m_Dis=numfirst; numsecond=0; UpdateData(FALSE); m_Dis=0; } if(numfirst!=0 && numsecond==0&&op=='*') { numsecond=m_Dis; numfirst=numfirst*numsecond; m_Dis=numfirst; numsecond=0; UpdateData(FALSE); m_Dis=0; } if(numfirst!=0 && numsecond==0&&op=='/') { numsecond=m_Dis; numfirst=numfirst/numsecond; m_Dis=numfirst; numsecond=0; UpdateData(FALSE); m_Dis=0; } if(numfirst==0 && numsecond==0) { //该状态为程序启动还没有开始录入输入的状态 numfirst=m_Dis; //屏幕的值赋值到numfirst UpdateData(FALSE); m_Dis=0; } op='-'; //最后记录最后一个操作是+ poz=1;//小数点位置归位 point_flag=FALSE;//默认小数点标志为整数,也就是0,也就是FALSE } } void CCalculatorDlg::OnMul() { // TODO: Add your control notification handler code here { //根据numfirst和numsecond和op的值分为5种状态。 if(numfirst!=0 && numsecond==0&&op=='+') { numsecond=m_Dis; numfirst=numfirst+numsecond; //之前按的是加把两个数赋值到前一个数 m_Dis=numfirst;//赋值给屏幕 numsecond=0; //从新赋值为0,清空,不影响下一次判断 UpdateData(FALSE); m_Dis=0; //屏幕的值同时清空 } if(numfirst!=0 && numsecond==0&&op=='-') { numsecond=m_Dis; numfirst=numfirst-numsecond; m_Dis=numfirst; numsecond=0; UpdateData(FALSE); m_Dis=0; } if(numfirst!=0 && numsecond==0&&op=='*') { numsecond=m_Dis; numfirst=numfirst*numsecond; m_Dis=numfirst; numsecond=0; UpdateData(FALSE); m_Dis=0; } if(numfirst!=0 && numsecond==0&&op=='/') { numsecond=m_Dis; numfirst=numfirst/numsecond; m_Dis=numfirst; numsecond=0; UpdateData(FALSE); m_Dis=0; } if(numfirst==0 && numsecond==0) { //该状态为程序启动还没有开始录入输入的状态 numfirst=m_Dis; //屏幕的值赋值到numfirst UpdateData(FALSE); m_Dis=0; } op='*'; //最后记录最后一个操作是+ poz=1;//小数点位置归位 point_flag=FALSE;//默认小数点标志为整数,也就是0,也就是FALSE } } void CCalculatorDlg::OnDiv() { // TODO: Add your control notification handler code here { //根据numfirst和numsecond和op的值分为5种状态。 if(numfirst!=0 && numsecond==0&&op=='+') { numsecond=m_Dis; numfirst=numfirst+numsecond; //之前按的是加把两个数赋值到前一个数 m_Dis=numfirst;//赋值给屏幕 numsecond=0; //从新赋值为0,清空,不影响下一次判断 UpdateData(FALSE); m_Dis=0; //屏幕的值同时清空 } if(numfirst!=0 && numsecond==0&&op=='-') { numsecond=m_Dis; numfirst=numfirst-numsecond; m_Dis=numfirst; numsecond=0; UpdateData(FALSE); m_Dis=0; } if(numfirst!=0 && numsecond==0&&op=='*') { numsecond=m_Dis; numfirst=numfirst*numsecond; m_Dis=numfirst; numsecond=0; UpdateData(FALSE); m_Dis=0; } if(numfirst!=0 && numsecond==0&&op=='/') { numsecond=m_Dis; numfirst=numfirst/numsecond; m_Dis=numfirst; numsecond=0; UpdateData(FALSE); m_Dis=0; } if(numfirst==0 && numsecond==0) { //该状态为程序启动还没有开始录入输入的状态 numfirst=m_Dis; //屏幕的值赋值到numfirst UpdateData(FALSE); m_Dis=0; } op='/'; //最后记录最后一个操作是+ poz=1;//小数点位置归位 point_flag=FALSE;//默认小数点标志为整数,也就是0,也就是FALSE } } void CCalculatorDlg::OnEou() { // TODO: Add your control notification handler code here { //根据numfirst和numsecond和op的值分为5种状态。 if(numfirst!=0 && numsecond==0&&op=='+') { numsecond=m_Dis; numfirst=numfirst+numsecond; //之前按的是加把两个数赋值到前一个数 m_Dis=numfirst;//赋值给屏幕 numsecond=0; //从新赋值为0,清空,不影响下一次判断 UpdateData(FALSE); m_Dis=0; //屏幕的值同时清空 } if(numfirst!=0 && numsecond==0&&op=='-') { numsecond=m_Dis; numfirst=numfirst-numsecond; m_Dis=numfirst; numsecond=0; UpdateData(FALSE); m_Dis=0; } if(numfirst!=0 && numsecond==0&&op=='*') { numsecond=m_Dis; numfirst=numfirst*numsecond; m_Dis=numfirst; numsecond=0; UpdateData(FALSE); m_Dis=0; } if(numfirst!=0 && numsecond==0&&op=='/') { numsecond=m_Dis; numfirst=numfirst/numsecond; m_Dis=numfirst; numsecond=0; UpdateData(FALSE); m_Dis=0; } if(numfirst==0 && numsecond==0) { //该状态为程序启动还没有开始录入输入的状态 numfirst=m_Dis; //屏幕的值赋值到numfirst UpdateData(FALSE); m_Dis=0; } op='='; //最后记录最后一个操作是+ poz=1;//小数点位置归位 point_flag=FALSE;//默认小数点标志为整数,也就是0,也就是FALSE } } 总结: 本次MFC计算器的制作,学习到了MFC基本的编程方法,增加了小组开发的团结协作能力。对OOP编程的理解进一步加深。但是程序仍然没存在一定的问题,比如除数不能为0的Exception handle,符号键多次点击结果混乱。由于时间仓促,如果有更多的时间,必定这些问题会迎刃而解。通过这次课程设计,以后Windows 应用程序势必会轻车熟路。

15,979

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 界面
社区管理员
  • 界面
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧