[MFC]Squres程序:单文档界面演示

本文通过Squares应用程序详细讲解了MFC环境下如何创建单文档界面程序。程序包含一个4×4网格,用户可选择6种颜色填充格子,点击保存的.sqr文件记录网格颜色状态。创建过程涉及设置Document/View架构,修改CSquresDocument和CSquresView类,其中CSquresView需处理鼠标左击事件。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1. 接下来将展示Squres应用程序来说明单文档界面程序的编写:

    1) 视图用来显示一个4×4的网格,初始化时每个网格都是白色的(即新建文档时);

    2) 菜单栏中有一个Color子菜单,可以选择当前要填充的颜色,总共共有6中,而初始时默认将红色作为当前填充色;

    3) 可以用鼠标点击网格中的格子,之后会用当前选中的填充色来填充选中的格子;

    4) 程序文档的后缀是.sqr,里面就保存4×4网格中各个格子的颜色,以及当前选中的填充色;


2. 程序的创建:

    1) 还是选择MFC[.exe]模板;

    2) 第一步中选择Single document选项,并且要选中Document/View architecture support?复选框;

    3) 而在第3步中的Advanced选项卡中填写默认的文件扩展名.sqr就行了(Wizzard会自动将该扩展名写入程序的字符串资源当中);

    4) 由于程序简单,只需要修改Document类和View类即可;


3. CSquresDocument:

.h:

// SquresDoc.h : interface of the CSquresDoc class
//
/////////////////////////////////////////////////////////////////////////////

#if !defined(AFX_SQURESDOC_H__29091B77_23ED_4908_817F_F58907F39F60__INCLUDED_)
#define AFX_SQURESDOC_H__29091B77_23ED_4908_817F_F58907F39F60__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000


class CSquresDoc : public CDocument
{
protected: // create from serialization only
	CSquresDoc();
	DECLARE_DYNCREATE(CSquresDoc)

// Attributes
public:

// Operations
public:

// Overrides
	// ClassWizard generated virtual function overrides
	//{{AFX_VIRTUAL(CSquresDoc)
	public:
	virtual BOOL OnNewDocument();
	virtual void Serialize(CArchive& ar);
	//}}AFX_VIRTUAL

// Implementation
public:
	COLORREF GetCurrentColor(); // 获取当前选中的颜色
	void SetSquareColor(COLORREF color, int i, int j); // 修改某一网格的颜色
	COLORREF GetSquareColor(int i, int j); // 获取某一网格的颜色
	virtual ~CSquresDoc();
#ifdef _DEBUG
	virtual void AssertValid() const;
	virtual void Dump(CDumpContext& dc) const;
#endif

protected:

// Generated message map functions
protected:
	static COLORREF clrChoiceOnly[6]; // 保存只能选择的6中颜色
	COLORREF m_clrGrid[4][4]; // 4×4的网格,存放每个格子中的颜色
	COLORREF m_clrCurrentColor; // 当前选中的颜色
	//{{AFX_MSG(CSquresDoc)
		// NOTE - the ClassWizard will add and remove member functions here.
		//    DO NOT EDIT what you see in these blocks of generated code !
	//}}AFX_MSG
	afx_msg void OnColor(UINT nID); // 选中Color菜单
	afx_msg void OnUpdateColor(CCmdUI* pCmdUI); // 更新Color菜单项(单选按钮选中)
	DECLARE_MESSAGE_MAP()
};

/////////////////////////////////////////////////////////////////////////////

//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.

#endif // !defined(AFX_SQURESDOC_H__29091B77_23ED_4908_817F_F58907F39F60__INCLUDED_)

.cpp:

// SquresDoc.cpp : implementation of the CSquresDoc class
//

#include "stdafx.h"
#include "Squres.h"

#include "SquresDoc.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

COLORREF CSquresDoc::clrChoiceOnly[6] = {
	RGB(255, 0, 0), // 红
	RGB(255, 255, 0), // 黄
	RGB(0, 255, 0), // 绿
	RGB(0, 255, 255), // 青黄
	RGB(0, 0, 255), // 蓝
	RGB(255, 255, 255) // 白
};

/////////////////////////////////////////////////////////////////////////////
// CSquresDoc

IMPLEMENT_DYNCREATE(CSquresDoc, CDocument)

BEGIN_MESSAGE_MAP(CSquresDoc, CDocument)
	//{{AFX_MSG_MAP(CSquresDoc)
		// NOTE - the ClassWizard will add and remove mapping macros here.
		//    DO NOT EDIT what you see in these blocks of generated code!
	//}}AFX_MSG_MAP
	ON_COMMAND_RANGE(ID_COLOR_RED, ID_COLOR_WHITE, OnColor)
	ON_UPDATE_COMMAND_UI_RANGE(ID_COLOR_RED, ID_COLOR_WHITE, OnUpdateColor)
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CSquresDoc construction/destruction

CSquresDoc::CSquresDoc()
{
	// TODO: add one-time construction code here

}

CSquresDoc::~CSquresDoc()
{
}

BOOL CSquresDoc::OnNewDocument()
{
	if (!CDocument::OnNewDocument())
		return FALSE;

	// TODO: add reinitialization code here
	// (SDI documents will reuse this document)
	// 对于新建的文档,颜色都初始化为白色
	for (int i = 0; i < 4; i++)
		for (int j = 0; j < 4; j++)
			m_clrGrid[i][j] = RGB(255, 255, 255);
	m_clrCurrentColor = RGB(255, 0, 0); // 而当前颜色初始化为红色

	return TRUE;
}



