您的位置:首页 > 编程语言

三. 简单绘图--Windows编程课程学习笔记

2016-06-20 15:20 537 查看

3.1 MFC消息映射机制

首先新建一个单文档类型的MFC APPWizard(exe)工程,取名MyMFCApp。试完成左键消息的捕捉。在

3.1.1 ClassWizard(类向导)

       项目->类向导。



有命令、消息、虚函数、成员变量、方法五个选项卡,此外,还可以添加类。

3.1.2 消息映射机制

用ClassWizard添加一个LButtonDown的响应函数,在源文件会增加以下代码。

1)  消息响应函数原型

在MyMFCAppView.h中

// 生成的消息映射函数
protected:
DECLARE_MESSAGE_MAP()
public:
afx_msg voidOnLButtonDown(UINT nFlags, CPoint point);


2)  ON_WM_LBUTTONDOWN消息映射宏

在MyMFCAppView.cpp中

BEGIN_MESSAGE_MAP(CMyMFCAppView, CView)
// 标准打印命令
ON_COMMAND(ID_FILE_PRINT,&CView::OnFilePrint)
ON_COMMAND(ID_FILE_PRINT_DIRECT, &CView::OnFilePrint)
ON_COMMAND(ID_FILE_PRINT_PREVIEW, &CView::OnFilePrintPreview)
ON_WM_LBUTTONDOWN()
END_MESSAGE_MAP()

在BEGAIN_MESSAGE_MAP到END_MESSAGE_MAP()两个宏之间定义了CMyMFCApp类的消息映射表。作用是把WM_LBUTTONDOWN与OnLButtonDown关联。

3)  消息响应函数的定义

void CMyMFCAppView::OnLButtonDown(UINT nFlags, CPoint point)
{
// TODO: 在此添加消息处理程序代码和/或调用默认值
MessageBox("Left button down!");
CView::OnLButtonDown(nFlags, point);
}

在windows应用程序中,消息被放到消息队列,应用程序GetMessage取消息,DispatchMessage交给操作系统,后者调用应用程序的窗口过程函数,WndProc进行处理。该函数用switch-case进行判别并分类处理。

而MFC程序中,只要定义了与消息有关的三处信息,就可以实现消息的响应。

当收到一个消息,消息的第一个参数指明了与哪个窗口句柄相关,通过对照表,可以找到与之相关的C++对象指针。把这个指针传递给应用程序框架类的基类,后者调用一个名为WindowProc的函数。该函数在WinCore.cpp中。该函数是一个虚函数。调用了OnWndMsg函数。

LRESULTCWnd::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
{
//OnWndMsg does most of the work, except for DefWindowProc call
LRESULT lResult = 0;
if (!OnWndMsg(message, wParam, lParam, &lResult))
lResult = DefWindowProc(message, wParam,lParam);
return lResult;
}

OnWndMsg函数的处理过程:(1)首先判断消息是否有消息响应函数。判断方法是在相应窗口类中查找所需的消息响应函数。因为传递给WindowProc函数的事窗口子类指针,所以,OnWndMsg函数回到相应的子类头文件中查找,看看DECLARE_MESSAGE_MAP()宏上是否有消息响应函数的声明;再到子类源文件看看是否有相应的消息映射宏;(2)有消息响应函数则响应,没有则交给基类处理。

3.2 绘制线条

在CMyMFCAppView类添加一个类型为CPoint的m_ptOrigin私有成员。

在CMyMFCAppView.cpp初始化为0。   

m_ptOrigin = 0;

在OnLButtonDown函数中保存鼠标按下点的信息。

m_ptOrigin = point;

WM_LBUTTONUP消息添加响应函数。

(1)利用Platform SKD函数

HDChdc;
hdc = ::GetDC(m_hWnd);
::MoveToEx(hdc, m_ptOrigin.x, m_ptOrigin.y, NULL);
::LineTo(hdc, point.x, point.y);
::ReleaseDC(m_hWnd, hdc);

