首先在view.h文件里面进行声明
// 操作
public:
int m_PenSize;//画笔
COLORREF m_PenColor, m_BrushColor;//填充
CPoint m_PointBegin, m_PointEnd;//画圆enum class DrawType {
LineSegment,Circle,Rectangle,Ellips,Pencil,Text,Eraser,myLoadImage,Magnify
}m_DrawType;//绘制功能int m_TextId;
CEdit* m_Edit = nullptr;
CPoint m_TextPos = CPoint(0, 0);//设置文本框初值CPoint m_MagnifyCenter = CPoint(0, 0);
int m_MagnifyWidth = 600;
int m_MagnifyHeight = 400;//设置放大框的初值
在生成的消息映射函数中加入
CRect* GetMagnifyRect(CPoint&);
接下来在view.cpp文件中进行操作
首先依旧是对画笔功能进行初始化
CMFCTest1View::CMFCTest1View() noexcept
{
// TODO: 在此处添加构造代码
m_PenSize = 1;
m_PenColor = RGB(0, 0, 0);
m_BrushColor = RGB(0, 0, 0);
m_PointBegin = CPoint(0, 0);
m_PointEnd = CPoint(0, 0);
m_DrawType = DrawType::LineSegment;
m_TextId = 10086;
}
CMFCTest1View::~CMFCTest1View()
{
if (m_Edit != nullptr) {
delete m_Edit;
m_Edit = nullptr;
}
}
在解决方案资源管理器中的资源文件找到.rc后缀文件,点开后在找到Menu,再点击其中的内容,设置按钮,如下图所示:
设置好按钮后依次为各项功能添加事件处理程序,此时在view.cpp文件中会产生相应函数
我们为每项功能的函数进行补充
//绘制线条
void CMFCTest1View::OnDrawLineSegment()
{
m_DrawType = DrawType::LineSegment;
// TODO: 在此添加命令处理程序代码
}//绘制长方形
void CMFCTest1View::OnDrawRectangle()
{
m_DrawType = DrawType::Rectangle;
// TODO: 在此添加命令处理程序代码
}//绘制圆
void CMFCTest1View::OnDrawCircle()
{
m_DrawType = DrawType::Circle;
// TODO: 在此添加命令处理程序代码
}//绘制椭圆
void CMFCTest1View::OnDrawEllipse()
{
m_DrawType = DrawType::Ellips;
// TODO: 在此添加命令处理程序代码
}//选择颜色
void CMFCTest1View::OnSetColor()
{
// TODO: 在此添加命令处理程序代码
CColorDialog dlg;
if (IDOK == dlg.DoModal()) {
m_PenColor = dlg.GetColor();}
}//设置尺寸
void CMFCTest1View::OnSetPenSize()
{
// TODO: 在此添加命令处理程序代码
CSetPenSizeDialog dlg;
if (IDOK == dlg.DoModal()) {
this->m_PenSize = dlg.m_PenSize;
}
}//绘制文本框
void CMFCTest1View::OnText()
{
m_DrawType = DrawType::Text;
// TODO: 在此添加命令处理程序代码
}//传递文本框内容
BOOL CMFCTest1View::PreTranslateMessage(MSG* pMsg)
{
// TODO: 在此添加专用代码和/或调用基类
if (pMsg->message == WM_KEYDOWN && pMsg->wParam == VK_RETURN)
{
if (m_DrawType == DrawType::Text)
{
CString pStr;
m_Edit->GetWindowTextW(pStr);
delete m_Edit;
m_Edit = nullptr;CClientDC dc(this);
dc.TextOutW(m_TextPos.x, m_TextPos.y, pStr);return TRUE;
}
}return CView::PreTranslateMessage(pMsg);
}//创建画笔
void CMFCTest1View::OnSetPencil()
{
// TODO: 在此添加命令处理程序代码
m_DrawType = DrawType::Pencil;
}//创建橡皮擦
void CMFCTest1View::OnSetEraser()
{
// TODO: 在此添加命令处理程序代码
m_DrawType = DrawType::Eraser;
}//打开文件
void CMFCTest1View::OnFileOpen()
{
// TODO: 在此添加命令处理程序代码
m_DrawType = DrawType::myLoadImage;CString filter, strPath;
filter = "bmp图片(*.bmp)|*.bmp||";
CFileDialog dlg(TRUE, NULL, NULL, OFN_HIDEREADONLY, filter);
if (dlg.DoModal() == IDOK)
{
strPath = dlg.GetPathName();
}HBITMAP hBitmap = (HBITMAP)::LoadImage(NULL, strPath,IMAGE_BITMAP,0,0,
LR_DEFAULTCOLOR | LR_CREATEDIBSECTION | LR_LOADFROMFILE);CBitmap loadImageBitmap;
loadImageBitmap.Attach(hBitmap);BITMAP bitMap;
loadImageBitmap.GetBitmap(&bitMap);CBrush newBrush, * oldBrush;
newBrush.CreatePatternBrush(&loadImageBitmap);
CClientDC dc(this);
oldBrush = (CBrush*)dc.SelectObject(&newBrush);dc.Rectangle(0, 0, bitMap.bmWidth, bitMap.bmHeight);
dc.SelectObject(oldBrush);
}//放大框功能
void CMFCTest1View::OnMagnify()
{
// TODO: 在此添加命令处理程序代码
m_DrawType = DrawType::Magnify;
}//设置放大框属性
CRect* CMFCTest1View::GetMagnifyRect(CPoint& p_Msg)
{
CRect rect;
GetClientRect(&rect);CPoint leftTop, rightBottom;
leftTop.x = p_Msg.x - m_MagnifyWidth / 2;
rightBottom.x = p_Msg.x + m_MagnifyWidth / 2;
leftTop.y = p_Msg.y - m_MagnifyHeight / 2;
rightBottom.y = p_Msg.y + m_MagnifyHeight / 2;if (leftTop.x < 0) {
leftTop.x = 0;
rightBottom.x = leftTop.x + m_MagnifyWidth;
}
else if (rightBottom.x > rect.right) {
rightBottom.x = rect.right;
leftTop.x = rightBottom.x - m_MagnifyWidth;
}
if (leftTop.y < 0) {
leftTop.y = 0;
rightBottom.y = leftTop.y + m_MagnifyHeight;
}
else if (rightBottom.y > rect.bottom) {
rightBottom.y = rect.bottom;
leftTop.y = rightBottom.y - m_MagnifyHeight;
}
CRect* r_Rect = new CRect(leftTop, rightBottom);return r_Rect;
}
根据以下代码添加相应类向导,其作用是在鼠标按下、移动、松开时绘制出相应功能的线条、文本框等
void CMFCTest1View::OnLButtonDown(UINT nFlags, CPoint point)
{
// TODO: 在此添加消息处理程序代码和/或调用默认值
m_PointBegin = m_PointEnd = point;
m_TextPos = point;
m_MagnifyCenter = point;switch (m_DrawType) {
case DrawType::Magnify:
{
CClientDC dc(this);
dc.SetROP2(R2_NOTXORPEN);CPen newPen, * oldPen;
newPen.CreatePen(PS_SOLID, m_PenSize, m_PenColor);
oldPen = dc.SelectObject(&newPen);dc.SelectStockObject(5);
CRect* rectUndraw = GetMagnifyRect(m_MagnifyCenter);
dc.Rectangle(rectUndraw);dc.SelectObject(oldPen);
delete rectUndraw;break;
}
}
CView::OnLButtonDown(nFlags, point);
}
void CMFCTest1View::OnMouseMove(UINT nFlags, CPoint point)
{
// TODO: 在此添加消息处理程序代码和/或调用默认值
if (nFlags & MK_LBUTTON) {
CClientDC dc(this);
CPen newPen, * oldPen;
newPen.CreatePen(PS_SOLID, m_PenSize, m_PenColor);
oldPen = dc.SelectObject(&newPen);switch (m_DrawType) {
case DrawType::LineSegment:dc.SetROP2(R2_NOTXORPEN);
dc.MoveTo(m_PointBegin);
dc.LineTo(m_PointEnd);dc.MoveTo(m_PointBegin);
dc.LineTo(point);m_PointEnd = point;
break;case DrawType::Rectangle:
{
dc.SetROP2(R2_NOTXORPEN);
dc.SelectStockObject(5);CRect rectP1(m_PointBegin, m_PointEnd);
dc.Rectangle(rectP1);CRect rectP2(m_PointBegin, point);
dc.Rectangle(rectP2);m_PointEnd = point;
break;}
case DrawType::Ellips:
{
dc.SetROP2(R2_NOTXORPEN);
dc.SelectStockObject(5);CRect rectP1(m_PointBegin, m_PointEnd);
dc.Ellipse(rectP1);CRect rectP2(m_PointBegin, point);
dc.Ellipse(rectP2);m_PointEnd = point;
break;}
case DrawType::Circle:
{
dc.SetROP2(R2_NOTXORPEN);
dc.SelectStockObject(5);int length_1 = m_PointEnd.y - m_PointBegin.y;
if (m_PointEnd.x < m_PointBegin.x) {
m_PointEnd.x = m_PointBegin.x - abs(length_1);
}
else {
m_PointEnd.x = m_PointBegin.x + abs(length_1);
}CRect rectP1(m_PointBegin, m_PointEnd);
dc.Ellipse(rectP1);int length_2 = point.y - m_PointBegin.y;
if (point.x < m_PointBegin.x) {
m_PointEnd.x = m_PointBegin.x - abs(length_2);
}
else {
m_PointEnd.x = m_PointBegin.x + abs(length_2);
}
m_PointEnd.y = point.y;CRect rectP2(m_PointBegin, m_PointEnd);
dc.Ellipse(rectP2);m_PointEnd = point;
break;}
case DrawType::Text:
{
if (m_Edit != nullptr ) {
delete m_Edit;
}CEdit* myEdit = new CEdit();//新建edit对象
myEdit->Create(WS_CHILD | WS_VISIBLE | WS_BORDER, CRect(m_PointBegin, point), this, m_TextId);//设置文本框模式m_Edit = myEdit;
myEdit->ShowWindow(SW_SHOW);
break;
}
case DrawType::Pencil:
{
m_PointBegin = m_PointEnd;
m_PointEnd = point;
dc.MoveTo(m_PointBegin);
dc.LineTo(m_PointEnd);
break;
}case DrawType::Eraser:
{
COLORREF pColor = dc.GetBkColor();
CPen newPen(PS_SOLID, m_PenSize, pColor);
dc.SelectObject(&newPen);
m_PointBegin = m_PointEnd;
m_PointEnd = point;
dc.MoveTo(m_PointBegin);
dc.LineTo(m_PointEnd);
break;
}case DrawType::Magnify:
{
dc.SetROP2(R2_NOTXORPEN);
dc.SelectStockObject(5);CRect* rectUndraw = GetMagnifyRect(m_MagnifyCenter);
dc.Rectangle(rectUndraw);
delete rectUndraw;CRect* rectDraw = GetMagnifyRect(point);
dc.Rectangle(rectDraw);
delete rectDraw;m_MagnifyCenter = point;
break;
}default:
break;
}
dc.SelectObject(oldPen);
}CView::OnMouseMove(nFlags, point);
}
void CMFCTest1View::OnLButtonUp(UINT nFlags, CPoint point)
{
// TODO: 在此添加消息处理程序代码和/或调用默认值CClientDC dc(this);
CPen newPen, * oldPen;
newPen.CreatePen(PS_SOLID, m_PenSize, m_PenColor);
oldPen = dc.SelectObject(&newPen);switch (m_DrawType) {
case DrawType::LineSegment:dc.MoveTo(m_PointBegin);
dc.LineTo(point);break;
case DrawType::Rectangle:
{
dc.SelectStockObject(PS_NULL);
CRect rectP2(m_PointBegin, point);
dc.Rectangle(rectP2);break;
}case DrawType::Ellips:
{
dc.SelectStockObject(PS_NULL);
CRect rectP2(m_PointBegin, point);
dc.Ellipse(rectP2);break;
}case DrawType::Circle:
{
dc.SelectStockObject(5);int length_2 = point.y - m_PointBegin.y;
if (point.x < m_PointBegin.x) {
m_PointEnd.x = m_PointBegin.x - abs(length_2);
}
else {
m_PointEnd.x = m_PointBegin.x + abs(length_2);
}
m_PointEnd.y = point.y;CRect rectP2(m_PointBegin, m_PointEnd);
dc.Ellipse(rectP2);m_PointEnd = point;
break;}
case DrawType::Text:
{
CEdit* myEdit = new CEdit();//新建edit对象
myEdit->Create(WS_CHILD | WS_VISIBLE | WS_BORDER, CRect(m_PointBegin, point), this, m_TextId);//设置文本框模式
myEdit->ShowWindow(SW_SHOW);if (nullptr != m_Edit) {
delete m_Edit;
}m_Edit = myEdit;
break;
}
case DrawType::Magnify:
{
dc.SetROP2(R2_NOTXORPEN);
dc.SelectStockObject(5);CRect* rectUndraw = GetMagnifyRect(m_MagnifyCenter);
dc.Rectangle(rectUndraw);CRect rect;
GetClientRect(&rect);CDC * pDC = GetDC();
dc.StretchBlt(0, 0, rect.Width(), rect.Height(), pDC, rectUndraw->left, rectUndraw->top, rectUndraw->Width(), rectUndraw->Height(), SRCCOPY);
delete rectUndraw;
ReleaseDC(pDC);
break;
}default:
break;
}oldPen = dc.SelectObject(oldPen);
CView::OnLButtonUp(nFlags, point);
}
最后让我们一起看看功能实现的样子
放大后效果图