7 颜色填充功能
油漆桶功能主要应用了FloodFill函数,该函数的功能是用当前刷从点(x, y)开始向四周填充到颜色为crColor的边界。其中形参m_PointBegin.x和m_PointBegin.y记录了鼠标单击时的位置,m_PenColor记录了之前绘制图形所用的铅笔颜色,这样FloodFill函数就会从鼠标单击时的位置开始如同漫水一样漫向四周,直到之前的铅笔颜色为止。这样就实现了颜色填充功能。
具体实现代码如下:
在OnLButtonUp() 中添加如下代码:
case DrawType::Fill:
{
CClientDC dc(this);
CBrush newBrush(m_BrushColor);
oldBrush = dc.SelectObject(&newBrush);
dc.SelectObject(newBrush);
dc.FloodFill(m_PointBegin.x, m_PointBegin.y, m_PenColor);
dc.SelectObject(oldBrush);
}
实现效果:
8 选择画笔颜色
在设置画笔颜色的时候我们首先要定义一个CColorDialog对象,这是一个对话框,包含系统定义的颜色的列表,如图所示。当dlg.DoModal()==IDOK时,也就是说对话框弹出来了,并且你点击了对话框上的OK按钮,然后就执行m_PenColor=dlg.GetColor(),将画笔的颜色设置为你选择的颜色。
具体实现如下:
void CMFC_PAINTView::OnMenucolor()
{
CColorDialog dlg;
if (IDOK == dlg.DoModal()) //弹出对话框
{
m_PenColor = dlg.GetColor();//得到颜色
}
}
//在OnMouseMove()中和OnLButtonUp()中都需要添加以下代码:
CPen newPen, *oldPen;
newPen.CreatePen(PS_SOLID, m_PenSize, m_PenColor);
oldPen = dc.SelectObject(&newPen);
//因为是局部变量,所以可以同名。
//在函数最后加dc.SelectObject(oldPen);
效果如下:

9 设置画笔粗细
画笔的粗细设置也和颜色相类似,我们先创建一个对话框,调用GetWindowText函数获取用户输入的值,然后将m_PenSize的值设置为获取到的值,这样就改变了画笔的粗细。
//首先需要创建一个对话框,然后添加一个示例编辑框,给这个框添加一个类CSetPenSizeDialog和变量m_Edit
void CSetPenSizeDialog::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
DDX_Control(pDX, IDC_EDIT1, m_Edit);
CString str;
m_Edit.GetWindowText(str);
m_PenSize = _ttoi(str);
}
//添加事件处理程序,生成函数OnMenuSize(),在View.cpp中得包含头文件“CSetPenSizeDialog.h”
void CMFC_PAINTView::OnMenusize()
{
CSetPenSizeDialog dlg;
if (IDOK == dlg.DoModal()) {
this->m_PenSize = dlg.m_PenSize;
}
}
效果如下:

10 将绘制出来的图形保存的实现
1、CreateCompatibleDC 该函数创建一个与指定设备兼容的内存设备上下文环境(DC);
2、filterindex是“打开”或“另存为”对话框(CommonDialog控件)中的一个缺省的过滤器,来打开或者保存文件的文件扩展名。要使用这个属性值,就必须先给filter属性赋值。
添加事件处理程序,生成函数OnFileSave():
void CMFC_PAINTView::OnFileSave()
{
CClientDC dc(this);
CRect rect;
BOOL showMsgTag; //是否要弹出”图像保存成功对话框"
BOOL saveTag;
CString saveFilePath;
GetClientRect(&rect); //获取画布大小
HBITMAP hbitmap = CreateCompatibleBitmap(dc, rect.right - rect.left, rect.bottom - rect.top);
//创建兼容位图
HDC hdc = CreateCompatibleDC(dc); //创建兼容DC,以便将图像保存为不同的格式
HBITMAP hOldMap = (HBITMAP)SelectObject(hdc, hbitmap);
//将位图选入DC,并保存返回值
BitBlt(hdc, 0, 0, rect.right - rect.left, rect.bottom - rect.top, dc, 0, 0, SRCCOPY);
//将屏幕DC的图像复制到内存DC中
CImage image;
image.Attach(hbitmap); //将位图转化为一般图像
saveTag = FALSE;
if (!saveTag) //如果图像是第一次被写入,则打开对话框
{
showMsgTag = TRUE;
CString strFilter = _T("位图文件|*.bmp|JPEG 图像文件|*.jpg|GIF图像文件 | *.gif | PNG图像文件 | *.png |其他格式| *.* |");
CFileDialog dlg(FALSE, _T("bmp"), _T("iPaint1.bmp"), NULL, strFilter);
if (dlg.DoModal() != IDOK)
return;
CString strFileName; //如果用户没有指定文件扩展名,则为其添加一个
CString strExtension;
strFileName = dlg.m_ofn.lpstrFile;
if (dlg.m_ofn.nFileExtension = 0) //扩展名项目为0
{
switch (dlg.m_ofn.nFilterIndex)
{
case 1:
strExtension = "bmp"; break;
case 2:
strExtension = "jpg"; break;
case 3:
strExtension = "gif"; break;
case 4:
strExtension = "png"; break;
default:
break;
}
strFileName = strFileName + "." + strExtension;
}
saveFilePath = strFileName; //saveFilePath为视类中的全局变量,类型为CString
}
else
{
showMsgTag = FALSE;
}
//AfxMessageBox(saveFilePath); //显示图像保存的全路径(包含文件名)
HRESULT hResult = image.Save(saveFilePath); //保存图像
if (FAILED(hResult))
{
MessageBox(_T("保存图像文件失败!"));
}
else
{
if (showMsgTag)
MessageBox(_T("文件保存成功!"));
}
image.Detach();
SelectObject(hdc, hOldMap);
}
效果如下:

11 添加位图
添加图片时,我们先调用GetPathName函数获取选择的文件的文件路径,然后通过LoadImage函数加载图片,用Attach(hBitmap)把位图资源句柄附加到hBitmap对象上,然后创建一个基于位图的画刷,最后就可将位图绘制在客户端。
//添加事件处理程序,生成函数OnFileOpen():
void CMFC_PAINTView::OnFileOpen()
{
m_DrawType = DrawType::myLoadImage;
CString strPath, filter; //打开文件,获得图片路径
filter = "bmp图片(*.bmp)|*.bmp||";
CFileDialog dlg(TRUE, NULL, NULL, OFN_HIDEREADONLY);
if (dlg.DoModal() == IDOK) {
strPath = dlg.GetPathName();
}
HBITMAP hBitmap = (HBITMAP)::LoadImage(NULL, strPath, IMAGE_BITMAP, 0, 0, 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);
}
效果如下: