接下来尝试在paint 的case语句里实现画出一个小方块。好,回到上次我说的那个那个语句 我们查看wndProc这个东西,系统的注释有解释这是用来干嘛的,
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { int wmId, wmEvent; PAINTSTRUCT ps;//画笔结构体 HDC hdc;//获取画柄,我理解的是获取画图的工具 POINT point[4];//这里我们以点为基准,一个正方形有四个点 switch (message) { case WM_COMMAND: wmId = LOWORD(wParam); wmEvent = HIWORD(wParam); // 分析菜单选择: switch (wmId) { case IDM_ABOUT: DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About); break; case IDM_EXIT: DestroyWindow(hWnd); break; default: return DefWindowProc(hWnd, message, wParam, lParam); } break;
case WM_PAINT:
hdc = BeginPaint(hWnd, &ps);
// TODO: 在此添加任意绘图代码... EndPaint(hWnd, &ps); break;
case WM_DESTROY: PostQuitMessage(0); break; default: return DefWindowProc(hWnd, message, wParam, lParam); } return 0; }
在开头,我写了一些自己理解的注释,定义了一个POINT类的数组,分析下这个case语句
case WM_PAINT:
hdc = BeginPaint(hWnd, &ps);
begin就是开始,end就是结束,下面来试试怎么画一个方块,代码如下// TODO: 在此添加任意绘图代码... EndPaint(hWnd, &ps); break;
case WM_PAINT: hdc = BeginPaint(hWnd, &ps); point[0].x=0;point[0].y=0; point[1].x=20;point[1].y=0; point[2].x=20;point[2].y=20; point[3].x=0;point[3].y=20; Polygon(hdc,point,4); // TODO: 在此添加任意绘图代码... EndPaint(hWnd, &ps); break;
我们画个最简单的,我们知道,屏幕的每个位置都对应有他们的XY坐标,那么在桌面上,最左上角的点就是我们所谓的原点,我们可以想象它是一个直角坐标系,右边为X的正方向,向下为Y轴的正方向(别问我怎么不是向上为正方向那么蠢的问题)哈哈。piont[0],指的是第一个点,x的坐标是0,y的坐标为0。Polygon方法是绘制多边形,,在这里可以理解为,连接起那些点,顺序是从0到3的,我们可以调换顺序看看。hdc参数是获取画柄,point是我们建立的对象,4是指有4个点。连接的顺序是0->1->2->3; 这个也是我们画错好几个得出来的规律。运行得到图如下
同样 我们可以尝试画出两个方块,比如是竖直的方块
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { int wmId, wmEvent; PAINTSTRUCT ps;//画笔结构体 HDC hdc;//获取画柄,我理解的是获取画图的工具 POINT point[8];//这里我们以点为基准,一个正方形有四个点 switch (message) { case WM_COMMAND: wmId = LOWORD(wParam); wmEvent = HIWORD(wParam); // 分析菜单选择: switch (wmId) { case IDM_ABOUT: DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About); break; case IDM_EXIT: DestroyWindow(hWnd); break; default: return DefWindowProc(hWnd, message, wParam, lParam); } break; case WM_PAINT: hdc = BeginPaint(hWnd, &ps); point[0].x=0;point[0].y=0; point[1].x=20;point[1].y=0; point[2].x=20;point[2].y=20; point[3].x=0;point[3].y=20; point[4].x=0;point[4].y=20; point[5].x=20;point[5].y=20; point[6].x=20;point[6].y=40; point[7].x=0;point[7].y=40; Polygon(hdc,point,8); // TODO: 在此添加任意绘图代码... EndPaint(hWnd, &ps); break; case WM_DESTROY: PostQuitMessage(0); break; default: return DefWindowProc(hWnd, message, wParam, lParam); } return 0; }
运行下:
至于这个算法,就自己去想了,很简单。这个时候,我们来考虑下实用性的问题,如果我要在其他地方画图形呢?每次画个图形都要计算,那么运算量是不是太大了呢?以后要做移动,每移动一次我们都要计算一次坐标?显然不实际!!我们来考虑解决方法。如果我能写出一个通用的算法(类似于数学的公式)去画一个方块,那是不是就想怎么画怎么画呢?
这里,我自己想了个比较通用的方法(我们老师规定边长为20)运行结果如下LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { int wmId, wmEvent; int drawBeepers(HDC hdc,POINT point[],int X,int Y);//声明一个画方块的函数 PAINTSTRUCT ps;//画笔结构体 HDC hdc;//获取画柄,我理解的是获取画图的工具 POINT point[4];//这里我们以点为基准,一个正方形有四个点 switch (message) { case WM_COMMAND: wmId = LOWORD(wParam); wmEvent = HIWORD(wParam); // 分析菜单选择: switch (wmId) { case IDM_ABOUT: DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About); break; case IDM_EXIT: DestroyWindow(hWnd); break; default: return DefWindowProc(hWnd, message, wParam, lParam); } break; case WM_PAINT: hdc = BeginPaint(hWnd, &ps); drawBeepers(hdc,point,60,60);//以x=60,y=60的点处画方块 // TODO: 在此添加任意绘图代码... EndPaint(hWnd, &ps); break; case WM_DESTROY: PostQuitMessage(0); break; default: return DefWindowProc(hWnd, message, wParam, lParam); } return 0; } int drawBeepers(HDC hdc,POINT point[],int X,int Y)//定义一个画方块的方法 { //hdc参数获取画柄,point参数,X,Y是我们人为加的参数,目的是设置我们自己的原点坐标 point[0].x=X;point[0].y=Y; point[1].x=20+X;point[1].y=Y; point[2].x=20+X;point[2].y=20+Y; point[3].x=X;point[3].y=20+Y;//这几行算法自己琢磨,不难;就是坐标的运算 Polygon(hdc,point,4); return 0; }//然后,放进paint的case语句中
我们发现,方块貌似移动了,是的!可能有人觉得没什么用,但是我们的俄罗斯就是一个个这样的方块拼凑的,所以,我们已经做了一大步。那么我们具体怎么实现俄罗斯方块的方块制作呢?还有,俄罗斯方块那么多,加上变形,不可能每个都我们画一遍吧。应该有很多共同点吧?怎么避免重复工作?那就得涉及到我们的c++的类与继承了。
下篇博文就继续讨论这些问题。