正文

游戏编程起源(初学者)Ⅵ (三)2006-01-28 12:19:00

【评论】 【打印】 【字体: 】 本文链接:http://blog.pfan.cn/mroske/9908.html

分享到:

GDI显示位图
记得我告诉过你位图是很容易操纵的,因为Windows本身就是位图。现在让我们看看到底有多容易吧!用GDI显示位图需要四个基本的步骤:
1
、得到你要操作的窗口的DC句柄。
2
、获得位图的句柄。
3
、为位图创建设备上下文。
4
、传送位图。
你已经知道第一步怎么做了,以前我也间接提到过第二步的做法,但没有具体说。我说过通过函数LoadBitmap()可以得到位图资源的句柄,但它有些过时了,有一个更灵活的函数LoadImage()取代了它,现在让我们看看怎么使用这个新函数。原形如下:

HANDLE LoadImage(
    HINSTANCE hinst,  // handle of the instance containing the image
    LPCTSTR lpszName, // name or identifier of image
    UINT uType,       // type of image
    int cxDesired,    // desired width
    int cyDesired,    // desired height
    UINT fuLoad       // load flags
);


如果函数调用失败,返回NULL。成功,你得到位图的句柄,意味着你就可以从资源或外部文件调用位图了。注意,这个函数还可以取得光标、图标的句柄,所以返回类型只是简单的HANDLE。在Visual C++6.0中,你需要用HBITMAP类型定义位图的句柄变量,否则编译器会生气的。例如:

HBITMAP hBitmap
hBitmap
LoadImage……);

下面是LoadImage()函数的参数说明:
HINSTANCE hinst:如果你从资源调用位图,这应该是你的应用程序的实例。如果你要从外部文件调用位图,就把它设置为NULL
LPCTSTR lpszName:这个要么是资源标识符,记住用MAKEINTRESOURCE()宏转变数字常量;要么就是你要调用的图象的完整文件名称。
UINT uType:根据你的调用对象来决定。应该是IMAGE_BITMAPIMAGE_CURSORIMAGE_ICON中的一种。
int cxDesiredcyDesired:这是你希望的图象的尺寸。如果你都设置为0,将是图象的真实尺寸。
UINT fuLoad:这是可以组合用的标志,当然是用“|”来连接。以下是一些常用的标志:
LR_CREATEDIBSECTION:如果uTypeIMAGE_BITMAP,将导致函数返回一个DIBDIB,设备无关的位图)。基本的意思就是返回一个不依赖于显示设备的位图。
LR_DEFAULTSIZE:对于光标和图标,如果cxDesiredcyDesired都设置为0,这个标志将启用Windows的默认尺寸,而不是图形的实际尺寸。
LR_LOADFROMFILE:如果你要从外部文件中调入图象,你就必须用这个标志。
条件允许的话,你应当尽量使用LR_CREATEDIBSECTIONLR_LOADFROMFILE这两个标志。现在,你已经得到了图象(过去我们总说位图,好像不太准确,毕竟有时我们不从资源里调用)的句柄,下一步你必须建立设备上下文把图象放进去。位图的应该独有的特点是:它只能被选入到内存设备上下文中。内存设备上下文被定义为一个具有显示表面的设备上下文。它只存在于内存中,并且与特定的设备上下文相关。使用内存设备上下文,你必须首先创建它。CreateCompatibleDC()函数正是用于这个目的。它的一般形式如下:

HDC CreateCompatibleDC(HDC hdc);

函数唯一的参数是与内存设备上下文相兼容的设备上下文句柄。如果内存设备上下文与视频屏幕兼容,则这个参数可以为NULL。我们就用NULL。如果函数失败,返回NULL。现在,我们把位图(或图象)放入内存失败上下文,我们用这个函数:

HGDIOBJ SelectObject(
    HDC hdc,         // handle to device context
    HGDIOBJ hgdiobj  // handle to object
);

函数的返回类型HGDIOBJ是一个比HBITMAP更通用的类型。不用担心,HGDIOBJHBITMAP的一致性没有任何问题。以下是函数的参数说明:
HDC hdc:是设备上下文的句柄。要调用图象,必须是内存设备上下文的句柄。
HGDIOBJ hgdiobj:要调用对象的的句柄。可调用的有位图、画刷、字体、画笔等。这里是位图(图象)的句柄。
返回值是要调入设备上下文中的对象的句柄。这里是位图的句柄。如果失败,返回NULL
现在你已经把位图装入设备上下文,你还需要进行最后的一步:把内存DC里的内容拷贝到显示设备上下文中。然而,我们首先要得到位图的一些信息,如尺寸,这是显示图象时必须的。所以,我们还需要另一个函数GetObject(),它可以用于获得对象的信息,当然,这里我们是要获得位图的信息。函数的一般形式如下:

