Visual C++程序设计 # 机试操作复习 (MFC机试)

  • 考试环境: VS2010 (适用于NCEPU)
  • 个人总结,禁止转载
  • 猜测考试题型为:单文档里嵌入对话框

编译异常处理方法

如果确认代码无误,选择重新生成解决方案,尝试能不能解决问题

1 基于对话框的应用程序

基础知识

  • 学会修改控件的ID
  • 学会拖拽控件
  • 学会修改Static Text\Button\对话框的标题(Caption)
  • 学会给控件添加Value型变量[ctrl+shift+x]
    Visual C++程序设计 # 机试操作复习 (MFC机试)_第1张图片
  • 学会设置Edit的只读(readonly)
  • 学会添加Button的click事件 [双击Button]
  • 数据交换机制DDX/数据验证机制DDV
  • 修改对话框内控件的Tab顺序[Ctrl+D]
  • 关闭对话框
	this->OnOK();
	this->OnCancel();

或者修改ID为IDOK, IDCANCEL

  • 弹出对话框
    前置操作:#include对话框的头文件
CdialogPracticeDlg dlg;
INT_PTR nResponse = dlg.DoModal();
if (nResponse == IDOK)
{
	// TODO: 在此放置处理何时用
	//  “确定”来关闭对话框的代码
}
else if (nResponse == IDCANCEL)
{
	// TODO: 在此放置处理何时用
	//  “取消”来关闭对话框的代码
}

注意:这段代码必须要会,如果记不住:在XXXX(工程名).cpp里面的InitInstance函数有类似的代码,可以仿写

  • afxMessageBox
  • 添加处理程序(以及错误添加的删除)
    Visual C++程序设计 # 机试操作复习 (MFC机试)_第2张图片
  • 新建对话框
    Visual C++程序设计 # 机试操作复习 (MFC机试)_第3张图片
    然后双击或者右键添加类
    Visual C++程序设计 # 机试操作复习 (MFC机试)_第4张图片
#include "TipDlg.h"

void CdialogPracticeDlg::OnBnClickedButtonCalc()
{
	CTipDlg dlg;
	INT_PTR nResponse = dlg.DoModal();
	if(nResponse == IDCANCEL)return;

	UpdateData(TRUE);
	m_dAns = m_dOp1 + m_dOp2;
	UpdateData(FALSE);
}
  • CString类的基本操作要会 文末拓展阅读材料
    CString变为int:int y = _ttoi(year);
  • 组合框(ComboBox)的基本使用和一些属性
    data 写数据

    Visual C++程序设计 # 机试操作复习 (MFC机试)_第5张图片
    droplist不能修改,只能选,dropdown可以改


    一般把sort关掉
    关联变量:int 表示第几个被选中(从0开始,记得设置sort为false,-1表示默认不选中)
    m_nChoose是关联的int变量,sort设置为false,数据是+;-;*;/;
void CdialogPracticeDlg::OnBnClickedButtonCalc()
{	
	UpdateData(TRUE);
	if(m_nChoose == -1){
		AfxMessageBox(_T("please choosee an operator"));
		return;
	}
	switch(m_nChoose){
	case 0:
		m_dAns = m_dOp1 + m_dOp2;
		break;
	case 1:
		m_dAns = m_dOp1 - m_dOp2;
		break;
	case 2:
		m_dAns = m_dOp1 * m_dOp2;
		break;
	case 3:
		if( fabs(m_dOp2) < 1e-10 ){
			AfxMessageBox(_T("Error"));
			return;
		}
		m_dAns = m_dOp1 / m_dOp2;
		break;
	}
	UpdateData(FALSE);
}

给combo box关联 control类型变量m_comboCalc
定位到:CXXXXXXXDlg::OnInitDialog(),在TODO后面添加代码
Visual C++程序设计 # 机试操作复习 (MFC机试)_第6张图片

