Windows Api教案3_windowsapi实例
Windows Api教案3由刀豆文库小编整理,希望给你工作、学习、生活带来方便,猜你可能喜欢“windowsapi实例”。
教
案
用
纸 第四章
图 形 基 础
一
概述
图形设备接口(GDI:Graphics Device Interface)是Windows的子系统,它负责在视频显示器和打印机上显示图形。二
GDI的结构
⒈ GDI原理
Window 98和Windows NT中的图形主要由GDI32.DLL动态链接库输出的函数来处理。在Window 98中,这个GDI32.DLL实际是利用16位GDI.EXE动态链接库来执行许多函数。在Windows NT中,GDI.EXE只用于16位的程序。这些动态链接库为用户安装的视频显示器和任何打印机调用设备驱动程序中的例程。视频驱动程序访问视频显示器的硬件,打印机驱动程序将GDI命令转换为各种打印机能够理解的代码或命令。GDI的主要目的之一是支持与设备无关的图形。GDI是图形设备硬件之间的一种高层接口。
图形输出设备分为光栅设备和矢量设备两大类。⒉ GDI函数分类
◆ 获取(或创建)和释放(或清除)DC的函数;
如,GetDC和ReleaseDC函数等 ◆ 获取有关DC信息的函数;
如,GetTextMetrics函数来获取有关DC中当前所选字体的尺寸信息。◆ 绘图函数;
如,TextOut等;
◆ 设置和获取DC参数的函数;
DC的“属性”决定有关绘图函数如何工作的细节。如,SetTextColor ◆ 使用GDI对象的函数;
如,Brush,Pen和Bitmap等,用SelectObject函数来选择。⒊ GDI图元
在屏幕或打印机上显示的图形类型本身可以被分为几类,通常被称为“图元”,他们是:
◆ 直线和曲线
线条是所有矢量图形绘制系统的基础。GDI支持直线、矩形、椭圆、弧,以及贝塞尔曲线。所有更复杂的曲线可由折线代替。◆ 填充区域
当一系列直线或者曲线封闭了一个区域时,该区域可以使用当前GDI画刷对象进行填充。这个画刷可以是实心色彩、图案,也可以是在区域内垂直或者水平重复的位图图像。◆ 位图
吉
林
化
工
学
院
第 42 页 教
案
用
纸
位图是位的矩形数组,这些位对应于显示设备上的像素,它们是光栅图形的基础工具。位图通常用于在视频显示器或者打印机上显示复杂图像。位图还可以用于显示必须很快绘制的小图像,诸如图标、鼠标光标等。GDI支持两种类型的位图:老的“设备有关”位图,是GDI对象;新的“设备无关”位图,可以存储在磁盘文件中。◆ 文本
文本通常不仅是所有的计算机图形系统中最复杂的部分,而且也是最重要的部分。Windows 98不仅支持TrueType字体,而且继续支持旧时的基于位图的字体。⒋ 其他方面
◆ 映射模式和变换
虽然默认时以像素为单位进行绘图,但是并非局限于此。GDI映射模式允许用户以英寸、mm或者任何用户想使用的单位来绘图,但Windows 98不支持坐标变换。◆ 元文件
元文件是以二进制形式存储的GDI命令的集合。元文件主要用于通过剪贴板传输矢量图形表示。◆ 区域
区域是形状任意的复杂区,通常定义为较简单区域的布尔组合。在GDI内部,区域除了存储为最初用来定义区域的线条组合以外,还以一系列扫描线的形式存储。用户可以将区域用于绘制轮廓、填充和剪裁。◆ 路径
路径是GDI内部存储的直线和曲线的集合。路径可以用于绘图、填充和剪裁,还可以转换为区域。◆ 剪裁
绘图可以限制在客户区的某一部分中。剪裁区域可以是矩形或非矩形,剪裁通常是通过区域或者路径来定义的。◆ 调色板
定制调色板通常限于显示256色的显示器。Windows仅保留这些色彩之中的20种供系统使用,用户可以改变其他236种色彩,以准确显示按位图形式存储的真实图像。◆ 打印 三
设备描述表
⒈ 获取DC句柄 方法一: HDC hdc;PAINTSTRUCT ps;吉
林
化
工
学
院
第 43 页 教
案
用
纸
hdc=BeginPaint(hwnd,&ps);„„
EndPaint(hwnd,&ps);方法二:
hdc=GetDC(hwnd);„„
ReleaseDC(hwnd,hdc);方法三:
hdc=GetWindowDC(hwnd);„„
ReleaseDC(hwnd,hdc);方法四:
hdc=CreateDC(TEXT(“DISPLAY”),NULL,NULL,NULL);通过方法四可以获取整个屏幕的DC句柄。特例一:
有时用户只是需要获取关于DC的一些信息而并不进行任何绘画,这时,可以使用CreateIC来获取一个“信息描述表”的句柄,其参数与CreateDC函数相同,如:
hdc=CreateDC(TEXT(“DISPLAY”),NULL,NULL,NULL);⒉ 获取DC信息
GetDeviceCaps函数:
int GetDeviceCaps(HDC hdc, // handle to the device context int nIndex // index of capability to query);
通过该函数可以获取指定设备的信息。如: iValue=GetDeviceCaps(hdc,HORZRES);可得到设备的宽度(单位为像素)。四
画点和线
在理论上,只要提供SetPixel和GetPixel函数,就可以使用图形设备驱动程序绘制一切东西了。
⒈ 写像素
COLORREF SetPixel(HDC hdc, // handle to device context int X, // x-coordinate of pixel int Y, // y-coordinate of pixel COLORREF crColor // pixel color);
⒉ GetPixel COLORREF GetPixel(吉
林
化
工
学
院
第 44 页 教
案
用
纸
HDC hdc, // handle to device context int XPos, // x-coordinate of pixel int nYPos // y-coordinate of pixel);说明:用来获取指定坐标处的像素颜色;
COLORREF用来指定一个RGB颜色 #define RGB(r,g,b)((COLORREF((BYTE(r)|
((WORD((BYTE)(g)
((DWORD(BYTE(b)
Windows可以画直线、椭圆线和贝塞尔样条。Windows98支持的7个画线函数是:
◆ LineTo 画直线
◆ Polyline和PolylineTo 画一系列相连的直线 ◆ PolyPolyline 画多组相连的线 ◆ Arc 画椭圆线
◆ PolyBezier和PolyBezierTo 画贝塞尔样条 另外,Windows NT还支持3种画线函数 ◆ ArcTo和AngleArc 画椭圆线;
◆ PolyDraw 画一系列相连的线以及贝塞尔样条。既画线也填充所画图形的封闭区域的函数: ◆ Rectangle 画矩形 ◆ Ellipse 画椭圆
◆ RounRect 画带圆角的矩形
◆ Pie 画椭圆的一部分,使其看起来像一个扇形 ◆ Chord 画椭圆的一部分,以呈弓形
设备描述表的5个属性影响着用这些函数所画线的外观:当前画笔的位置(仅用于LineTo、PolylineTo、PolyBezierTo和ArcTo)、画笔、背景方式、背景色和绘图模式。
画一条直线,必须调用两个函数。第一个函数指定了线的开始点,第二各函数指定了线的终点:
MoveToEx(hdc,xBeg,yBeg,NULL);LineTo(hdc,xEnd,yEnd);⒋ SINEWAVE程序
/*----------
SINEWAVE.C--Sine Wave Using Polyline
(c)Charles Petzold, 1998
----------*/
#include 吉
林
化
工
学
院
第 45 页 教
案
用
纸
#include
#define NUM
1000 #define TWOPI(2 * 3.14159)
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,PSTR szCmdLine, int iCmdShow){
static TCHAR szAppName[] = TEXT(“SineWave”);
HWND
hwnd;
MSG
msg;
WNDCLASS
wndcla;
wndcla.style
= CS_HREDRAW | CS_VREDRAW;
wndcla.lpfnWndProc
= WndProc;
wndcla.cbClsExtra
= 0;
wndcla.cbWndExtra
= 0;
wndcla.hInstance
= hInstance;
wndcla.hIcon
= LoadIcon(NULL, IDI_APPLICATION);
wndcla.hCursor
= LoadCursor(NULL, IDC_ARROW);
wndcla.hbrBackground =(HBRUSH)GetStockObject(WHITE_BRUSH);
wndcla.lpszMenuName = NULL;
wndcla.lpszClaName = szAppName;
if(!RegisterCla(&wndcla))
{
MeageBox(NULL, TEXT(“Program requires Windows NT!”),szAppName, MB_ICONERROR);
return 0;
}
hwnd = CreateWindow(szAppName, TEXT(“Sine Wave Using Polyline”),WS_OVERLAPPEDWINDOW,CW_USEDEFAULT, CW_USEDEFAULT,CW_USEDEFAULT, CW_USEDEFAULT,NULL, NULL, hInstance, NULL);
ShowWindow(hwnd, iCmdShow);
UpdateWindow(hwnd);
while(GetMeage(&msg, NULL, 0, 0))
{
TranslateMeage(&msg);
DispatchMeage(&msg);
}
return msg.wParam;} 吉
林
化
工
学
院
第 46 页 教
案
用
纸
LRESULT CALLBACK WndProc(HWND hwnd, UINT meage, WPARAM wParam, LPARAM lParam){
static int cxClient, cyClient;
HDC
hdc;
int
i;
PAINTSTRUCT ps;
POINT
apt [NUM];
switch(meage)
{
case WM_SIZE:
cxClient = LOWORD(lParam);
cyClient = HIWORD(lParam);
return 0;
case WM_PAINT:
hdc = BeginPaint(hwnd, &ps);
MoveToEx(hdc, 0,cyClient / 2, NULL);
LineTo
(hdc, cxClient, cyClient / 2);
for(i = 0;i
{
apt[i].x = i * cxClient / NUM;
apt[i].y =(int)(cyClient / 2 *(1-sin(TWOPI * i / NUM)));
}
Polyline(hdc, apt, NUM);
return 0;
case WM_DESTROY:
PostQuitMeage(0);
return 0;
}
return DefWindowProc(hwnd, meage, wParam, lParam);} ⒌ 相关函数原型 ①
BOOL LineTo(HDC hdc,// device context handle
int nXEnd, // x-coordinate of line's ending point
int nYEnd
// y-coordinate of line's ending point);②
BOOL Polyline(HDC hdc,// handle to device context
CONST POINT *lppt, // pointer to array containing endpoints
int cPoints
// number of points in the array);③ BOOL PolylineTo(吉
林
化
工
学
院
第 47 页 教
案
用
纸
HDC hdc,// handle to device context
CONST POINT *lppt, // pointer to array of points
DWORD cCount
// number of points in array);④ BOOL PolyPolyline(HDC hdc,// handle to a device context
CONST POINT *lppt,// pointer to an array of points
CONST DWORD *lpdwPolyPoints, // pointer to an array of values
DWORD cCount
// count of entries in the second array);⑤ BOOL Arc(HDC hdc,// handle to device context
int nLeftRect,// x-coord of bounding rectangle's upper-left corner
int nTopRect,// y-coord of bounding rectangle's upper-left corner
int nRightRect, // x-coord of bounding rectangle's lower-right corner
int nBottomRect, // y-coord of bounding rectangle's lower-right corner
int nXStartArc, // first radial ending point
int nYStartArc, // first radial ending point
int nXEndArc,// second radial ending point
int nYEndArc
// second radial ending point);⑥ BOOL PolyBezier(HDC hdc,// handle to device context
CONST POINT *lppt, // pointer to endpoints and control points
DWORD cPoints
// count of endpoints and control points);⑦ BOOL PolyBezierTo(HDC hdc,// handle to device context
CONST POINT *lppt, // pointer to endpoints and control points
DWORD cCount
// count of endpoints and control points);⑧ BOOL MoveToEx(HDC hdc,// handle to device context
int X,// x-coordinate of new current position
int Y,// y-coordinate of new current position
LPPOINT lpPoint
// pointer to old current position);⒍ 程序片段
① 下面的代码从窗口的左上角开始,在客户区中画一个网格,线与线之间相隔100个像素。
吉
林
化
工
学
院
第 48 页 教
案
用
纸
GetClientRect(hwnd,&rect);fox(x=0;x
MoveToEx(hdc,x,0,NULL);
LineTo(hdc,x,rect.bottom);} for(y=0;y
MoveToEx(hdc,0,y,NULL);
LineTo(hdc,rect.right,y);} ② 用画线函数画一个矩形
POINT apt[5]={100,100,200,100,200,200,100,200,100,100};MovtToEx(hdc,apt[0].x,apt[0].y,NULL);for(i=1;i
LineTo(hdc,apt[i].x,apt[i].y);注意:最后一个点与第一个点坐标相同。③ 用Polyline函数画矩形
Polyline(hdc,apt,5);//等同于Polyline(hdc,apt,sizeof(apt)/sizeof(POINT));注意:虽然与②效果相同,但Polyline既不使用也不改变当前位置。PolylineTo则不同,它使用当前位置作为开始点,并将当前位置设置为最后一根线的终点。
MoveToEx(hdc,apt[0].x,apt[0].y,NULL);PolylineTo(hdc,apt+1,4);⒎ 边界框函数
Rectangle、Ellipse、RoundRect、Chord、Pie函数是在画线,但它们同时又在使用当前的区域填充一个封闭区域。这些函数的共性是基于一个矩形边界框的。用户定义一个包含该对象的框,即“边界框”;Windows就在这个框内画出该对象。
① Rectangle
Rectangle(hdc,1,1,5,4);
吉
林
化
工
学
院
第 49 页 教
案
用
纸
画矩形边框示意图:
② Ellipse函数
③ RoundRect函数
吉
林
化
工
学
院
第 50 页 教
案
用
纸
④ Arc函数
⑤ Chord函数
⑥ Pie函数
吉
林
化
工
学
院
第 51 页 教
案
用
纸
⒏ LineDemo程序片段
LRESULT CALLBACK WndProc(HWND hwnd, UINT meage, WPARAM wParam, LPARAM lParam){
static int cxClient, cyClient;
HDC
hdc;
PAINTSTRUCT ps;
switch(meage)
{
case WM_SIZE:
cxClient = LOWORD(lParam);
cyClient = HIWORD(lParam);
return 0;
case WM_PAINT:
hdc = BeginPaint(hwnd, &ps);
Rectangle(hdc,cxClient / 8,cyClient / 8,* cxClient / 8, 7 * cyClient / 8);
MoveToEx(hdc,0,0, NULL);
LineTo
(hdc, cxClient, cyClient);
MoveToEx(hdc,0, cyClient, NULL);
LineTo
(hdc, cxClient,0);
Ellipse
(hdc,cxClient / 8,cyClient / 8,* cxClient / 8, 7 * cyClient / 8);
RoundRect(hdc,cxClient / 4,cyClient / 4,* cxClient / 4, 3 * cyClient / 4,cxClient / 4,cyClient / 4);
EndPaint(hwnd, &ps);
return 0;
case WM_DESTROY:
PostQuitMeage(0);
return 0;
}
return DefWindowProc(hwnd, meage, wParam, lParam);} 五
画笔
⒈ 使用现有画笔(Stock Pens)
Windows使用设备描述表中当前选中的“画笔”来画线。画笔决定线的色彩、宽度和线型,线型可以是实线、点划线或者虚线,默认设备描述表中画笔为BLACK_PEN。不管映射方式是什么,这种画笔都画出一个像素宽的黑色实线来。除了BLACK_PEN,Windows还提供WHITE_PEN和NULL_PEN两种画笔。
可以采用如下方式使用现有画笔: HPEN hPen;hPen=GetStorckObject(WHITE_PEN);SelectObject(hdc,hPen);吉
林
化
工
学
院
第 52 页 教
案
用
纸
或者:
SelectObject(hdc,GetStockObject(WHITE_PEN));
再或者: HPEN hPen;SelectObject(hdc,GetStockObject(BLACK_PEN));hPen=SelectObject(hdc,GetStockObject(WHITE_PEN));hPen是BLACK_PEN的句柄。
可以使用SelectObject(hdc,hPen);将BLACK_PEN选进设备描述表。⒉ 画笔的创建、选择和删除
使用函数CreatPen或CreatePenIndirect创建一个“逻辑画笔”,这些函数返回逻辑画笔的句柄,调用SelectObject将画笔选进设备描述表。在任何时候,都只能有一种画笔选进设备描述表。在释放设备描述表(或者在选择了另一种画笔到设备描述表中)之后,就可以调用DeleteObject来删除所创建的逻辑画笔。
① GDI对象
逻辑画笔、刷子、位图、区域、字体和调色板。除了调色板,这些对象都是通过SelectObject选进设备描述表的。
② 使用GDI对象的规则
◆ 最后要删除自己创建的所有GDI对象;
◆ 当GDI对象正在一个有效的设备描述表时,不要删除它; ◆ 不要删除现有对象。③ CreatePen函数
HPEN CreatePen(int fnPenStyle, // pen style int nWidth, // pen width COLORREF crColor // pen color);
fnPenStyle为画笔的类型,即:
PS_SOLID、PS_DASH、PS_DOT、PS_DASHDOT、PS_DASHDOTDOT、PS_NULL、PS_INSIDEFRAME ④ DeleteObject函数
BOOL DeleteObject(HGDIOBJ hObject // handle to graphic object);
吉
林
化
工
学
院
第 53 页