画板的实现非常有趣,首先要新建一张HBITMAP来保存原来的绘制内容,然后需要创建一个可拉伸的输入框,供用户输入文字。必要时还得提供UnDo功能,供用户取消上一次绘制的功能。
利用业余时间,我制作了一个画板程序,包含了以下几个功能:
1. 可动态拉伸及移动位置的编辑框,供用户输入文字。
2. 可画直线,圆圈,箭头,线段及线条。
3. 可使用CTRL+Z组合键,撤销上一次的绘制。
此画板还有些地方需要进行完善,它们是:
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);
3. 模板CResizeCtrlImpl,负责拦截CEdit控件的鼠标消息,然后在CEdit周围画虚线及拉伸点。供用户进行拉伸及移动操作。
CEdit首先继承CResizeCtrlImpl:
class CBitmapEdit : public CWindowImpl,
public CResizeCtrlImpl,
public CDoubleBufferImpl
// Draw resize control.
void DrawResizeControl(Graphics& g)
{
if (!m_bEnable)
{
return;
}
T* pT = static_cast(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]);
}
}
编译该程序前,您需要安装WTL9.0开发包。下载地址:http://download.csdn.net/detail/renstarone/6958327
源代码下载地址:http://download.csdn.net/detail/renstarone/6958583