跟我一起玩Win32开发(10):绘图(C)
来源:互联网 发布:ui设计和java哪个好学 编辑:程序博客网 时间:2024/05/30 23:36
今天我们来欣赏一下用于填充图形的函数,当然我不会逐个去介绍,因为我们参考MSDN直接套参数就可以了。
SetDCBrushColor函数有必要扯一下,它的声明如下:
COLORREF SetDCBrushColor( __in HDC hdc, __in COLORREF crColor );
第二个参数,通过RGB宏产生COLORREF传进去就可以了,比如这样:
SetDCBrushColor(ps.hdc,RGB(211,254,41));
但是,如果只是调用这个函数,你会发现在绘图的时候,画刷的颜色还是没有变化,因为我们还没有将HBRUSH的默认画刷DC_BRUSH选到DC中去。所以,在调用SetDCBrushColor之前,要把默认的画刷先放到设备上下文,默认画刷可以通过GetStockObject(DC_BRUSH)获得。
SelectObject(ps.hdc,GetStockObject(DC_BRUSH));
接下来我们可以尝试填充几个图形试试,如矩形、椭圆、饼图等。
case WM_PAINT:{BeginPaint(hwnd,&ps);SelectObject(ps.hdc,GetStockObject(DC_BRUSH));SetDCBrushColor(ps.hdc,RGB(0,0,255));Rectangle(ps.hdc,20,18,68,50);SetDCBrushColor(ps.hdc,RGB(220,32,70));Rectangle(ps.hdc,125,100,230,300);SetDCBrushColor(ps.hdc,RGB(30,235,12));Ellipse(ps.hdc,270,80,390,223);SetDCBrushColor(ps.hdc,RGB(35,160,242));Chord(ps.hdc,185,260,420,480,190,260,405,479);SetDCBrushColor(ps.hdc,RGB(211,254,41));Pie(ps.hdc,35,320,300,600,56,470,60,360);EndPaint(hwnd,&ps);}return 0;
每一次调用SetDCBrushColor都会改变画刷的颜色,所以,比如你希望绘制蓝色的矩形,在调用Rectangle之前就要调用SetDCBrushColor修改画刷颜色,然后再画矩形。我们可以看看上面代码的最终效果。
下面,我们做一个人类历史上最简单的画图程序。
我们为程序提供几种可选的线条风格,通过菜单来选择,如实线,虚线等,鼠标按下左键后开始,鼠标左键弹起就完成一条直线的绘制。为了简化,我们把相应菜单的ID设置的值与CreatePen中的线型的宏的值一致。
这样一来,选择了哪个菜单就直接用这个菜单的ID来创建画笔,就省去了许多代码。
在响应WM_CREATE消息时,创建菜单。
case WM_CREATE:{// 创建菜单HMENU menubar = CreateMenu();HMENU menuPop = CreatePopupMenu();AppendMenu(menuPop,MF_STRING,(UINT_PTR)PS_SOLID,L"实线");AppendMenu(menuPop,MF_STRING,(UINT_PTR)PS_DASH,L"虚线");AppendMenu(menuPop,MF_STRING,(UINT_PTR)PS_DOT,L"点线");AppendMenu(menuPop,MF_STRING,(UINT_PTR)PS_DASHDOT,L"点虚线");AppendMenu(menubar, MF_STRING | MF_POPUP, (UINT_PTR)menuPop, L"选择线型");SetMenu(hwnd, menubar);}return 0;
现在我们来想一下,绘制直线的大概思路。
1、鼠标左键按下,记录线条的起点。
2、鼠标左键弹起时,记录线条的终点,并画出整条线。
3、当窗口发生重绘时,前面画的所有线条被清除,要希望保留前面画的线条,就要响应WM_PAINT消息,把所有线条重新画一次。
4、由于我们会在窗口上画出多条线,程序需要定义一个结构体用来保存线条的起点、终点和所使用的线型。
5、正因为需要保存多条线的数据,故可以把每一条线的相关数据放到一个vector中。
根据上面的分析,完成程序的代码如下:
#include <Windows.h>#include <WindowsX.h>#include <vector>using namespace std;typedef struct tagData{int ptBeginX, ptBeginY;//起点int ptEndX, ptEndY;//终点int penStyle;//画笔的线型} PAINTDATA;LRESULT CALLBACK WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);int WINAPI WinMain(HINSTANCE hThisApp,HINSTANCE hPrevApp,LPSTR lpsCmd,int nShow){WNDCLASS wc = {};wc.hbrBackground = CreateSolidBrush(RGB(0,0,0));wc.hInstance = hThisApp;wc.lpfnWndProc = WindowProc;wc.lpszClassName = L"My";wc.style = CS_HREDRAW | CS_VREDRAW;RegisterClass(&wc);HWND hwnd = CreateWindow(L"My",L"应用程序",WS_OVERLAPPEDWINDOW,50,20,600,480,NULL,NULL,hThisApp,NULL);if(hwnd == NULL)return -1;ShowWindow(hwnd, nShow);UpdateWindow(hwnd);MSG msg;while(GetMessage(&msg,NULL,0,0)){TranslateMessage(&msg);DispatchMessage(&msg);}return 0;}LRESULT CALLBACK WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam){static vector<PAINTDATA> datas;static int penStyle = PS_SOLID;static PAINTDATA *pCurrentData = NULL;//指向当前PAINTDATA的指针switch(msg){case WM_CREATE:{// 创建菜单HMENU menubar = CreateMenu();HMENU menuPop = CreatePopupMenu();AppendMenu(menuPop,MF_STRING,(UINT_PTR)PS_SOLID,L"实线");AppendMenu(menuPop,MF_STRING,(UINT_PTR)PS_DASH,L"虚线");AppendMenu(menuPop,MF_STRING,(UINT_PTR)PS_DOT,L"点线");AppendMenu(menuPop,MF_STRING,(UINT_PTR)PS_DASHDOT,L"点虚线");AppendMenu(menubar, MF_STRING | MF_POPUP, (UINT_PTR)menuPop, L"选择线型");SetMenu(hwnd, menubar);}return 0;case WM_COMMAND:{//为选中的菜单加上单选标记HMENU mnbar = GetMenu(hwnd);HMENU hmnPop = GetSubMenu(mnbar, 0);CheckMenuRadioItem(hmnPop, PS_SOLID, PS_DASHDOT, LOWORD(wParam), MF_BYCOMMAND);//记录用户选择的线型penStyle = (int)LOWORD(wParam);}return 0;case WM_LBUTTONDOWN:{pCurrentData = new PAINTDATA;//获取起点pCurrentData ->penStyle = penStyle;pCurrentData->ptBeginX = GET_X_LPARAM(lParam);pCurrentData->ptBeginY = GET_Y_LPARAM(lParam);}return 0;case WM_LBUTTONUP:{if(pCurrentData != NULL){//获取终点pCurrentData->ptEndX = GET_X_LPARAM(lParam);pCurrentData->ptEndY = GET_Y_LPARAM(lParam);//画出线条HDC hdc = GetDC(hwnd);HPEN pen = CreatePen(pCurrentData->penStyle,1,RGB(0,255,0));HPEN oldpen = (HPEN)SelectObject(hdc,pen);MoveToEx(hdc,pCurrentData->ptBeginX,pCurrentData->ptBeginY,NULL);LineTo(hdc,pCurrentData->ptEndX,pCurrentData->ptEndY);SelectObject(hdc,oldpen);DeleteObject(pen);ReleaseDC(hwnd,hdc);//把当前数据添加到vector中datas.push_back(*pCurrentData);}}return 0;case WM_PAINT:{PAINTSTRUCT ps;BeginPaint(hwnd,&ps);//将所有线条重新画一遍vector<PAINTDATA>::const_iterator item;for(item = datas.begin(); item != datas.end(); item++){HPEN pen = CreatePen(item->penStyle, 1, RGB(0,255,0));SelectObject(ps.hdc, pen);MoveToEx(ps.hdc, item->ptBeginX, item->ptBeginY, NULL);LineTo(ps.hdc, item->ptEndX, item->ptEndY);DeleteObject(pen);}EndPaint(hwnd,&ps);}return 0;case WM_DESTROY:PostQuitMessage(0);return 0;default:return DefWindowProc(hwnd,msg,wParam,lParam);}return 0;}
结构体PAINTDATA用来保存每一条线的起点坐标、终点坐标、线型。为了避免在跳出WindowProc后所有数据被回收,可以使用static关键字来声明变量,这样这些变量的生命周期就与整个应用程序相同了。
运行程序后,在菜单中选择一种线型,然后在窗口上画线,效果如图所示。
- 跟我一起玩Win32开发(10):绘图(C)
- 跟我一起玩Win32开发(8):绘图(A)
- 跟我一起玩Win32开发(9):绘图(B)
- 跟我一起玩Win32开发(4):创建菜单
- 跟我一起玩Win32开发(7):多边形窗口
- 跟我一起玩Win32开发(13):握手对话框
- 跟我一起玩Win32开发(15):ListView控件
- 跟我一起玩Win32开发(20):浏览文件夹
- 跟我一起玩Win32开发(22):抓取屏幕
- 跟我一起玩Win32开发(24):计时器
- 跟我一起玩Win32开发(25):监视剪贴板
- 跟我一起玩Win32开发(25):监视剪贴板
- 跟我一起玩Win32开发(2):完整的开发流程
- 跟我一起玩Win32开发(2):完整的开发流程
- 跟我一起玩Win32开发(1):关于C++的几个要点
- 跟我一起玩Win32开发(3):窗口的重绘
- 跟我一起玩Win32开发(5):具有单选标记的菜单
- 跟我一起玩Win32开发(6):创建右键菜单
- 如何搭建modem编译环境
- 什么是构架设计图 ?有哪些组成?
- Hibernate的merge()方法
- 【SQLSERVER】存储过程基础
- ffmpeg 解码视频小例子
- 跟我一起玩Win32开发(10):绘图(C)
- redhat6.2 安装jdk
- Java io文件操作(按字符、字节、行、随机读取,追加,文件操作)
- python之list.append()和list.extend(list)的区别
- 微博里很热的1000瓶子10小白鼠找毒药问题
- Mac OS X 背后的故事(六)Cordell Ratzlaff 引发的 Aqua 革命(上)
- JSP、JAVA获取各种路径总结
- JAVA中集合map,set,list详解
- 软件系统的架构(ArchitECture)有两个要素是什么?