/////////////////////////////////////////////////////////////////////////////
// CSquresDoc serialization

// 串行化时先串行化网格最后再串行化当前颜色
void CSquresDoc::Serialize(CArchive& ar)
{
	if (ar.IsStoring())
	{
		// TODO: add storing code here
		for (int i = 0; i < 4; i++)
			for (int j = 0; j < 4; j++)
				ar << m_clrGrid[i][j];
		ar << m_clrCurrentColor;
	}
	else
	{
		// TODO: add loading code here
		for (int i = 0; i < 4; i++)
			for (int j = 0; j < 4; j++)
				ar >> m_clrGrid[i][j];
		ar >> m_clrCurrentColor;		
	}
}

/////////////////////////////////////////////////////////////////////////////
// CSquresDoc diagnostics

#ifdef _DEBUG
void CSquresDoc::AssertValid() const
{
	CDocument::AssertValid();
}

void CSquresDoc::Dump(CDumpContext& dc) const
{
	CDocument::Dump(dc);
}
#endif //_DEBUG

/////////////////////////////////////////////////////////////////////////////
// CSquresDoc commands

COLORREF CSquresDoc::GetSquareColor(int i, int j)
{
	ASSERT(0 <= i && i <= 3 && 0 <= j && j <= 3);
	return m_clrGrid[i][j];
}

void CSquresDoc::SetSquareColor(COLORREF color, int i, int j)
{
	ASSERT(0 <= i && i <= 3 && 0 <= j && j <= 3);
	m_clrGrid[i][j] = color;
	// 颜色修改后需要及时更新视图
	SetModifiedFlag(TRUE);
	UpdateAllViews(NULL);
}

COLORREF CSquresDoc::GetCurrentColor()
{
	return m_clrCurrentColor;
}

void CSquresDoc::OnColor(UINT nID)
{
	m_clrCurrentColor = clrChoiceOnly[nID - ID_COLOR_RED];
}

void CSquresDoc::OnUpdateColor(CCmdUI* pCmdUI)
{
	pCmdUI->SetRadio(m_clrCurrentColor == clrChoiceOnly[pCmdUI->m_nID - ID_COLOR_RED]);
}


4. CSquresView:

.h:只需添加一个处理鼠标左击的处理程序即可

protected:
	//{{AFX_MSG(CSquresView)
	// 左键击中网格使之改变为当前选中的颜色
	afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
	//}}AFX_MSG
.cpp:

// SquresView.cpp : implementation of the CSquresView class
//

#include "stdafx.h"
#include "Squres.h"

#include "SquresDoc.h"
#include "SquresView.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// CSquresView

IMPLEMENT_DYNCREATE(CSquresView, CView)

BEGIN_MESSAGE_MAP(CSquresView, CView)
	//{{AFX_MSG_MAP(CSquresView)
	ON_WM_LBUTTONDOWN()
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CSquresView construction/destruction

CSquresView::CSquresView()
{
	// TODO: add construction code here

}

CSquresView::~CSquresView()
{
}

BOOL CSquresView::PreCreateWindow(CREATESTRUCT& cs)
{
	// TODO: Modify the Window class or styles here by modifying
	//  the CREATESTRUCT cs

	return CView::PreCreateWindow(cs);
}

/////////////////////////////////////////////////////////////////////////////
// CSquresView drawing

void CSquresView::OnDraw(CDC* pDC)
{
	CSquresDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	// TODO: add draw code for native data here

	pDC->SetMapMode(MM_LOENGLISH);

	for (int i = 0; i < 4; i++)
		for (int j = 0; j < 4; j++) {
			COLORREF color = pDoc->GetSquareColor(i, j);
			CBrush brush(color);

			int x1 = j * 100 + 50;
			int y1 = i * -100 - 50;
			int x2 = x1 + 100;
			int y2 = y1 - 100;
			CRect rect(x1, y1, x2, y2);
			pDC->FillRect(rect, &brush);
		}

	for (int x = 50; x <= 450; x += 100) {
		pDC->MoveTo(x, -50);
		pDC->LineTo(x, -450);
	}

	for (int y = -50; y >= -450; y -= 100) {
		pDC->MoveTo(50, y);
		pDC->LineTo(450, y);
	}
}

/////////////////////////////////////////////////////////////////////////////
// CSquresView diagnostics

#ifdef _DEBUG
void CSquresView::AssertValid() const
{
	CView::AssertValid();
}

void CSquresView::Dump(CDumpContext& dc) const
{
	CView::Dump(dc);
}

CSquresDoc* CSquresView::GetDocument() // non-debug version is inline
{
	ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CSquresDoc)));
	return (CSquresDoc*)m_pDocument;
}
#endif //_DEBUG

/////////////////////////////////////////////////////////////////////////////
// CSquresView message handlers

void CSquresView::OnLButtonDown(UINT nFlags, CPoint point) 
{
	// TODO: Add your message handler code here and/or call default
	
	CView::OnLButtonDown(nFlags, point);

	CClientDC dc(this);
	dc.SetMapMode(MM_LOENGLISH);
	CPoint pos = point;
	dc.DPtoLP(&pos); // 调整成逻辑位置

	// 先判断是否击中在网格内
	if (50 <= pos.x && pos.x <= 450 && -450 <= pos.y && pos.y <= -50) {
		int i = (-pos.y - 50) / 100;
		int j = (pos.x - 50) / 100;
		CSquresDoc* pDoc = GetDocument();
		COLORREF clrCurrentColor = pDoc->GetCurrentColor();
		pDoc->SetSquareColor(clrCurrentColor, i, j); // 设置新的网格颜色
	}
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值