7移动的小球
任务:在新建的窗口上画出一个小球,随着键盘的上、下、左、右的操作,小球也随着移动。
步骤:1.建立WIN32项目(不用自己写窗口,直接用)
2.将消息处理函数修改如下:
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
int wmId, wmEvent;
PAINTSTRUCT ps;
HDC hdc;
HGDIOBJ hPen,hBrush;
RECT rect;
int nRad=20,nLen=40; //半径和步长
static int nX,nY; //圆心 //静态避免每一次消息响应都被重赋值
int _nX,_nY; //预算圆心,即移动后是否出边界,再确定圆心是否移动
static SIZE size; //窗口的尺寸
switch (message)
{
//创建窗口时,获取窗口的大小,并初始化小球的位置
case WM_CREATE:
GetClientRect(hWnd,&rect);
nX=(rect.right)/2;
nY=(rect.bottom)/2;
size.cx=rect.right;
size.cy=rect.bottom;
break;
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: 在此添加任意绘图代码...
//获取画笔和画刷
hPen=SelectObject(hdc,CreatePen(0,2,RGB(rand()%256,rand()%256,rand()%256)));
hBrush=SelectObject(hdc,CreateSolidBrush(RGB(rand()%256,rand()%256,rand()%256)));
//画圆
Ellipse(hdc,nX-nRad,nY-nRad,nX+nRad,nY+nRad);
//将设备还原并释放资源
SelectObject(hdc,hPen);
DeleteObject(CreatePen(0,2,RGB(rand()%256,rand()%256,rand()%256)));
ReleaseDC(hWnd,hdc);
CloseHandle(hPen);
EndPaint(hWnd, &ps);
break;
//通过拉伸,改变窗口的大小,重新获取窗口的大小
case WM_SIZE:
GetClientRect(hWnd,&rect);
size.cx=rect.right;
size.cy=rect.bottom;
break;
//键盘按键消息,实现小球的移动
case WM_KEYDOWN:
_nX=nX,_nY=nY;
switch(wParam)
{
case VK_UP:
_nY-=nLen;
break;
case VK_LEFT:
_nX-=nLen;
break;
case VK_DOWN:
_nY+=nLen;
break;
case VK_RIGHT:
_nX+=nLen;
break;
}
//判断边界
nX=max(nRad,min(_nX,size.cx-nRad));
nY=max(nRad,min(_nY,size.cy-nRad));
//重绘界面
InvalidateRect(hWnd,NULL,TRUE);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
知识点:
结构体:
typedef struct tagSIZE{LONG cx,LONG cy}SIZE;
cx可以代表矩形的宽,cy代表矩形的高。
使用画笔步骤:
1.创建画笔
HPEN CreatePen(int nPenStyle,int nWidth, COLORREF crColor);
用指定的样式、宽度、颜色创建一个画笔。
2.置当前DC可以使用的画笔。
HGDIOBJ SelectObject(
HDC hdc, //当前DC的句柄
HGDIOBJ hgdiobj //要使用的GDI对象句柄
)
返回当前DC原来使用的同类型的GDI对象句柄
3.从当前DC中取出画笔,即将旧画笔放入当前DC中。
SeleteObject(hdc,hOldPen);
4.销毁画笔
DeleteObject(hPen)
代码中例子解析:
hPen=SelectObject(hdc,CreatePen(0,2,RGB(255.0.0)));
等同于以下两句
hPen=CreatePen(0,2,RGB(255.0.0)); //创建我们所需要的画笔
hOldPen=(HPEN)SelectObject(hdc,hPen); //将我们的画笔放入DC中,同时返回原来的画笔
使用完后,将初始的画笔放入DC中
SelectObject(hdc,hOldPen);
释放我们自己创建的画笔
DeleteObject(hPen);
比如:我们要创建红色的画笔,而系统默认的画笔是黑色。
那么hPen就代表红色画笔。hOldPen代表黑色画笔。
画刷的使用与画笔类似:
1.创建画刷
CreateSolidBrush() //创建实心画刷
CreateHatchBrush() //创建阴影线的画刷
2.置当前DC可以使用的画刷。
HGDIOBJ SelectObject(
HDC hdc, //当前DC的句柄
HGDIOBJ hgdiobj //要使用的GDI对象句柄
)
返回当前DC原来使用的同类型的GDI对象句柄
3.从当前DC中取出画刷,即将旧画笔放入当前DC中。
SeleteObject(hdc,hOldBrush);
4.销毁画刷
DeleteObject(hBrush)
判断边界的方法:
nX=max(nRad,min(_nX,size.cx-nRad));
nY=max(nRad,min(_nY,size.cy-nRad));
可以通过画图清晰可见。
min(_nX,size.cx-nRad) 判断右边界。_nX为移动后小球的预判圆心,(size.cx-nRad)小球刚好接触边界
的圆心,取两者最小值,即不出右边界。
max(nRad,XXXX) 判断左边界。nRad为小球的半径。当小球与左边界相切时,此时半径的长度可以作为
小球的圆心。当小球越过左边界时,XXXX可能将为负数,但绝不大于nRad。因此取最大值,即不出左边界。
同理:nY=max(nRad,min(_nY,size.cy-nRad))也是如此。
InvalidateRect(hWnd,NULL,TRUE);
该函数重新绘制界面。会响应WM_PAINT