06简单绘图程序的实现及菜单的使用

更新时间:2023-10-22 14:06:01 阅读量: 综合文库 文档下载

说明:文章内容仅供预览,部分内容可能不全。下载后的文档,内容与下面显示的完全一致。下载之前请确认下面内容是否您想要的,是否完整无缺。

06简单绘图程序的实现及菜单的使用

到现在为止已经分别实现了使用鼠标绘制线段、矩形、椭圆,能不能在一个程序里实现这三种操作的切换?当然可以!

1、 对绘制线段、矩形与椭圆的程序进行分析,每一种绘图操作有三个动作:鼠标落下、鼠

标移动与鼠标弹起,分别对应于3段代码,对画线的三段代码进行分析,与这写代码相关的变量有:

与消息相关的变量:HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam; 与绘图操作相关的变量: POINT ptStart,ptEnd;BOOL bMouseDown; 如果把相关代码封装在三个绘图函数中,则以上变量都是窗口函数的局部变量,在绘图函数中是无法访问的,可以将消息的参数作为绘图函数的参数传到绘图函数中,也可以将绘图相关的变量变成函数参数,但这样存在以下问题:参数数量较多,效率较低,如果以后因为增加绘图函数的功能需要增加新的变量则需要修改函数的原型;因此可以将与绘图函数相关的变量封装在一个结构体内,在窗口函数中 一个结构体变量,给绘图函数传入一个结构体指针。

2、 定义结构体如下: typedef struct tagDrawStru { POINT ptStart,ptEnd; BOOL bMouseDown;

} DRAWSTRU,*PDRAWSTRU;

3、 在窗口函数中定义如下静态局部变量: static DRAWSTRU ds;

4、 定义3个函数分别完成鼠标落下、移动和弹起的处理,代码如下:

VOID LineMouseDown( PDRAWSTRU pDs,HWND hWnd,WPARAM wParam,LPARAM lParam) { pDs->ptStart.x=LOWORD(lParam); pDs->ptStart.y=HIWORD(lParam); pDs->ptEnd.x=pDs->ptStart.x; pDs->ptEnd.y=pDs->ptStart.y; pDs->bMouseDown=TRUE; SetCapture(hWnd); }

VOID LineMouseUp( PDRAWSTRU pDs,HWND hWnd,WPARAM wParam,LPARAM lParam) { HDC hdc; pDs->bMouseDown=FALSE; ReleaseCapture(); hdc=GetDC(hWnd); SetROP2(hdc,R2_NOT); MoveToEx(hdc,pDs->ptStart.x,pDs->ptStart.y,NULL); LineTo(hdc,pDs->ptEnd.x,pDs->ptEnd.y); pDs->ptEnd.x=LOWORD(lParam);

pDs->ptEnd.y=HIWORD(lParam); SetROP2(hdc,R2_COPYPEN); MoveToEx(hdc,pDs->ptStart.x,pDs->ptStart.y,NULL); LineTo(hdc,pDs->ptEnd.x,pDs->ptEnd.y); ReleaseDC(hWnd,hdc); }

VOID LineMouseMove( PDRAWSTRU pDs,HWND hWnd,WPARAM wParam,LPARAM lParam) { HDC hdc; if(pDs->bMouseDown) { hdc=GetDC(hWnd); SetROP2(hdc,R2_NOT); MoveToEx(hdc,pDs->ptStart.x,pDs->ptStart.y,NULL); LineTo(hdc,pDs->ptEnd.x,pDs->ptEnd.y); pDs->ptEnd.x=LOWORD(lParam); pDs->ptEnd.y=HIWORD(lParam); MoveToEx(hdc,pDs->ptStart.x,pDs->ptStart.y,NULL); LineTo(hdc,pDs->ptEnd.x,pDs->ptEnd.y); ReleaseDC(hWnd,hdc); } }

5、 修改窗口过程,将鼠标消息的处理代码修改为函数调用,代码如下: case WM_LBUTTONDOWN: LineMouseDown(&ds,hWnd,wParam,lParam); break; case WM_LBUTTONUP: LineMouseUp(&ds,hWnd,wParam,lParam); break; case WM_MOUSEMOVE: LineMouseMove(&ds,hWnd,wParam,lParam); break;

6、 在源程序文件的起始位置添加函数的声明:

VOID LineMouseDown( PDRAWSTRU pDs,HWND hWnd,WPARAM wParam,LPARAM lParam);

VOID LineMouseUp( PDRAWSTRU pDs,HWND hWnd,WPARAM wParam,LPARAM lParam); VOID LineMouseMove( PDRAWSTRU pDs,HWND hWnd,WPARAM wParam,LPARAM lParam);

7、 编译运行程序,观察运行结果。通过函数封装实现了绘制线段的操作 8、 同理对绘制矩形、椭圆的代码进行封装得到以下函数:

VOID RectMouseDown( PDRAWSTRU pDs,HWND hWnd,WPARAM wParam,LPARAM lParam);

VOID RectMouseUp( PDRAWSTRU pDs,HWND hWnd,WPARAM wParam,LPARAM lParam);

VOID RectMouseMove( PDRAWSTRU pDs,HWND hWnd,WPARAM wParam,LPARAM lParam);

VOID EllipseMouseDown( PDRAWSTRU pDs,HWND hWnd,WPARAM wParam,LPARAM lParam);

VOID EllipseMouseUp( PDRAWSTRU pDs,HWND hWnd,WPARAM wParam,LPARAM lParam);

