天天看点

VC++界面编程之--实现一个画板并提供文字输入功能(MsPaint)

画板的实现非常有趣,首先要新建一张HBITMAP来保存原来的绘制内容,然后需要创建一个可拉伸的输入框,供用户输入文字。必要时还得提供UnDo功能,供用户取消上一次绘制的功能。

利用业余时间,我制作了一个画板程序,包含了以下几个功能:

1. 可动态拉伸及移动位置的编辑框,供用户输入文字。

2. 可画直线,圆圈,箭头,线段及线条。

3. 可使用CTRL+Z组合键,撤销上一次的绘制。

VC++界面编程之--实现一个画板并提供文字输入功能(MsPaint)

此画板还有些地方需要进行完善,它们是:

1. 绘制时是刷新全部绘制区域,最好是刷新当前绘制区域。

2. 输入的文字,没有实现动态绘制到画板的功能,留给读者自己去实现。

3. 创建的绘制区域,是直接在主窗口上进行绘制的,理想的情况应该是新建一个子窗口,进行绘制。因为主窗口的边框的长和宽,影响到了输入框位置的计算。

以下是一些实现的技术细节:

1. 类CCanvas将每一次的绘制内容,都保存到了一个CBitmap中,方便下一次的绘制。GDI绘制的圆圈和线条有锯齿,不好看。所以先我用GDI+进行了绘制,绘制完成后才将GDI+的Bitmap转换为GDI的CBitmap。当然,也是为了加快窗口的绘制速度。

// Turn GDI+ bitmap to GDI bitmap to let draw old faster.
		m_bmpOld.get()->GetHBITMAP((ARGB)Color::Transparent, &m_bmpCache.m_hBitmap);
           

2. 模板CCanvasWndImpl,负责在主窗口上面,创建一个CCanvas绘制对象,并截获主窗口的鼠标消息,进行绘制。这里我也许应该创建一个子窗口,因为主窗口是有边框的,动态计算画布的位置时,需要将边框的长和宽考虑在内。

3. 模板CResizeCtrlImpl,负责拦截CEdit控件的鼠标消息,然后在CEdit周围画虚线及拉伸点。供用户进行拉伸及移动操作。

CEdit首先继承CResizeCtrlImpl:

class CBitmapEdit : public CWindowImpl<CBitmapEdit>,
					public CResizeCtrlImpl<CBitmapEdit>,
					public CDoubleBufferImpl<CBitmapEdit>
           

然后在DoPait方法中调用CResizeCtrlImpl类中的DrawResizeControl(Graphics& g)方法,即可画出虚线边框及拉伸点。

// Draw resize control.
	void DrawResizeControl(Graphics& g)
	{
		if (!m_bEnable)
		{
			return;
		}

		T* pT = static_cast<T*>(this);
		pT->GetClientRect(&m_rcClient);
		m_rcClient.DeflateRect(m_nBorder, m_nBorder, m_nBorder, m_nBorder);

		// Draw border with dash style.
		Pen pen(m_clrBorder, (REAL)m_nBorder);
		pen.SetDashStyle(DashStyleDash);
		pen.SetAlignment(PenAlignmentInset);

		g.DrawRectangle(&pen, m_rcClient);

		// Draw dragging rectangle.
		SolidBrush br(Color::AliceBlue);
		for (UINT nIndex = 0; nIndex < m_szBlocks.size(); ++nIndex)
		{
			g.FillRectangle(&br, m_szBlocks[nIndex]);
		}
	}
           

最后,就如文章开头所说,该程序还有一些没有实现的地方和缺陷。希望朋友们不要介意

VC++界面编程之--实现一个画板并提供文字输入功能(MsPaint)

编译该程序前,您需要安装WTL9.0开发包。下载地址:http://download.csdn.net/detail/renstarone/6958327

源代码下载地址:http://download.csdn.net/detail/renstarone/6958583