m_comboCalc.AddString(_T(“+"));动态添加选项

动态添加:

for(int i=2000;i<=2020;i++){
	CString str;
	str.Format(_T("%d"),i);
	this->m_combo_year.AddString(str);
}

获得当前选中的选项和文本

CString year;
int nChoose = this->m_combo_year.GetCurSel();
this->m_combo_year.GetLBText(nChoose,year);

修改选项:SetCurSel()
清空选项: ResetContent()
选项变化事件:CBN_SELCHANGE
Visual C++程序设计 # 机试操作复习 (MFC机试)_第7张图片
如果是dropdown,怎么获得输入框里的文本?m_combo.GetWindowTextW()
拓展阅读: https://blog.csdn.net/qq_33583069/article/details/106167719

  • 根据ID获得控件变量的方法:
    CButton *p8 = ((CButton*)GetDlgItem(IDC_B8));
  • Radio Button 单选互斥的操作

    根据tab顺序,直到新的group:true,否则后面的都互斥
    GetCheck()判断是否选中,0未选中1选中
  • 设置Button不可用/可用
pButton->EnableWindow(FALSE);
pButton->EnableWindow(TRUE);

综合案例:计算器

https://blog.csdn.net/qq_33583069/article/details/106183203
Visual C++程序设计 # 机试操作复习 (MFC机试)_第8张图片

// CCalculatorDlg 消息处理程序

BOOL CCalculatorDlg::OnInitDialog()
{
	CDialogEx::OnInitDialog();

	// 将“关于...”菜单项添加到系统菜单中。

	// IDM_ABOUTBOX 必须在系统命令范围内。
	ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
	ASSERT(IDM_ABOUTBOX < 0xF000);

	CMenu* pSysMenu = GetSystemMenu(FALSE);
	if (pSysMenu != NULL)
	{
		BOOL bNameValid;
		CString strAboutMenu;
		bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);
		ASSERT(bNameValid);
		if (!strAboutMenu.IsEmpty())
		{
			pSysMenu->AppendMenu(MF_SEPARATOR);
			pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
		}
	}

	// 设置此对话框的图标。当应用程序主窗口不是对话框时,框架将自动
	//  执行此操作
	SetIcon(m_hIcon, TRUE);			// 设置大图标
	SetIcon(m_hIcon, FALSE);		// 设置小图标

	// TODO: 在此添加额外的初始化代码
	CButton* pRadioDec = (CButton*)GetDlgItem(IDC_RADIO_DEC);
	pRadioDec->SetCheck(TRUE);
	CButton *pCheck = (CButton*)GetDlgItem(IDC_CHECK);
	pCheck->SetCheck(TRUE);

	return TRUE;  // 除非将焦点设置到控件,否则返回 TRUE
}

void CCalculatorDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
	if ((nID & 0xFFF0) == IDM_ABOUTBOX)
	{
		CAboutDlg dlgAbout;
		dlgAbout.DoModal();
	}
	else
	{
		CDialogEx::OnSysCommand(nID, lParam);
	}
}

// 如果向对话框添加最小化按钮,则需要下面的代码
//  来绘制该图标。对于使用文档/视图模型的 MFC 应用程序,
//  这将由框架自动完成。

void CCalculatorDlg::OnPaint()
{
	if (IsIconic())
	{
		CPaintDC dc(this); // 用于绘制的设备上下文

		SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);

		// 使图标在工作区矩形中居中
		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;

		// 绘制图标
		dc.DrawIcon(x, y, m_hIcon);
	}
	else
	{
		CDialogEx::OnPaint();
	}
}

//当用户拖动最小化窗口时系统调用此函数取得光标
//显示。
HCURSOR CCalculatorDlg::OnQueryDragIcon()
{
	return static_cast<HCURSOR>(m_hIcon);
}



void CCalculatorDlg::OnBnClickedB0(){
	m_nValue = m_nValue*10;
	UpdateData(FALSE);
}

void CCalculatorDlg::OnBnClickedB1()
{
	m_nValue = m_nValue*10+1;
	UpdateData(FALSE);
}




void CCalculatorDlg::OnBnClickedB2()
{
	m_nValue = m_nValue*10+2;
	UpdateData(FALSE);
}


void CCalculatorDlg::OnBnClickedB3()
{
	m_nValue = m_nValue*10+3;
	UpdateData(FALSE);
}


void CCalculatorDlg::OnBnClickedB4()
{
	m_nValue = m_nValue*10+4;
	UpdateData(FALSE);
}


void CCalculatorDlg::OnBnClickedB5()
{
	m_nValue = m_nValue*10+5;
	UpdateData(FALSE);
}


void CCalculatorDlg::OnBnClickedB6()
{
	m_nValue = m_nValue*10+6;
	UpdateData(FALSE);
}


void CCalculatorDlg::OnBnClickedB7()
{
	m_nValue = m_nValue*10+7;
	UpdateData(FALSE);
}


void CCalculatorDlg::OnBnClickedB8()
{
	m_nValue = m_nValue*10+8;
	UpdateData(FALSE);
}


void CCalculatorDlg::OnBnClickedB9()
{
	m_nValue = m_nValue*10+9;
	UpdateData(FALSE);
}


