3D游戏编程入门(六)Windows的GDI组件(中)
恩,继续.
前天我们说到了使用GDI函数进行绘制图形,已经说完了点和线,今天将其补完.
- 使用GDI绘制面
- 绘制矩形 Rectangle (hdc, xLeft, yTop, xRight, yBottom) ;
- 绘制椭圆 Ellipse (hdc, xLeft, yTop, xRight, yBottom) ;
- 绘制圆角矩形 RoundRect (hdc, xLeft, yTop, xRight, yBottom, xCornerEllipse, yCornerEllipse) ;
- 绘制扇型Pie(hdc,xLeft,xTop,xRight,yBottom,xStart,yStart,xEnd,yEnd);
- 绘制弓型Chord(hdc,xLeft,yTop,xRight,yBottom,xStart,yStart.xEnd,yEnd);
是否觉得绘制扇型和弓型的参数十分类似?其实其参数都是一样的,仅仅是差别一个以圆心为顶点的三角型而已.这两项参数有些复杂,我来说下.Pie(设备句柄,扇型所在圆的外切矩形左上启始点x,y坐标,扇型所在圆的外切矩形右下终止点x,y坐标,扇型两边的x,y坐标)这里值得注意的是,我们获得的扇形或弓形是从Start点到End点逆时针的区域.当我们想绘制另外一半扇型的时候,可以将Start点和End点交换参数,我们就可以获得另外一部分了.
- 使用GDI函数控制绘画风格
就如PS一样,我们应该可以选择自己使用的画笔风格,想想我们就算画地图也是需要有需要虚线,粗线,颜色的呢.而GDI画笔可以由我们来控制这些.默认时,我们的内定设备内容将是BLACK_PEN,它将画出一个象素宽的黑色实线.
WINDOWS本身还支持两种画笔,WHITE_PEN,NULL_PEN,从名字意译应该得知,一个为白色单位象素的画笔,一个为空画笔,即此画笔画出的线条不可见.
当然我们可以自定义自己选择的画笔,首先我们需要将画笔选择进入设备的内容.
hPen = GetStockObject (WHITE_PEN) ;
SelectObject (hdc, hPen) ;
我们调用这两个函数来创建一个基础的画笔,并且将其装入设备. 这是使用默认画笔的方法,我们自行建立画笔的函数为:
hPen = CreatePen (iPenStyle, iWidth, crColor) ;
其中第一个参数是画笔的风格,我们可以确定画笔是实线还是虚线或是点线,这些是在WINGDI.H的头文件中宏定义好的,我现将这些参数做图如下:
第2个参数是画笔的宽度,第三个参数是画笔的颜色.
如我们先定义三个变量来存放三个风格的画笔句柄:
static HPEN hPen1, hPen2, hPen3 ;
在处理WM_CREATE期间,可以建立三种画笔。
hPen1 = CreatePen (PS_SOLID, 1, 0) ;
hPen2 = CreatePen (PS_SOLID, 3, RGB (255, 0, 0)) ;
hPen3 = CreatePen (PS_DOT, 0, 0) ;
再决定自己到底要选择使用哪一个,我们以选用第2个为例
SelectObject (hdc, hPen2) ;
接下来就是绘制图象的函数了,即上面说的画点,线,面的函数.之后在处理WM_DESTROY期间,可以删除所建立的三种画笔。
DeleteObject (hPen1) ;
DeleteObject (hPen2) ;
DeleteObject (hPen3) ;
我们说过,GDI支持在一个密闭的范围内进行填充色彩,这时我们使用的不再是画笔,而是画刷,它负责色彩的填充,和画笔类似的是,它也可以自行设置各种属性,我这里继续拿函数使用来说明.
首先我们要建立画刷
hBrush = CreateSolidBrush (crColor) ;
当然,我们还可以使用由水平、垂直或者倾斜的线组成的“影线标记(hatch marks)”来建立不同风格的画刷.
hBrush = CreateHatchBrush (iHatchStyle, crColor) ;
这里的iHatchStyle依旧是画刷的风格.常用宏定义好的类型有:
说到了这里,我给大家提供一段代码案例:
#include //包含windows头文件
LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) //声明回调函数
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow) //WinMain入口函数
{
//定义窗口类参数
static TCHAR szAppName[] = TEXT ("AltWind") ;
HWND hwnd ;
MSG msg ;
WNDCLASS wndclass ;
wndclass.style = CS_HREDRAW | CS_VREDRAW ;
wndclass.lpfnWndProc= WndProc ;
wndclass.cbClsExtra = 0 ;
wndclass.cbWndExtra = 0 ;
wndclass.hInstance = hInstance ;
wndclass.hIcon = LoadIcon (NULL, IDI_APPLICATION) ;
wndclass.hCursor = LoadCursor (NULL,IDC_ARROW) ;
wndclass.hbrBackground= (HBRUSH) GetStockObject(WHITE_BRUSH);
wndclass.lpszMenuName= NULL ;
wndclass.lpszClassName= szAppName ;
//判断是否注册窗口成功,若失败则弹出相应的消息警告框
if (!RegisterClass (&wndclass))
{
MessageBox ( NULL, TEXT ("Program requires Windows NT!"), szAppName, MB_ICONERROR) ;
return 0 ;
}
//创建窗口
hwnd = CreateWindow (szAppName, TEXT ("Alternate and Winding Fill Modes"), WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, NULL) ;
//显示更新窗口
ShowWindow (hwnd, iCmdShow) ;
UpdateWindow (hwnd) ;
//消息循环中进行消息处理
while (GetMessage (&msg, NULL, 0, 0))
{
TranslateMessage (&msg) ;
DispatchMessage (&msg) ;
}
return msg.wParam ;
}
//消息回调函数
LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
static POINT aptFigure [10] = {10,70, 50,70, 50,10, 90,10, 90,50, 30,50, 30,90, 70,90, 70,30, 10,30 };
static int cxClient, cyClient ; /*声明两个变量存放鼠标X,Y坐标.
在下面,我们为这两项赋值时,LOWORD(lParam)代表取lParam的低16位,HIWORD(lParam)代表取lParam的高16位,在lParam中存放的实际就是鼠标的位置,低16位为x坐标,高16位为鼠标y坐标.*/
HDC hdc ;
int i ;
PAINTSTRUCT ps ;
POINT apt[10] ;
switch (message) {
case WM_SIZE:
cxClient = LOWORD (lParam) ;
cyClient = HIWORD (lParam) ;
return 0 ;
case WM_PAINT: //开始重绘
hdc = BeginPaint (hwnd, &ps) ;
SelectObject (hdc, GetStockObject (GRAY_BRUSH)) ;
for (i = 0 ; i < 10 ; i++)
{ apt[i].x = cxClient * aptFigure[i].x / 200 ;
apt[i].y = cyClient * aptFigure[i].y / 100 ;
}
SetPolyFillMode (hdc, ALTERNATE) ;
Polygon (hdc, apt, 10) ;
for (i = 0 ; i < 10 ; i++)
{
apt[i].x += cxClient / 2 ;
}
SetPolyFillMode (hdc, WINDING) ; //填充
Polygon (hdc, apt, 10) ;
EndPaint (hwnd, &ps) ;
return 0 ;
case WM_DESTROY:
PostQuitMessage (0) ;
return 0 ;
}
return DefWindowProc (hwnd, message, wParam, lParam) ;
}
最后出来的图形应该是这样的