MFC程序的设计要求如下:
- 建立一个多文档应用项目(项目名称为学生姓名拼音首字母缩写),并将视图类设置为表单类视图。
- 在该表单中采用编辑框和旋转按钮输入点的横、纵坐标值。
- 对框架窗口进行切分。
- 使得左边窗格输入点的坐标值后,右边窗格将在该点处显示一个小方块。若在右边窗格中任意单击鼠标,则相应的小方块移动到当前鼠标位置处,同时左边编辑框的内容也会随之发生改变。
MFC程序的设计过程如下:
从零开始请参考此文章:安装使用VS2019/2017调试C语言的几点注意事项_123-wqy的博客-CSDN博客_vs2019编写c语言勾选的组件
只需要在安装时额外勾选MFC相关组件即可,如下
首先,打开visual studio 2019,新建MFC多文档工程如下
删除原有的静态文本,通过右侧工具栏的工具箱添加控件并修改该表单
需要添加一个Group Box、两个Static Text、两个Edit Control、两个Spin Control,具体布局如下:
可以打开背景的网格界面并辅以键盘的方向键实现较为准确的位移布局
现在,两个编辑框的ID默认应该为IDC_EDIT1和IDC_EDIT2,两个旋转按钮的ID默认应该为IDC_SPIN1和IDC_SPIN2,且IDC_EDIT1右侧放置着IDC_SPIN1,IDC_EDIT2同理。
右键两个旋转按钮,点击”属性“,在弹出的工具栏设置如下,修改图中带有红色标记的4个选项为图中所示(True)
修改文本如下
右键编辑框,为其添加控制变量,如下
可能会弹出如下提示框,不予理会
再右键旋转按钮,为其添加控制变量,如下
右键编辑框,点击“添加事件处理程序”,添加如下
对另一个编辑框也进行同样的操作
会弹出如下提示,无视即可,我们需要两个编辑框对应一个处理函数
接下来编写对应的代码,首先添加绘图使用的类CDrawView
点击项目——类向导
点击右侧添加类——添加MFC类
注意:仅能够通过这个方式进行添加,直接点击“添加类” 得到的代码并不完全,需要自行添加函数
自动添加了如下两个文件
在CDrawView类中添加public变量
CPoint m_ptDraw; //用于存放绘制实心小方块的位置值
在CMy123wqyMFCDoc类中添加public变量
CPoint m_ptRect; //绘制的小方块
并在CMy123wqyMFCDoc类构造时初始化该变量为(0,0)
m_ptRect.x = m_ptRect.y = 0;
在CMy123wqyMFCView类中添加public变量
BOOL m_bEditOK;
并在CMy123wqyMFCView类构造时初始化该变量为FALSE
m_bEditOK = FALSE;
编写相关代码如下
首先,将ChildFrm.cpp文件中切分窗口的相关代码修改如下
修改BOOL CChildFrame::OnCreateClient(LPCREATESTRUCT /*lpcs*/, CCreateContext* pContext)函数
BOOL CChildFrame::OnCreateClient(LPCREATESTRUCT /*lpcs*/, CCreateContext* pContext)
{
CRect rect;
GetClientRect(&rect); //获得视图窗口的尺寸存入 rect对象中
CSize paneSize(rect.Width() / 2, rect.Height());//定义切分后的视图窗口的尺寸
// 创建静态分割窗口,两列一行
if (!m_wndSplitter.CreateStatic(this, 1, 2))
return FALSE;
if (!m_wndSplitter.CreateView(0, 0, RUNTIME_CLASS(CMy123wqyMFCView), paneSize, pContext))
return FALSE;
if (!m_wndSplitter.CreateView(0, 1, RUNTIME_CLASS(CDrawView), paneSize, pContext))
return FALSE;
m_wndSplitter.RecalcLayout(); //重新布局切分窗口
return TRUE;
}
为能够取得运行时的类,需要在ChildFrm.cpp文件起始部分添加有关的头文件
#include "123-wqy-MFCView.h"
#include "CDrawView.h"
再修改123-wqy-MFCView.cpp中的void CMy123wqyMFCView::OnEnChangeEdit()函数如下
void CMy123wqyMFCView::OnEnChangeEdit()
{
// TODO: 如果该控件是 RICHEDIT 控件,它将不
// 发送此通知,除非重写 CFormView::OnInitDialog()
// 函数并调用 CRichEditCtrl().SetEventMask(),
// 同时将 ENM_CHANGE 标志“或”运算到掩码中。
// TODO: 在此添加控件通知处理程序代码
if (!m_bEditOK)
return; //使 CEx_RectView类视图初始显示时不执行该函数下面代码。
UpdateData(TRUE);
CMy123wqyMFCDoc* pDoc = (CMy123wqyMFCDoc*)GetDocument();
pDoc->m_ptRect.x = m_CoorX; //将设定坐标值存入文档数据成员
pDoc->m_ptRect.y = m_CoorY;
CPoint pt(pDoc->m_ptRect.x, pDoc->m_ptRect.y);
pDoc->UpdateAllViews(NULL, 2, (CObject*)&pt);
//通知更新 CDrawView 视图,调用 CDrawView::OnUpdate()函数并传递 Hint参数
}
再修改void CMy123wqyMFCView::OnInitialUpdate()函数如下
void CMy123wqyMFCView::OnInitialUpdate()
{
CFormView::OnInitialUpdate();
ResizeParentToFit();
CMy123wqyMFCDoc* pDoc = (CMy123wqyMFCDoc*)GetDocument();
m_CoorX = m_CoorY = 50;
pDoc->m_ptRect.x = pDoc->m_ptRect.y = 50;
m_SpinX.SetRange(0, 1024);
m_SpinY.SetRange(0, 768);
UpdateData(FALSE);//编辑框显示坐标位置初值
m_bEditOK = TRUE;
}
随后重载CMy123wqyMFCView类的OnUpdate虚函数,首先点击项目——类向导
找到虚函数——OnUpdate并双击,随后点击确定,添加的函数如下
取消默认对LPARAM lHint参数和CObject* pHint参数的注释,同时,还应注意取消123-wqy-MFCView.h文件中对该函数的声明的相应参数的注释
修改void CMy123wqyMFCView::OnUpdate(CView* /*pSender*/, LPARAM lHint, CObject* pHint)函数如下
void CMy123wqyMFCView::OnUpdate(CView* /*pSender*/, LPARAM lHint, CObject* pHint)
{
// TODO: 在此添加专用代码和/或调用基类
if (lHint) //接受 CDrawView 传递 Hint 参数
{
CPoint* pPoint = (CPoint*)pHint;
m_CoorX = pPoint->x;
m_CoorY = pPoint->y;
UpdateData(FALSE); //使编辑框控件显示鼠标坐标
CMy123wqyMFCDoc* pDoc = (CMy123wqyMFCDoc*)GetDocument();
//pDoc->m_ptRect.x = m_CoorX; //将鼠标坐标值存入文档数据成员
//pDoc->m_ptRect.y = m_CoorY;
pDoc->m_ptRect = *pPoint;
}
}
再修改CDrawView.cpp文件中的void CDrawView::OnDraw(CDC* pDC)函数如下
void CDrawView::OnDraw(CDC* pDC)
{
CDocument* pDoc = GetDocument();
// TODO: 在此添加绘制代码
CBrush drawBrush;
drawBrush.CreateSolidBrush(RGB(192, 192, 0));
CBrush* pOldBrush = pDC->SelectObject(&drawBrush);
pDC->Rectangle(m_ptDraw.x - 5, m_ptDraw.y - 5, m_ptDraw.x + 5, m_ptDraw.y + 5);
pDC->SelectObject(pOldBrush);
}
再次打开项目——类向导,为CDrawView类重载OnInitialUpdate虚函数、OnUpdate虚函数和添加OnLButtonDown消息的处理程序
并在CDrawView.cpp前部包含头文件
#include "123-wqy-MFCDoc.h"
修改void CDrawView::OnInitialUpdate()函数如下
void CDrawView::OnInitialUpdate()
{
CView::OnInitialUpdate();
// TODO: 在此添加专用代码和/或调用基类
CMy123wqyMFCDoc* pDoc = (CMy123wqyMFCDoc*)GetDocument();
m_ptDraw = pDoc->m_ptRect; //将文档数据成员初值赋给为实心小方块位置数据成员
}
取消默认对void CDrawView::OnUpdate函数中对参数LPARAM lHint和参数CObject* pHint的注释
修改void CDrawView::OnUpdate(CView* /*pSender*/, LPARAM /*lHint*/, CObject* /*pHint*/)函数如下
void CDrawView::OnUpdate(CView* /*pSender*/, LPARAM lHint, CObject* pHint)
{
// TODO: 在此添加专用代码和/或调用基类
if (lHint == 2) //接受 CEx_RectView 传递 Hint 参数
{
CPoint* pPoint = (CPoint*)pHint;
m_ptDraw = *pPoint;
Invalidate();
}
}
修改void CDrawView::OnLButtonDown(UINT nFlags, CPoint point)函数如下
void CDrawView::OnLButtonDown(UINT nFlags, CPoint point)
{
// TODO: 在此添加消息处理程序代码和/或调用默认值
m_ptDraw = point;
GetDocument()->UpdateAllViews(NULL, 1, (CObject*)&m_ptDraw);
Invalidate();
CView::OnLButtonDown(nFlags, point);
}
此时,VS在123-wqy-MFCView.cpp的123-wqy-MFCView类构造函数下报错,如下
参考其它类的构造函数,可以确认是添加的m_CoorX(0)引起错误,将其删除,修改如下
对应的构造函数即为
CMy123wqyMFCView::CMy123wqyMFCView() noexcept
: CFormView(IDD_MY123WQYMFC_FORM)
{
// TODO: 在此处添加构造代码
m_bEditOK = FALSE;
}
到这里就基本完成了,此时点击“本地Windows调试器”运行时会报编译错误如下
双击其中一条错误,定位到123-wqy-MFCView.h文件
CMy123wqyMFCDoc* GetDocument() const;
观察发现应该是未包含有关CMy123wqyMFCDoc的头文件导致的,在123-wqy-MFCView.h文件前再包含123-wqy-MFCDoc.h文件,如下
#include "123-wqy-MFCDoc.h"
若此处进行了包含,则可以在123-wqy-MFCView.cpp文件中去除对123-wqy-MFCDoc.h文件的包含了,再次编译运行,结果如下
可以看到,Y坐标区域没有显示,联想到一开始的错误提示,转到123-wqy-MFCView.cpp文件中的void CMy123wqyMFCView::DoDataExchange(CDataExchange* pDX)函数处,此处缺少了对控件IDC_EDIT2的变量关联,将其添加并修改如下
void CMy123wqyMFCView::DoDataExchange(CDataExchange* pDX)
{
CFormView::DoDataExchange(pDX);
DDX_Control(pDX, IDC_SPIN1, m_SpinX);
DDX_Control(pDX, IDC_SPIN2, m_SpinY);
DDX_Text(pDX, IDC_EDIT1, m_CoorX);
DDX_Text(pDX, IDC_EDIT2, m_CoorY);
}
再次编译运行,结果如下
此时Y坐标仍然不能设置,联想之前出现的错误,查看123-wqy-MFCView.cpp文件的MESSAGE_MAP部分,如下
可以看到Y轴坐标的编辑框没有关联对应的处理函数,增加修改如下
BEGIN_MESSAGE_MAP(CMy123wqyMFCView, CFormView)
// 标准打印命令
ON_COMMAND(ID_FILE_PRINT, &CFormView::OnFilePrint)
ON_COMMAND(ID_FILE_PRINT_DIRECT, &CFormView::OnFilePrint)
ON_COMMAND(ID_FILE_PRINT_PREVIEW, &CFormView::OnFilePrintPreview)
ON_EN_CHANGE(IDC_EDIT1, &CMy123wqyMFCView::OnEnChangeEdit)
ON_EN_CHANGE(IDC_EDIT2, &CMy123wqyMFCView::OnEnChangeEdit)
END_MESSAGE_MAP()
再次编译运行,结果如下
完成了相关要求,实现了相关功能
附录:所有源文件、头文件以及工程下载
工程文件下载:https://123-wqy.lanzoui.com/i2FRJqc9fre
123-wqy-MFC.h: 123-wqy-MFC 应用程序的主头文件
// 123-wqy-MFC.h: 123-wqy-MFC 应用程序的主头文件
//
#pragma once
#ifndef __AFXWIN_H__
#error "在包含此文件之前包含 'pch.h' 以生成 PCH"
#endif
#include "resource.h" // 主符号
// CMy123wqyMFCApp:
// 有关此类的实现,请参阅 123-wqy-MFC.cpp
//
class CMy123wqyMFCApp : public CWinApp
{
public:
CMy123wqyMFCApp() noexcept;
// 重写
public:
virtual BOOL InitInstance();
virtual int ExitInstance();
// 实现
afx_msg void OnAppAbout();
DECLARE_MESSAGE_MAP()
};
extern CMy123wqyMFCApp theApp;
123-wqy-MFCDoc.h: CMy123wqyMFCDoc 类的接口
// 123-wqy-MFCDoc.h: CMy123wqyMFCDoc 类的接口
//
#pragma once
class CMy123wqyMFCDoc : public CDocument
{
protected: // 仅从序列化创建
CMy123wqyMFCDoc() noexcept;
DECLARE_DYNCREATE(CMy123wqyMFCDoc)
// 特性
public:
// 操作
public:
CPoint m_ptRect; //绘制的小方块
// 重写
public:
virtual BOOL OnNewDocument();
virtual void Serialize(CArchive& ar);
#ifdef SHARED_HANDLERS
virtual void InitializeSearchContent();
virtual void OnDrawThumbnail(CDC& dc, LPRECT lprcBounds);
#endif // SHARED_HANDLERS
// 实现
public:
virtual ~CMy123wqyMFCDoc();
#ifdef _DEBUG
virtual void AssertValid() const;
virtual void Dump(CDumpContext& dc) const;
#endif
protected:
// 生成的消息映射函数
protected:
DECLARE_MESSAGE_MAP()
#ifdef SHARED_HANDLERS
// 用于为搜索处理程序设置搜索内容的 Helper 函数
void SetSearchContent(const CString& value);
#endif // SHARED_HANDLERS
};
123-wqy-MFCView.h: CMy123wqyMFCView 类的接口
// 123-wqy-MFCView.h: CMy123wqyMFCView 类的接口
//
#pragma once
#include "123-wqy-MFCDoc.h"
class CMy123wqyMFCView : public CFormView
{
protected: // 仅从序列化创建
CMy123wqyMFCView() noexcept;
DECLARE_DYNCREATE(CMy123wqyMFCView)
public:
#ifdef AFX_DESIGN_TIME
enum{ IDD = IDD_MY123WQYMFC_FORM };
#endif
// 特性
public:
CMy123wqyMFCDoc* GetDocument() const;
// 操作
public:
// 重写
public:
virtual BOOL PreCreateWindow(CREATESTRUCT& cs);
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV 支持
virtual void OnInitialUpdate(); // 构造后第一次调用
virtual BOOL OnPreparePrinting(CPrintInfo* pInfo);
virtual void OnBeginPrinting(CDC* pDC, CPrintInfo* pInfo);
virtual void OnEndPrinting(CDC* pDC, CPrintInfo* pInfo);
virtual void OnPrint(CDC* pDC, CPrintInfo* pInfo);
// 实现
public:
virtual ~CMy123wqyMFCView();
#ifdef _DEBUG
virtual void AssertValid() const;
virtual void Dump(CDumpContext& dc) const;
#endif
protected:
// 生成的消息映射函数
protected:
DECLARE_MESSAGE_MAP()
public:
CSpinButtonCtrl m_SpinX;
CSpinButtonCtrl m_SpinY;
BOOL m_bEditOK;
afx_msg void OnEnChangeEdit();
long m_CoorX, m_CoorY;
virtual void OnUpdate(CView* /*pSender*/, LPARAM lHint, CObject* pHint);
};
#ifndef _DEBUG // 123-wqy-MFCView.cpp 中的调试版本
inline CMy123wqyMFCDoc* CMy123wqyMFCView::GetDocument() const
{ return reinterpret_cast<CMy123wqyMFCDoc*>(m_pDocument); }
#endif
CDrawView.h: CDrawView 视图接口
#pragma once
// CDrawView 视图
class CDrawView : public CView
{
DECLARE_DYNCREATE(CDrawView)
protected:
CDrawView(); // 动态创建所使用的受保护的构造函数
virtual ~CDrawView();
public:
CPoint m_ptDraw; //用于存放绘制实心小方块的位置值
virtual void OnDraw(CDC* pDC); // 重写以绘制该视图
#ifdef _DEBUG
virtual void AssertValid() const;
#ifndef _WIN32_WCE
virtual void Dump(CDumpContext& dc) const;
#endif
#endif
protected:
DECLARE_MESSAGE_MAP()
public:
virtual void OnInitialUpdate();
afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
virtual void OnUpdate(CView* /*pSender*/, LPARAM /*lHint*/, CObject* /*pHint*/);
};
ChildFrm.h: CChildFrame 类的接口
// ChildFrm.h: CChildFrame 类的接口
//
#pragma once
class CChildFrame : public CMDIChildWnd
{
DECLARE_DYNCREATE(CChildFrame)
public:
CChildFrame() noexcept;
// 特性
protected:
CSplitterWnd m_wndSplitter;
public:
// 操作
public:
// 重写
public:
virtual BOOL OnCreateClient(LPCREATESTRUCT lpcs, CCreateContext* pContext);
virtual BOOL PreCreateWindow(CREATESTRUCT& cs);
// 实现
public:
virtual ~CChildFrame();
#ifdef _DEBUG
virtual void AssertValid() const;
virtual void Dump(CDumpContext& dc) const;
#endif
// 生成的消息映射函数
protected:
DECLARE_MESSAGE_MAP()
};
framework.h: 框架头文件
#pragma once
#ifndef VC_EXTRALEAN
#define VC_EXTRALEAN // 从 Windows 头中排除极少使用的资料
#endif
#include "targetver.h"
#define _ATL_CSTRING_EXPLICIT_CONSTRUCTORS // 某些 CString 构造函数将是显式的
// 关闭 MFC 的一些常见且经常可放心忽略的隐藏警告消息
#define _AFX_ALL_WARNINGS
#include <afxwin.h> // MFC 核心组件和标准组件
#include <afxext.h> // MFC 扩展
#include <afxdisp.h> // MFC 自动化类
#ifndef _AFX_NO_OLE_SUPPORT
#include <afxdtctl.h> // MFC 对 Internet Explorer 4 公共控件的支持
#endif
#ifndef _AFX_NO_AFXCMN_SUPPORT
#include <afxcmn.h> // MFC 对 Windows 公共控件的支持
#endif // _AFX_NO_AFXCMN_SUPPORT
#include <afxcontrolbars.h> // MFC 支持功能区和控制条
#ifdef _UNICODE
#if defined _M_IX86
#pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='x86' publicKeyToken='6595b64144ccf1df' language='*'\"")
#elif defined _M_X64
#pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='amd64' publicKeyToken='6595b64144ccf1df' language='*'\"")
#else
#pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")
#endif
#endif
MainFrm.h: CMainFrame 类的接口
// MainFrm.h: CMainFrame 类的接口
//
#pragma once
class CMainFrame : public CMDIFrameWnd
{
DECLARE_DYNAMIC(CMainFrame)
public:
CMainFrame() noexcept;
// 特性
public:
// 操作
public:
// 重写
public:
virtual BOOL PreCreateWindow(CREATESTRUCT& cs);
// 实现
public:
virtual ~CMainFrame();
#ifdef _DEBUG
virtual void AssertValid() const;
virtual void Dump(CDumpContext& dc) const;
#endif
protected: // 控件条嵌入成员
CToolBar m_wndToolBar;
CStatusBar m_wndStatusBar;
// 生成的消息映射函数
protected:
afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
DECLARE_MESSAGE_MAP()
};
pch.h: 这是预编译标头文件
// pch.h: 这是预编译标头文件。
// 下方列出的文件仅编译一次,提高了将来生成的生成性能。
// 这还将影响 IntelliSense 性能,包括代码完成和许多代码浏览功能。
// 但是,如果此处列出的文件中的任何一个在生成之间有更新,它们全部都将被重新编译。
// 请勿在此处添加要频繁更新的文件,这将使得性能优势无效。
#ifndef PCH_H
#define PCH_H
// 添加要在此处预编译的标头
#include "framework.h"
#endif //PCH_H
Resource.h: Microsoft Visual C++ 生成的包含文件,供 My123wqyMFC.rc 使用
//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ 生成的包含文件。
// 供 My123wqyMFC.rc 使用
//
#define IDD_ABOUTBOX 100
#define IDP_OLE_INIT_FAILED 100
#define IDD_MY123WQYMFC_FORM 101
#define IDR_MAINFRAME 128
#define IDR_My123wqyMFCTYPE 130
#define ID_WINDOW_MANAGER 131
#define IDC_EDIT1 1000
#define IDC_SPIN1 1001
#define IDC_EDIT2 1002
#define IDC_SPIN2 1003
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 311
#define _APS_NEXT_COMMAND_VALUE 32771
#define _APS_NEXT_CONTROL_VALUE 1004
#define _APS_NEXT_SYMED_VALUE 310
#endif
#endif
targetver.h: 决定应用程序所运行的Windows平台
#pragma once
// 包括 SDKDDKVer.h 将定义可用的最高版本的 Windows 平台。
//如果要为以前的 Windows 平台生成应用程序,请包括 WinSDKVer.h,并
// 将 _WIN32_WINNT 宏设置为要支持的平台,然后再包括 SDKDDKVer.h。
#include <SDKDDKVer.h>
CPP文件
123-wqy-MFC.cpp: 定义应用程序的类行为
// 123-wqy-MFC.cpp: 定义应用程序的类行为。
//
#include "pch.h"
#include "framework.h"
#include "afxwinappex.h"
#include "afxdialogex.h"
#include "123-wqy-MFC.h"
#include "MainFrm.h"
#include "ChildFrm.h"
#include "123-wqy-MFCDoc.h"
#include "123-wqy-MFCView.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
// CMy123wqyMFCApp
BEGIN_MESSAGE_MAP(CMy123wqyMFCApp, CWinApp)
ON_COMMAND(ID_APP_ABOUT, &CMy123wqyMFCApp::OnAppAbout)
// 基于文件的标准文档命令
ON_COMMAND(ID_FILE_NEW, &CWinApp::OnFileNew)
ON_COMMAND(ID_FILE_OPEN, &CWinApp::OnFileOpen)
// 标准打印设置命令
ON_COMMAND(ID_FILE_PRINT_SETUP, &CWinApp::OnFilePrintSetup)
END_MESSAGE_MAP()
// CMy123wqyMFCApp 构造
CMy123wqyMFCApp::CMy123wqyMFCApp() noexcept
{
// 支持重新启动管理器
m_dwRestartManagerSupportFlags = AFX_RESTART_MANAGER_SUPPORT_ALL_ASPECTS;
#ifdef _MANAGED
// 如果应用程序是利用公共语言运行时支持(/clr)构建的,则:
// 1) 必须有此附加设置,“重新启动管理器”支持才能正常工作。
// 2) 在您的项目中,您必须按照生成顺序向 System.Windows.Forms 添加引用。
System::Windows::Forms::Application::SetUnhandledExceptionMode(System::Windows::Forms::UnhandledExceptionMode::ThrowException);
#endif
// TODO: 将以下应用程序 ID 字符串替换为唯一的 ID 字符串;建议的字符串格式
//为 CompanyName.ProductName.SubProduct.VersionInformation
SetAppID(_T("My123wqyMFC.AppID.NoVersion"));
// TODO: 在此处添加构造代码,
// 将所有重要的初始化放置在 InitInstance 中
}
// 唯一的 CMy123wqyMFCApp 对象
CMy123wqyMFCApp theApp;
// CMy123wqyMFCApp 初始化
BOOL CMy123wqyMFCApp::InitInstance()
{
// 如果一个运行在 Windows XP 上的应用程序清单指定要
// 使用 ComCtl32.dll 版本 6 或更高版本来启用可视化方式,
//则需要 InitCommonControlsEx()。 否则,将无法创建窗口。
INITCOMMONCONTROLSEX InitCtrls;
InitCtrls.dwSize = sizeof(InitCtrls);
// 将它设置为包括所有要在应用程序中使用的
// 公共控件类。
InitCtrls.dwICC = ICC_WIN95_CLASSES;
InitCommonControlsEx(&InitCtrls);
CWinApp::InitInstance();
// 初始化 OLE 库
if (!AfxOleInit())
{
AfxMessageBox(IDP_OLE_INIT_FAILED);
return FALSE;
}
AfxEnableControlContainer();
EnableTaskbarInteraction(FALSE);
// 使用 RichEdit 控件需要 AfxInitRichEdit2()
// AfxInitRichEdit2();
// 标准初始化
// 如果未使用这些功能并希望减小
// 最终可执行文件的大小,则应移除下列
// 不需要的特定初始化例程
// 更改用于存储设置的注册表项
// TODO: 应适当修改该字符串,
// 例如修改为公司或组织名
SetRegistryKey(_T("应用程序向导生成的本地应用程序"));
LoadStdProfileSettings(4); // 加载标准 INI 文件选项(包括 MRU)
// 注册应用程序的文档模板。 文档模板
// 将用作文档、框架窗口和视图之间的连接
CMultiDocTemplate* pDocTemplate;
pDocTemplate = new CMultiDocTemplate(IDR_My123wqyMFCTYPE,
RUNTIME_CLASS(CMy123wqyMFCDoc),
RUNTIME_CLASS(CChildFrame), // 自定义 MDI 子框架
RUNTIME_CLASS(CMy123wqyMFCView));
if (!pDocTemplate)
return FALSE;
AddDocTemplate(pDocTemplate);
// 创建主 MDI 框架窗口
CMainFrame* pMainFrame = new CMainFrame;
if (!pMainFrame || !pMainFrame->LoadFrame(IDR_MAINFRAME))
{
delete pMainFrame;
return FALSE;
}
m_pMainWnd = pMainFrame;
// 分析标准 shell 命令、DDE、打开文件操作的命令行
CCommandLineInfo cmdInfo;
ParseCommandLine(cmdInfo);
// 调度在命令行中指定的命令。 如果
// 用 /RegServer、/Register、/Unregserver 或 /Unregister 启动应用程序,则返回 FALSE。
if (!ProcessShellCommand(cmdInfo))
return FALSE;
// 主窗口已初始化,因此显示它并对其进行更新
pMainFrame->ShowWindow(m_nCmdShow);
pMainFrame->UpdateWindow();
return TRUE;
}
int CMy123wqyMFCApp::ExitInstance()
{
//TODO: 处理可能已添加的附加资源
AfxOleTerm(FALSE);
return CWinApp::ExitInstance();
}
// CMy123wqyMFCApp 消息处理程序
// 用于应用程序“关于”菜单项的 CAboutDlg 对话框
class CAboutDlg : public CDialogEx
{
public:
CAboutDlg() noexcept;
// 对话框数据
#ifdef AFX_DESIGN_TIME
enum { IDD = IDD_ABOUTBOX };
#endif
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV 支持
// 实现
protected:
DECLARE_MESSAGE_MAP()
};
CAboutDlg::CAboutDlg() noexcept : CDialogEx(IDD_ABOUTBOX)
{
}
void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
CDialogEx::DoDataExchange(pDX);
}
BEGIN_MESSAGE_MAP(CAboutDlg, CDialogEx)
END_MESSAGE_MAP()
// 用于运行对话框的应用程序命令
void CMy123wqyMFCApp::OnAppAbout()
{
CAboutDlg aboutDlg;
aboutDlg.DoModal();
}
// CMy123wqyMFCApp 消息处理程序
123-wqy-MFCDoc.cpp: CMy123wqyMFCDoc 类的实现
// 123-wqy-MFCDoc.cpp: CMy123wqyMFCDoc 类的实现
//
#include "pch.h"
#include "framework.h"
// SHARED_HANDLERS 可以在实现预览、缩略图和搜索筛选器句柄的
// ATL 项目中进行定义,并允许与该项目共享文档代码。
#ifndef SHARED_HANDLERS
#include "123-wqy-MFC.h"
#endif
#include "123-wqy-MFCDoc.h"
#include <propkey.h>
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
// CMy123wqyMFCDoc
IMPLEMENT_DYNCREATE(CMy123wqyMFCDoc, CDocument)
BEGIN_MESSAGE_MAP(CMy123wqyMFCDoc, CDocument)
END_MESSAGE_MAP()
// CMy123wqyMFCDoc 构造/析构
CMy123wqyMFCDoc::CMy123wqyMFCDoc() noexcept
{
// TODO: 在此添加一次性构造代码
m_ptRect.x = m_ptRect.y = 0;
}
CMy123wqyMFCDoc::~CMy123wqyMFCDoc()
{
}
BOOL CMy123wqyMFCDoc::OnNewDocument()
{
if (!CDocument::OnNewDocument())
return FALSE;
// TODO: 在此添加重新初始化代码
// (SDI 文档将重用该文档)
return TRUE;
}
// CMy123wqyMFCDoc 序列化
void CMy123wqyMFCDoc::Serialize(CArchive& ar)
{
if (ar.IsStoring())
{
// TODO: 在此添加存储代码
}
else
{
// TODO: 在此添加加载代码
}
}
#ifdef SHARED_HANDLERS
// 缩略图的支持
void CMy123wqyMFCDoc::OnDrawThumbnail(CDC& dc, LPRECT lprcBounds)
{
// 修改此代码以绘制文档数据
dc.FillSolidRect(lprcBounds, RGB(255, 255, 255));
CString strText = _T("TODO: implement thumbnail drawing here");
LOGFONT lf;
CFont* pDefaultGUIFont = CFont::FromHandle((HFONT) GetStockObject(DEFAULT_GUI_FONT));
pDefaultGUIFont->GetLogFont(&lf);
lf.lfHeight = 36;
CFont fontDraw;
fontDraw.CreateFontIndirect(&lf);
CFont* pOldFont = dc.SelectObject(&fontDraw);
dc.DrawText(strText, lprcBounds, DT_CENTER | DT_WORDBREAK);
dc.SelectObject(pOldFont);
}
// 搜索处理程序的支持
void CMy123wqyMFCDoc::InitializeSearchContent()
{
CString strSearchContent;
// 从文档数据设置搜索内容。
// 内容部分应由“;”分隔
// 例如: strSearchContent = _T("point;rectangle;circle;ole object;");
SetSearchContent(strSearchContent);
}
void CMy123wqyMFCDoc::SetSearchContent(const CString& value)
{
if (value.IsEmpty())
{
RemoveChunk(PKEY_Search_Contents.fmtid, PKEY_Search_Contents.pid);
}
else
{
CMFCFilterChunkValueImpl *pChunk = nullptr;
ATLTRY(pChunk = new CMFCFilterChunkValueImpl);
if (pChunk != nullptr)
{
pChunk->SetTextValue(PKEY_Search_Contents, value, CHUNK_TEXT);
SetChunkValue(pChunk);
}
}
}
#endif // SHARED_HANDLERS
// CMy123wqyMFCDoc 诊断
#ifdef _DEBUG
void CMy123wqyMFCDoc::AssertValid() const
{
CDocument::AssertValid();
}
void CMy123wqyMFCDoc::Dump(CDumpContext& dc) const
{
CDocument::Dump(dc);
}
#endif //_DEBUG
// CMy123wqyMFCDoc 命令
123-wqy-MFCView.cpp: CMy123wqyMFCView 类的实现
// 123-wqy-MFCView.cpp: CMy123wqyMFCView 类的实现
//
#include "pch.h"
#include "framework.h"
// SHARED_HANDLERS 可以在实现预览、缩略图和搜索筛选器句柄的
// ATL 项目中进行定义,并允许与该项目共享文档代码。
#ifndef SHARED_HANDLERS
#include "123-wqy-MFC.h"
#endif
#include "123-wqy-MFCView.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
// CMy123wqyMFCView
IMPLEMENT_DYNCREATE(CMy123wqyMFCView, CFormView)
BEGIN_MESSAGE_MAP(CMy123wqyMFCView, CFormView)
// 标准打印命令
ON_COMMAND(ID_FILE_PRINT, &CFormView::OnFilePrint)
ON_COMMAND(ID_FILE_PRINT_DIRECT, &CFormView::OnFilePrint)
ON_COMMAND(ID_FILE_PRINT_PREVIEW, &CFormView::OnFilePrintPreview)
ON_EN_CHANGE(IDC_EDIT1, &CMy123wqyMFCView::OnEnChangeEdit)
ON_EN_CHANGE(IDC_EDIT2, &CMy123wqyMFCView::OnEnChangeEdit)
END_MESSAGE_MAP()
// CMy123wqyMFCView 构造/析构
CMy123wqyMFCView::CMy123wqyMFCView() noexcept
: CFormView(IDD_MY123WQYMFC_FORM)
{
// TODO: 在此处添加构造代码
m_bEditOK = FALSE;
}
CMy123wqyMFCView::~CMy123wqyMFCView()
{
}
void CMy123wqyMFCView::DoDataExchange(CDataExchange* pDX)
{
CFormView::DoDataExchange(pDX);
DDX_Control(pDX, IDC_SPIN1, m_SpinX);
DDX_Control(pDX, IDC_SPIN2, m_SpinY);
DDX_Text(pDX, IDC_EDIT1, m_CoorX);
DDX_Text(pDX, IDC_EDIT2, m_CoorY);
}
BOOL CMy123wqyMFCView::PreCreateWindow(CREATESTRUCT& cs)
{
// TODO: 在此处通过修改
// CREATESTRUCT cs 来修改窗口类或样式
return CFormView::PreCreateWindow(cs);
}
void CMy123wqyMFCView::OnInitialUpdate()
{
CFormView::OnInitialUpdate();
ResizeParentToFit();
CMy123wqyMFCDoc* pDoc = (CMy123wqyMFCDoc*)GetDocument();
m_CoorX = m_CoorY = 50;
pDoc->m_ptRect.x = pDoc->m_ptRect.y = 50;
m_SpinX.SetRange(0, 1024);
m_SpinY.SetRange(0, 768);
UpdateData(FALSE);//编辑框显示坐标位置初值
m_bEditOK = TRUE;
}
// CMy123wqyMFCView 打印
BOOL CMy123wqyMFCView::OnPreparePrinting(CPrintInfo* pInfo)
{
// 默认准备
return DoPreparePrinting(pInfo);
}
void CMy123wqyMFCView::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
// TODO: 添加额外的打印前进行的初始化过程
}
void CMy123wqyMFCView::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
// TODO: 添加打印后进行的清理过程
}
void CMy123wqyMFCView::OnPrint(CDC* pDC, CPrintInfo* /*pInfo*/)
{
// TODO: 在此处添加自定义打印代码
}
// CMy123wqyMFCView 诊断
#ifdef _DEBUG
void CMy123wqyMFCView::AssertValid() const
{
CFormView::AssertValid();
}
void CMy123wqyMFCView::Dump(CDumpContext& dc) const
{
CFormView::Dump(dc);
}
CMy123wqyMFCDoc* CMy123wqyMFCView::GetDocument() const // 非调试版本是内联的
{
ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CMy123wqyMFCDoc)));
return (CMy123wqyMFCDoc*)m_pDocument;
}
#endif //_DEBUG
// CMy123wqyMFCView 消息处理程序
void CMy123wqyMFCView::OnEnChangeEdit()
{
// TODO: 如果该控件是 RICHEDIT 控件,它将不
// 发送此通知,除非重写 CFormView::OnInitDialog()
// 函数并调用 CRichEditCtrl().SetEventMask(),
// 同时将 ENM_CHANGE 标志“或”运算到掩码中。
// TODO: 在此添加控件通知处理程序代码
if (!m_bEditOK)
return; //使 CEx_RectView类视图初始显示时不执行该函数下面代码。
UpdateData(TRUE);
CMy123wqyMFCDoc* pDoc = (CMy123wqyMFCDoc*)GetDocument();
pDoc->m_ptRect.x = m_CoorX; //将设定坐标值存入文档数据成员
pDoc->m_ptRect.y = m_CoorY;
CPoint pt(pDoc->m_ptRect.x, pDoc->m_ptRect.y);
pDoc->UpdateAllViews(NULL, 2, (CObject*)&pt);
//通知更新 CDrawView 视图,调用 CDrawView::OnUpdate()函数并传递 Hint参数
}
void CMy123wqyMFCView::OnUpdate(CView* /*pSender*/, LPARAM lHint, CObject* pHint)
{
// TODO: 在此添加专用代码和/或调用基类
if (lHint) //接受 CDrawView 传递 Hint 参数
{
CPoint* pPoint = (CPoint*)pHint;
m_CoorX = pPoint->x;
m_CoorY = pPoint->y;
UpdateData(FALSE); //使编辑框控件显示鼠标坐标
CMy123wqyMFCDoc* pDoc = (CMy123wqyMFCDoc*)GetDocument();
pDoc->m_ptRect = *pPoint;
}
}
CDrawView.cpp: CDrawView实现文件
// CDrawView.cpp: 实现文件
//
#include "pch.h"
#include "123-wqy-MFC.h"
#include "CDrawView.h"
#include "123-wqy-MFCDoc.h"
// CDrawView
IMPLEMENT_DYNCREATE(CDrawView, CView)
CDrawView::CDrawView()
{
}
CDrawView::~CDrawView()
{
}
BEGIN_MESSAGE_MAP(CDrawView, CView)
ON_WM_LBUTTONDOWN()
END_MESSAGE_MAP()
// CDrawView 绘图
void CDrawView::OnDraw(CDC* pDC)
{
CDocument* pDoc = GetDocument();
// TODO: 在此添加绘制代码
CBrush drawBrush;
drawBrush.CreateSolidBrush(RGB(192, 192, 0));
CBrush* pOldBrush = pDC->SelectObject(&drawBrush);
pDC->Rectangle(m_ptDraw.x - 5, m_ptDraw.y - 5, m_ptDraw.x + 5, m_ptDraw.y + 5);
pDC->SelectObject(pOldBrush);
}
// CDrawView 诊断
#ifdef _DEBUG
void CDrawView::AssertValid() const
{
CView::AssertValid();
}
#ifndef _WIN32_WCE
void CDrawView::Dump(CDumpContext& dc) const
{
CView::Dump(dc);
}
#endif
#endif //_DEBUG
// CDrawView 消息处理程序
void CDrawView::OnInitialUpdate()
{
CView::OnInitialUpdate();
// TODO: 在此添加专用代码和/或调用基类
CMy123wqyMFCDoc* pDoc = (CMy123wqyMFCDoc*)GetDocument();
m_ptDraw = pDoc->m_ptRect; //将文档数据成员初值赋给为实心小方块位置数据成员
}
void CDrawView::OnLButtonDown(UINT nFlags, CPoint point)
{
// TODO: 在此添加消息处理程序代码和/或调用默认值
m_ptDraw = point;
GetDocument()->UpdateAllViews(NULL, 1, (CObject*)&m_ptDraw);
Invalidate();
CView::OnLButtonDown(nFlags, point);
}
void CDrawView::OnUpdate(CView* /*pSender*/, LPARAM lHint, CObject* pHint)
{
// TODO: 在此添加专用代码和/或调用基类
if (lHint == 2) //接受 CEx_RectView 传递 Hint 参数
{
CPoint* pPoint = (CPoint*)pHint;
m_ptDraw = *pPoint;
Invalidate();
}
}
ChildFrm.cpp: CChildFrame 类的实现
// ChildFrm.cpp: CChildFrame 类的实现
//
#include "pch.h"
#include "framework.h"
#include "123-wqy-MFC.h"
#include "ChildFrm.h"
#include "123-wqy-MFCView.h"
#include "CDrawView.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
// CChildFrame
IMPLEMENT_DYNCREATE(CChildFrame, CMDIChildWnd)
BEGIN_MESSAGE_MAP(CChildFrame, CMDIChildWnd)
END_MESSAGE_MAP()
// CChildFrame 构造/析构
CChildFrame::CChildFrame() noexcept
{
// TODO: 在此添加成员初始化代码
}
CChildFrame::~CChildFrame()
{
}
BOOL CChildFrame::OnCreateClient(LPCREATESTRUCT /*lpcs*/, CCreateContext* pContext)
{
CRect rect;
GetClientRect(&rect); //获得视图窗口的尺寸存入 rect对象中
CSize paneSize(rect.Width() / 2, rect.Height());//定义切分后的视图窗口的尺寸
// 创建静态分割窗口,两列一行
if (!m_wndSplitter.CreateStatic(this, 1, 2))
return FALSE;
if (!m_wndSplitter.CreateView(0, 0, RUNTIME_CLASS(CMy123wqyMFCView), paneSize, pContext))
return FALSE;
if (!m_wndSplitter.CreateView(0, 1, RUNTIME_CLASS(CDrawView), paneSize, pContext))
return FALSE;
m_wndSplitter.RecalcLayout(); //重新布局切分窗口
return TRUE;
}
BOOL CChildFrame::PreCreateWindow(CREATESTRUCT& cs)
{
// TODO: 在此处通过修改 CREATESTRUCT cs 来修改窗口类或样式
if( !CMDIChildWnd::PreCreateWindow(cs) )
return FALSE;
return TRUE;
}
// CChildFrame 诊断
#ifdef _DEBUG
void CChildFrame::AssertValid() const
{
CMDIChildWnd::AssertValid();
}
void CChildFrame::Dump(CDumpContext& dc) const
{
CMDIChildWnd::Dump(dc);
}
#endif //_DEBUG
// CChildFrame 消息处理程序
MainFrm.cpp: CMainFrame 类的实现
// MainFrm.cpp: CMainFrame 类的实现
//
#include "pch.h"
#include "framework.h"
#include "123-wqy-MFC.h"
#include "MainFrm.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
// CMainFrame
IMPLEMENT_DYNAMIC(CMainFrame, CMDIFrameWnd)
BEGIN_MESSAGE_MAP(CMainFrame, CMDIFrameWnd)
ON_WM_CREATE()
END_MESSAGE_MAP()
static UINT indicators[] =
{
ID_SEPARATOR, // 状态行指示器
ID_INDICATOR_CAPS,
ID_INDICATOR_NUM,
ID_INDICATOR_SCRL,
};
// CMainFrame 构造/析构
CMainFrame::CMainFrame() noexcept
{
// TODO: 在此添加成员初始化代码
}
CMainFrame::~CMainFrame()
{
}
int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CMDIFrameWnd::OnCreate(lpCreateStruct) == -1)
return -1;
if (!m_wndToolBar.CreateEx(this, TBSTYLE_FLAT, WS_CHILD | WS_VISIBLE | CBRS_TOP | CBRS_GRIPPER | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC) ||
!m_wndToolBar.LoadToolBar(IDR_MAINFRAME))
{
TRACE0("未能创建工具栏\n");
return -1; // 未能创建
}
if (!m_wndStatusBar.Create(this))
{
TRACE0("未能创建状态栏\n");
return -1; // 未能创建
}
m_wndStatusBar.SetIndicators(indicators, sizeof(indicators)/sizeof(UINT));
// TODO: 如果不需要可停靠工具栏,则删除这三行
m_wndToolBar.EnableDocking(CBRS_ALIGN_ANY);
EnableDocking(CBRS_ALIGN_ANY);
DockControlBar(&m_wndToolBar);
return 0;
}
BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs)
{
if( !CMDIFrameWnd::PreCreateWindow(cs) )
return FALSE;
// TODO: 在此处通过修改
// CREATESTRUCT cs 来修改窗口类或样式
return TRUE;
}
// CMainFrame 诊断
#ifdef _DEBUG
void CMainFrame::AssertValid() const
{
CMDIFrameWnd::AssertValid();
}
void CMainFrame::Dump(CDumpContext& dc) const
{
CMDIFrameWnd::Dump(dc);
}
#endif //_DEBUG
// CMainFrame 消息处理程序
pch.cpp: 与预编译标头对应的源文件
// pch.cpp: 与预编译标头对应的源文件
#include "pch.h"
// 当使用预编译的头时,需要使用此源文件,编译才能成功。