void CCalculatorDlg::OnBnClickedBtnAdd()
{
	UpdateData(TRUE);
	m_nOp1 = m_nValue;
	m_nValue = 0;
	op = '+';
}


void CCalculatorDlg::OnBnClickedBtnSub()
{
	UpdateData(TRUE);
	m_nOp1 = m_nValue;
	m_nValue = 0;
	op = '-';
}


void CCalculatorDlg::OnBnClickedBtnMul()
{
	UpdateData(TRUE);
	m_nOp1 = m_nValue;
	m_nValue = 0;
	op = '*';
}


void CCalculatorDlg::OnBnClickedBtnDiv()
{
	UpdateData(TRUE);
	m_nOp1 = m_nValue;
	m_nValue = 0;
	op = '/';
}


void CCalculatorDlg::OnBnClickedBtnClr()
{
	m_nValue = 0;
	op = 0;
	m_nOp1 = 0;
	m_nOp2 = 0;
	UpdateData(FALSE);
}

int octToDec(int x){
	int result = 0;
	int w = 1;
	while(x){
		if(x&1)result += w*(x%8);
		w *= 8;
		x /= 8;
	}
	return result;
}


void CCalculatorDlg::OnBnClickedBtnEqu()
{
	if(op == 0){
		AfxMessageBox(_T("No Operand"));
		return;
	}
	m_nOp2 = m_nValue;	
	
	CButton *pRadioOct = ((CButton*)GetDlgItem(IDC_RADIO_OCT));
	if(pRadioOct->GetCheck()==1){
		m_nOp1 = octToDec(m_nOp1);
		m_nOp2 = octToDec(m_nOp2);
	}
	switch(op){
	case '+':
		m_nValue = m_nOp1 + m_nOp2;
		break;
	case '-':
		m_nValue = m_nOp1 - m_nOp2;
		break;
	case '*':
		m_nValue = m_nOp1 * m_nOp2;
		break;
	case '/':
		if(m_nOp2 == 0){
			AfxMessageBox(_T("Error"));
			return;
		}
		m_nValue = m_nOp1 / m_nOp2;
		break;
	}
	if(pRadioOct->GetCheck()==1){
		char s8[30];
		itoa(m_nValue,s8,8);
		m_nValue = atoi(s8);
	}
	UpdateData(FALSE);
	m_nValue = 0;
	op = 0;
	m_nOp1 = 0;
	m_nOp2 = 0;
}




void CCalculatorDlg::OnBnClickedRadioDec()
{
	CButton *p8 = ((CButton*)GetDlgItem(IDC_B8));
	CButton *p9 = ((CButton*)GetDlgItem(IDC_B9));
	p8->EnableWindow(TRUE);
	p9->EnableWindow(TRUE);
	transform();
}




void CCalculatorDlg::transform(){
	UpdateData(TRUE);
	CButton *pRadioOct = ((CButton*)GetDlgItem(IDC_RADIO_OCT));
	if(pRadioOct->GetCheck() == 0) {
		m_nValue = octToDec(m_nValue);
	}
	else {
		char s8[30];
		itoa(m_nValue,s8,8);
		m_nValue = atoi(s8);
	}
	UpdateData(FALSE);
}


void CCalculatorDlg::OnBnClickedRadioOct()
{
	CButton *p8 = ((CButton*)GetDlgItem(IDC_B8));
	CButton *p9 = ((CButton*)GetDlgItem(IDC_B9));
	p8->EnableWindow(FALSE);
	p9->EnableWindow(FALSE);
	transform();
}


void CCalculatorDlg::OnBnClickedCheck()
{
	CButton *pRadioDec = (CButton*)GetDlgItem(IDC_RADIO_DEC);
	CButton *pRadioOct = (CButton*)GetDlgItem(IDC_RADIO_OCT);
	CButton *pCheck = (CButton*)GetDlgItem(IDC_CHECK);
	if(pCheck->GetCheck()==0){
		pRadioDec->EnableWindow(FALSE);
		pRadioOct->EnableWindow(FALSE);
	} else {
		pRadioDec->EnableWindow(TRUE);
		pRadioOct->EnableWindow(TRUE);
	}
}

综合案例2 登录对话框

考察点:重写CEdit

https://blog.csdn.net/qq_33583069/article/details/106194453
如果只是限定Edit输入数字的话

改成True就好
如果是限定用字母的话,需要自己重写,这里才是本节重点(考点)