VOID EllipseMouseMove( PDRAWSTRU pDs,HWND hWnd,WPARAM wParam,LPARAM lParam);

9、 定义一个函数指针类型: typedef VOID (*PDRAWFUN)( PDRAWSTRU pDs,HWND hWnd,WPARAM wParam,LPARAM lParam); 10、 在窗口函数的定义部分定义3个函数指针变量: static PDRAWFUN pMouseDown,pMouseUp,pMouseMove; 11、 在窗口收到WM_CREATE消息时对指针变量进行初始化: case WM_CREATE: pMouseDown=EllipseMouseDown; pMouseUp=EllipseMouseUp; pMouseMove=EllipseMouseMove; break; 12、 修改鼠标消息的处理代码如下: case WM_LBUTTONDOWN: pMouseDown(&ds,hWnd,wParam,lParam); break; case WM_LBUTTONUP: pMouseUp(&ds,hWnd,wParam,lParam); break; case WM_MOUSEMOVE: pMouseMove(&ds,hWnd,wParam,lParam); break; 13、 编译运行!可以实现修改3个函数指针变量指向不同的函数进行不同的绘图操作,

最好是能够通过菜单或者工具栏实现指针变量的修改; 14、 为项目增加弹出式菜单如下图:

菜单的参数如下表: ID IDM_DRAW_LINE IDM_DRAW_RECT 标题 &Draw &Line &Rectangle IDM_DRAW_ELLIPSE &Ellipse 15、 为以上菜单项增加消息处理代码如下: case IDM_DRAW_LINE: pMouseDown=LineMouseDown; pMouseUp=LineMouseUp; pMouseMove=LineMouseMove; break; case IDM_DRAW_RECT: pMouseDown=RectMouseDown; pMouseUp=RectMouseUp; pMouseMove=RectMouseMove; break; case IDM_DRAW_ELLIPSE: pMouseDown=EllipseMouseDown; pMouseUp=EllipseMouseUp; pMouseMove=EllipseMouseMove; break;

编译运行程序,选择不同的菜单后,并使用鼠标绘制图形,发现程序有以下缺陷,菜单项不能反映当前鼠标操作时绘制什么图形。因此需要对菜单项添加标记。 16、 为菜单添加标记 函数介绍:

DWORD CheckMenuItem(HMENU hmenu,UINT uIDCheckItem,UINT uCheck); 参数:

hmenu :要做标记的菜单句柄

uIDCheckItem :菜单项的ID或位置

uCheck :为菜单加标记或清除标记,为下表中值的组合:

MF_BYCOMMAND MF_BYPOSITION MF_CHECKED MF_UNCHECKED

说明

指示uIDCheckItem 参数表示菜单项的ID 指示uIDCheckItem 参数表示菜单项从0开始的位置

添加选中标记 清除选中标记

将菜单消息的处理代码修改如下: case IDM_DRAW_LINE:

pMouseDown=LineMouseDown; pMouseUp=LineMouseUp; pMouseMove=LineMouseMove;

CheckMenuItem(hMenu,IDM_DRAW_LINE,MF_BYCOMMAND|MF_CHECKED);

CheckMenuItem(hMenu,IDM_DRAW_RECT,MF_BYCOMMAND|MF_UNCHECKED);

CheckMenuItem(hMenu,IDM_DRAW_ELLIPSE,MF_BYCOMMAND|MF_UNCHECKED);

break;

case IDM_DRAW_RECT:

pMouseDown=RectMouseDown; pMouseUp=RectMouseUp; pMouseMove=RectMouseMove;

CheckMenuItem(hMenu,IDM_DRAW_LINE,MF_BYCOMMAND|MF_UNCHECKED);

CheckMenuItem(hMenu,IDM_DRAW_RECT,MF_BYCOMMAND|MF_CHECKED);

CheckMenuItem(hMenu,IDM_DRAW_ELLIPSE,MF_BYCOMMAND|MF_UNCHECKED); break;

case IDM_DRAW_ELLIPSE:

pMouseDown=EllipseMouseDown; pMouseUp=EllipseMouseUp; pMouseMove=EllipseMouseMove;

CheckMenuItem(hMenu,IDM_DRAW_LINE,MF_BYCOMMAND|MF_UNCHECKED);

CheckMenuItem(hMenu,IDM_DRAW_RECT,MF_BYCOMMAND|MF_UNCHECKED);

CheckMenuItem(hMenu,IDM_DRAW_ELLIPSE,MF_BYCOMMAND|MF_CHECKED);

break;

17、 编译运行程序!

思考题:如何为系统加上颜色选择功能?

绘图时当鼠标指针拖动到窗口的外面(标题栏的上部),会发现图形出现了异常,绘制的图形不在预期位置,分析为什么?(提示:分析HIWORD宏, #define GET_Y_LPARAM(lp) ((int)(short)HIWORD(lp))

将所有的HIWORD宏用 GET_Y_LPARAM宏替换,)

为绘图程序增加线条颜色选择的功能 到现在为止绘制出的图形都是黑色的,如果想绘制出不同颜色的图形则每次绘图时应创建指定颜色的画笔,因此为程序增加一个菜单如下图:

菜单的参数如下表: ID IDM_COLOR_RED IDM_COLOR_GREEN IDM_COLOR_BLUE 标题 &Color &Red &Green &Blue

本文来源:https://www.bwwdw.com/article/q46f.html

Top