int GetObject(
    HGDIOBJ hgdiobj,  // handle to graphics object of interest
    int cbBuffer,     // size of buffer for object information
    LPVOID lpvObject  // pointer to buffer for object information
);

返回值是一个字节数。如果失败,返回0。当GetObject()调用的目标是位图时,返回的信息是与位图的宽度、高度和颜色格式有关的结构成员。参数说明如下:
HGDIOBJ hgdiobj:要得到信息的对象的句柄。这里我们传送位图的句柄。
int cbBuffer:存放调用返回的信息的缓冲区的大小。对于位图,我们将得到BITMAP类型结构,所以这里设置成sizeofBITMAP)。
LPVOID lpvObject:指向存放由调用返回的信息的缓冲区的指针。
你需要定义一个BITMAP结构类型的变量,调用GetObject()函数放入缓冲区的信息。由于BITMAP结构对我们来说是一个新的结构,所以就介绍一下:

typedef struct tagBITMAP { // bm
    LONG bmType;
    LONG bmWidth;
    LONG bmHeight;
    LONG bmWidthBytes;
    WORD bmPlanes;
    WORD bmBitsPixel;
    LPVOID bmBits;
} BITMAP;

很多成员,但我们实际上只对其中的两个有兴趣。但我们还是都介绍一下:
LONG bmType:指定位图类型,必须为0。有用吧!
LONG bmWidthbmHeight:分别是位图的宽度和高度,以象素为单位。必须都大于0
LONG bmWidthBytes:指定每一行扫描线中的字节数。因为Windows假定位图是字对齐的,所以这个值必须能够被2整除。
LONG bmPlanes:指定颜色面的数目。
LONG bmBitsPixel:指定表述象素颜色所需的位数。(好像没什么用)
LPVOID bmBits:如果你想存取实际的位图数据,这个指针指向位图位值得位置。
OK
,差不多了。一旦位图被选入内存设备上下文,且代码已经得到了位图宽度和高度的必要信息后,我们就可以将内存中存储的位图通过位块传输到达屏幕,然后在任意位置对它进行显示。我说过处理位图是很容易的,对吧?(如果你觉得不容易,只能怪我说的不够好)有两个函数需要说明,先说第一个:

BOOL BitBlt(
    HDC hdcDest, // handle to destination device context
    int nXDest,  // x-coordinate of destination rectangle's upper-left corner
    int nYDest,  // y-coordinate of destination rectangle's upper-left corner
    int nWidth,  // width of destination rectangle
    int nHeight, // height of destination rectangle
    HDC hdcSrc,  // handle to source device context
    int nXSrc,   // x-coordinate of source rectangle's upper-left corner
    int nYSrc,   // y-coordinate of source rectangle's upper-left corner
    DWORD dwRop  // raster operation code
);

BitBlt()
函数是执行位图显示操作最简单且最直接的方法。根据函数调用的成功或失败,返回值是TRUEFALSE。布尔函数都是这样。有很多参数,但很好理解:
HDC hdcDest:目标设备上下文句柄。根据我们的情况,应该是显示设备上下文句柄。
int nXDestnYDest:目标矩形左上角的xy坐标,也就是被显示的位图左上角的屏幕位置。
int nWidthnHeight:位图的宽度和高度。
HDC hdcSrc:原来的设备上下文句柄。根据我们的情况,应该是内存设备上下文句柄。
int nXSrcnYSrc:源位图的xy坐标。由于进行位块传输的矩形必须与在参数nWidth和参数nHeight中定义的尺寸相同,所以通常都设为0。但不一定总是这样,例如你只想显示位图的一部分,就不能都设置为0
DWORD dwRop:有很多光栅代码你可以选择,但只有一个我们感兴趣,SRCCOPY。它直接把源DC内的内容拷贝到目标DC中。

阅读(3038) | 评论(0)


版权声明:编程爱好者网站为此博客服务提供商,如本文牵涉到版权问题,编程爱好者网站不承担相关责任,如有版权问题请直接与本文作者联系解决。谢谢!

评论

暂无评论
您需要登录后才能评论,请 登录 或者 注册