重点
Visual C++程序设计 # 机试操作复习 (MFC机试)_第9张图片
基类选择为:CEdit
Visual C++程序设计 # 机试操作复习 (MFC机试)_第10张图片
添加WM_CHAR消息
Visual C++程序设计 # 机试操作复习 (MFC机试)_第11张图片
Visual C++程序设计 # 机试操作复习 (MFC机试)_第12张图片

  • 旋钮应该不考

  • 图标 bitmap
    Visual C++程序设计 # 机试操作复习 (MFC机试)_第13张图片

HBITMAP hBmp=::LoadBitmap(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDB_BITMAP1));
m_Btn.SetBitmap(hBmp);

2 单文档应用程序

  • 修改XXXView.cpp的OnDraw方法
void CSDIView::OnDraw(CDC* pDC)
{
	CSDIDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	if (!pDoc)
		return;
	// TODO: 在此处为本机数据添加绘制代码
	pDC->TextOut(50,50,_T("hello,单文档"));
}
  • pDC->TextOut(50,50,_T("hello,单文档"));

  • CreatePointFont()

    void CApp15View::OnDraw(CDC* pDC)
    {
        CApp15Doc* pDoc = GetDocument();
         ASSERT_VALID(pDoc);
         if (!pDoc)      return;
        CFont newFont;     // 新字体   
        CFont *pOldFont;   // 选择新字体之前的字体
        newFont.CreatePointFont(180, _T("隶书")); // 创建一种新的字体  
        pOldFont=(CFont*)pDC->SelectObject(&newFont);
        // 在指定位置输出文本   
        pDC->TextOut(40,10,_T("你好!"));   
        // 恢复以前的字体   
        pDC->SelectObject(pOldFont);   
        pDC->TextOut(50,50, _T("这是我的第一个单文档应用程序!"));
    }
    
  • pDC->SetTextColor(RGB(255,0,0));SetBkColor()

  • 修改菜单,并添加处理事件

    • 设置字体菜单
    • CreateFontIndirect
    • LogFont
    • CFontDialog
    void CSDIDoc::OnFontMenu()
    {
    	CFontDialog dlg;
    	if(dlg.DoModal() == IDOK){
    		LOGFONT lf;
    		COLORREF color;
    		dlg.GetCurrentFont(&lf);
    		m_font.DeleteObject();
    		m_font.CreateFontIndirect(&lf);
    		m_color = dlg.GetColor();
    		UpdateAllViews(NULL);
    	}
    }
    

    在view内里刷新的话是RedrawWindow()

    • 添加字体菜单(自定义)
      注意传递数据
    void CSDIDoc::OnAddText()
    {
    	CTextDlg dlg;
    	if(dlg.DoModal() == IDOK){
    		m_nX = dlg.m_nX;
    		m_nY = dlg.m_nY;
    		m_strText = dlg.m_strText;
    	}
    }
    
    • 鼠标消息响应
      • CPoint
    void CSDIView::OnLButtonDown(UINT nFlags, CPoint point)
    {
    	// TODO: 在此添加消息处理程序代码和/或调用默认值
    	m_posText = point;
    	RedrawWindow();
    	CView::OnLButtonDown(nFlags, point);
    }
    
    • 捕获和释放鼠标
      Visual C++程序设计 # 机试操作复习 (MFC机试)_第14张图片
  • 修改ToolBar

    Visual C++程序设计 # 机试操作复习 (MFC机试)_第15张图片
    ID和菜单栏上的某个菜单项保持一致

  • 修改光标

    • WM_SETCURSOR
    BOOL CSDIView::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message)
    {
    	// TODO: 在此添加消息处理程序代码和/或调用默认值
    		CSDIDoc* pDoc = GetDocument();
    		if(pDoc->m_nCursorFlag == 1){
    			::SetCursor(AfxGetApp()->LoadCursor(IDC_CURSOR));
    			return TRUE;
    		} else {
    			::SetCursor(AfxGetApp()->LoadStandardCursor(IDC_ARROW));
    			return TRUE;
    		}
    }
    
  • 修改标题
    方法一:
    Visual C++程序设计 # 机试操作复习 (MFC机试)_第16张图片
    方法二:资源->string table里改mainframe

  • 改图标(Icon) 应用程序左上角的那个
    Visual C++程序设计 # 机试操作复习 (MFC机试)_第17张图片
    改EXE图标
    Visual C++程序设计 # 机试操作复习 (MFC机试)_第18张图片

  • 对象链表