(2)利用MFC CDC类

CDC*pDC = GetDC();
pDC->MoveTo(m_ptOrigin);
pDC->LineTo(point);
ReleaseDC(pDC);

(3)利用CClientDC类

CClientDC dc(this);
dc.MoveTo(m_ptOrigin);
dc.LineTo(point);


(4)利用CWindowDC类

CWindowDC dc(this);
dc.MoveTo(m_ptOrigin);
dc.LineTo(point);


(5)在桌面窗口划线

CWindowDCdc(GetDesktopWindow());
ClientToScreen(&m_ptOrigin);
dc.MoveTo(m_ptOrigin);
ClientToScreen(&point);
dc.LineTo(point);


因为客户区与桌面坐标转换问题的存在,需调用ClientToScreen函数。

(6)绘彩色线条

CPenpen(PS_SOLID, 5, RGB(255, 0, 0));
CClientDC dc(this);
CPen*pOldPen = dc.SelectObject(&pen);
dc.MoveTo(m_ptOrigin);
dc.LineTo(point);
dc.SelectObject(pOldPen);


当构造一个GDI对象后,该对象并不会立即生效,必须通过SelectObject函数选入设备描述表,它才会在以后的绘制操作中生效。在完成绘图操作之后,都要利用SelectObject把先前的GDI对象选入设备描述表,以便使其恢复到先前的状态。

3.3使用画刷画图

(1)绘制矩形填充块

CBrush brush(RGB(255, 0, 0));
CClientDC dc(this);
dc.FillRect(CRect(m_ptOrigin,point), &brush);


(2)绘制位图填充块

CBitmap bmp;
bmp.LoadBitmap(IDB_BITMAP1);
CBrush brush(&bmp);
CClientDC dc(this);
dc.FillRect(CRect(m_ptOrigin,point), &brush);


(3)透明画刷

CPen pen(PS_SOLID, 5, RGB(255, 0, 0));
CClientDC dc(this);
//CBrush*pBrush = CBrush::FromHandle((HBRUSH)GetStockObject(NULL_BRUSH));
//CBrush*pOldBrush = (CBrush*)dc.SelectObject(pBrush);
CBrush* pOldBrush =(CBrush*)dc.SelectStockObject(HOLLOW_BRUSH);
CPen* pOldPen = dc.SelectObject(&pen);
dc.Rectangle(CRect(m_ptOrigin, point));
dc.SelectObject(pOldPen);


3.4 连续线条等

(1)连续线条

       添加WM_MOUSEMOVE响应函数到View类中。补充函数。

CClientDC dc(this);
if (nFlags == MK_LBUTTON)
{
dc.MoveTo(m_ptOrigin);
dc.LineTo(point);
m_ptOrigin = point;
}


       也可以添加私有成员BOOL m_bDraw到View类,View构造时赋值为FALSE,WM_LBUTTONDOWN为TRUE,

CClientDC dc(this);
if (m_bDraw == TRUE)
{
dc.MoveTo(m_ptOrigin);
dc.LineTo(point);
<span style="white-space:pre">	</span>m_bDraw = FALSE;
m_ptOrigin = point;
}

(2)扇形效果线条

       添加私有成员CPoint m_btEnd到View类,OnLButtonDown赋值point。

if (nFlags == MK_LBUTTON)
{
dc.MoveTo(m_ptOrigin);
/* 3.4.1 连续线条
//dc.LineTo(point);
//m_ptOrigin = point;
*/

// 3.4.2扇形
dc.LineTo(m_ptEnd);
m_ptEnd = point;

}

(3)橡皮筋技术

<span style="white-space:pre">	</span>//通过取反异或的模式擦除旧线条
dc.SetROP2(R2_NOTXORPEN);
dc.MoveTo(m_ptOrigin);dc.LineTo(m_ptEnd);
//绘制新线条
m_ptEnd = point;
dc.MoveTo(m_ptOrigin);dc.LineTo(m_ptEnd);
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  mfc Windows编程