绘图
void CMyView::OnLButtonUp(UINT nFlags, CPoint point) { // TODO: Add your message handler code here and/or call default //MessageBox("WM_LBUTTONUP"); // // 1:利用SDK全局函数实现画线功能 // HDC hdc; hdc = ::GetDC(m_hWnd); ::MoveToEx(hdc,m_ptOld.x,m_ptOld.y,NULL); ::LineTo(hdc,point.x,point.y); ::ReleaseDC(m_hWnd,hdc); // 2:利用MFC的CDC类实现画线功能 // CDC *pDC = GetDC(); pDC->MoveTo(m_ptOld); pDC->LineTo(point); ReleaseDC(pDC); // 3:利用MFC的CClientDC类实现画线功能 // CClientDC dc(this); dc.MoveTo(m_ptOld); dc.LineTo(point); // 4:利用MFC的CWindowDC类实现画线功能 // CWindowDC dc_2(this); dc_2.MoveTo(m_ptOld); dc_2.LineTo(point); // 5:利用MFC的CWindowDC类在父窗口中实现画线功能 // CWindowDC dc_3(GetParent()); dc_3.MoveTo(m_ptOld); dc_3.LineTo(point); // 6:利用MFC的CWindowDC类在桌面窗口中实现画线功能 // CWindowDC dc_4(GetDesktopWindow()); dc_4.MoveTo(m_ptOld); dc_4.LineTo(point); CView::OnLButtonUp(nFlags, point); }
现在来分析上面的代码。
1:首先想想要完成画线这样一个功能该怎么做呢?
从按下鼠标左键开始,移动鼠标至另一位置,松开鼠标左键,整个操作过程就是要PC实现画线的充分条件;PC处理完成后通过显示屏展现结果。到此为止,我们接触的全是硬件(操作的鼠标、看到的屏幕)。难道我们直接和硬件打交道吗?NO!和硬件打交道的是OS,我们只要和OS打交道就行了,OS就是人与机器之间的翻译员。
2:上面代码就是跟OS交流的语言,告诉OS我要干什么,怎么干。然后OS翻译我们的意思给机器,之后机器就把事情干好了。
3:我要操作系统这么做。
// 1:利用SDK全局函数实现画线功能 // HDC hdc;//设备上下文句柄 hdc = ::GetDC(m_hWnd);//把窗口和设备上下文句柄关联起来 ::MoveToEx(hdc,m_ptOld.x,m_ptOld.y,NULL);//初始化点的位置 ::LineTo(hdc,point.x,point.y);//移动到这个点 ::ReleaseDC(m_hWnd,hdc);//释放句柄资源
OS把上面的代码翻译成机器代码给机器看,机器一看,哦,这样哦。
4:上面代码中2到6的方法都是依据方法1为基础的。MFC把API函数封装到类中,就造出了CDC,CClientDC...等等这样的类。它们工作原理都差不多,如下:在构造函数中完成窗口与设备上下文句柄的关联工作,在MoveTo中调用API函数MoveTo,在LineTo函数中调用API函数LineTo,具体情况请看源代码。
void CMyView::OnLButtonUp(UINT nFlags, CPoint point) { // TODO: Add your message handler code here and/or call default // 设备描述表(Device Context,DC)是一个信息结构体,包含物理输出设备及其驱动程序。 // 在Windows平台下,所有的的图形操作都是通过它完成。 //MessageBox("WM_LBUTTONUP"); // // 绘制彩色线条 // //CPen pen(PS_SOLID,10,RGB(255,0,0));// PS_SOLID实心 CPen pen(PS_DASH,1,RGB(255,0,0));// PS_DASH虚线,宽度<=1时才有效。 CClientDC dc(this); CPen *pOldPen = dc.SelectObject(&pen); dc.MoveTo(m_ptOld); dc.LineTo(point); dc.SelectObject(pOldPen); // 使用画刷绘图 // CBrush brush(RGB(0,255,0));// 共有4个构造函数 CBrush *oldBrush; oldBrush = dc.SelectObject(&brush);// 先把自己定义的画刷选到设备描述表 dc.FillRect(CRect(m_ptOld,point),NULL);// 用自己定义的画刷 //dc.FillRect(CRect(m_ptOld,point),&brush);// 指定画刷 //dc.FillRect(CRect(m_ptOld,point),NULL);// 系统最初默认的画刷颜色是白色 // 位图画刷 // CBitmap bitmap; bitmap.LoadBitmap(IDB_BITMAP1); CBrush brush_2(&bitmap); dc.FillRect(CRect(m_ptOld,point),&brush_2); // 透明画刷 // dc.Rectangle(CRect(m_ptOld,point)); // 画刷句柄转换为画刷对象 // CBrush *pBrush = CBrush::FromHandle((HBRUSH)GetStockObject(NULL_BRUSH)); oldBrush = dc.SelectObject(pBrush); dc.Rectangle(CRect(m_ptOld,point)); m_bDraw = FALSE; CView::OnLButtonUp(nFlags, point); }
void CMyView::OnMouseMove(UINT nFlags, CPoint point) { // TODO: Add your message handler code here and/or call default //MessageBox("WM_MOUSEMOVE"); // 绘制连续线条 CClientDC dc(this); if (TRUE == m_bDraw) { dc.MoveTo(m_ptOld); dc.LineTo(point); m_ptOld = point; } CView::OnMouseMove(nFlags, point); }