前置条件: 自定义数据类(例如文本信息类,继承自CObject)
https://blog.csdn.net/qq_33583069/article/details/106239080
Visual C++程序设计 # 机试操作复习 (MFC机试)_第19张图片Visual C++程序设计 # 机试操作复习 (MFC机试)_第20张图片
Visual C++程序设计 # 机试操作复习 (MFC机试)_第21张图片
注意这里记录的是LOGFONT

void CSDIDoc::OnAppendText()
{
	CFontDialog dlg;
	LOGFONT lf;
	COLORREF color;
	if(dlg.DoModal() == IDOK){
		dlg.GetCurrentFont(&lf);
		color = dlg.GetColor();
		CTextDlg tdlg;
		if(tdlg.DoModal() == IDOK){
			m_nX = tdlg.m_nX;
			m_nY = tdlg.m_nY;
			m_strText = tdlg.m_strText;
			CMyText* pText = new CMyText(m_strText,CPoint(m_nX,m_nY),lf,color);
			m_textList.AddTail(pText)
		}
	}
	UpdateAllViews(NULL);
}

把view里ondraw的后面的代码删完,重写。

  • POSITION
  • GetHeadPosition
  • GetNext
    !!!这里必考!!!
void CSDIView::OnDraw(CDC* pDC)
{
	CSDIDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	if (!pDoc)
		return;
	// TODO: 在此处为本机数据添加绘制代码
	POSITION pos = pDoc->m_textList.GetHeadPosition();
	while(pos != NULL){
		CMyText* pText = (CMyText*)pDoc->m_textList.GetNext(pos);
		CFont font;
		font.CreateFontIndirect(&pText->m_textFont);
		CFont* pOld = pDC->SelectObject(&font);
		pDC->SetTextColor(pText->m_textColor);
		pDC->TextOut(pText->m_textPos.x,pText->m_textPos.y,pText->m_strText);
		pDC->SelectObject(pOld);
	}
}

删除:

  • RemoveAll
void CSDIDoc::RemoveTextList()
{
	POSITION pos = m_textList.GetHeadPosition();
	while(pos != NULL)
	{
		CMyText* pText = (CMyText*)m_textList.GetNext(pos);
		delete pText;
	}  
	m_textList.RemoveAll();
}

为CMainFrame类添加窗口关闭响应函数OnClose()

  • GetActiveDocument
void CMainFrame::OnClose()
{
	// TODO: 在此添加消息处理程序代码和/或调用默认值
	CSDIDoc* pDoc = (CSDIDoc*)this->GetActiveDocument();
	pDoc->RemoveTextList();
	CFrameWndEx::OnClose();
}
  • 新建/打开文件的处理
    执行File|New命令时,将调用文档类成员函数OnNewDocument(),该函数又要调用另一个成员函数DeleteContents()。另外执行File|Open命令时也会调用DeleteContents()函数。
    注意:选虚函数!!!
    Visual C++程序设计 # 机试操作复习 (MFC机试)_第22张图片
void CSDIDoc::DeleteContents()
{
	RemoveTextList();
	CDocument::DeleteContents();
}
  • 序列化
    https://blog.csdn.net/qq_33583069/article/details/106239080
    序列化这个不用记,在Doc里有类似的代码,直接复制然后修改就行
    Visual C++程序设计 # 机试操作复习 (MFC机试)_第23张图片
class CMyText:public CObject  
{
  DECLARE_SERIAL(CMyText)
  public:
   ……
      virtual void Serialize(CArchive &ar);
   ……
}
CArchive& operator<<(CArchive& ar, LOGFONT& logfont)
{
	ar.Write(&logfont, sizeof(logfont));
	return ar;
}
CArchive& operator>>(CArchive& ar, LOGFONT& logfont)
{
	ar.Read(&logfont, sizeof(logfont));
	return ar;
}
void CMyText::Serialize(CArchive& ar)
{
	if (ar.IsStoring())
	{
		ar << m_strText << m_textPos << m_textFont << m_textColor;
	}
	else
	{
		ar >> m_strText >> m_textPos >> m_textFont >> m_textColor;
	}
}
void CSDIDoc::Serialize(CArchive& ar)
{
	m_textList.Serialize(ar);
	if (ar.IsStoring())
	{
		// TODO: 在此添加存储代码
	}
	else
	{
		// TODO: 在此添加加载代码
	}
}

设置文档修改标记
Visual C++程序设计 # 机试操作复习 (MFC机试)_第24张图片

综合案例 画图系统

https://blog.csdn.net/qq_33583069/article/details/106248164

你可能感兴趣的:(Windows编程,mfc)