www.gusucode.com > VC++游戏圣剑英雄传2双刃剑源程序+开发文档-源码程序 > VC++游戏圣剑英雄传2双刃剑源程序+开发文档-源码程序\code\source\GAMELIB\Ddutil.cpp
//Download by http://www.NewXing.com /*========================================================================== * * Copyright (C) 1995-1996 Microsoft Corporation. All Rights Reserved. * * File: ddutil.cpp * Content: Routines for loading bitmap and palettes from resources * ***************************************************************************/ #undef WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN #include <windows.h> #include <stdio.h> #include <windowsx.h> #include <ddraw.h> #include "ddutil.h" //创建一个页面,并加载一个bmp图片 extern "C" IDirectDrawSurface * DDLoadBitmap(IDirectDraw *pdd, LPCSTR szBitmap, int dx, int dy) { HBITMAP hbm; BITMAP bm; DDSURFACEDESC ddsd; IDirectDrawSurface *pdds; //当一个资源 hbm = (HBITMAP)LoadImage(GetModuleHandle(NULL), szBitmap, IMAGE_BITMAP, dx, dy, LR_CREATEDIBSECTION); //失败,当一个文件 if (hbm == NULL) hbm = (HBITMAP)LoadImage(NULL, szBitmap, IMAGE_BITMAP, dx, dy, LR_LOADFROMFILE|LR_CREATEDIBSECTION); if (hbm == NULL) return NULL; //得到图片大小 GetObject(hbm, sizeof(bm), &bm); //创建页面 ZeroMemory(&ddsd, sizeof(ddsd)); ddsd.dwSize = sizeof(ddsd); ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT |DDSD_WIDTH; ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN; ddsd.dwWidth = bm.bmWidth; ddsd.dwHeight = bm.bmHeight; if (pdd->CreateSurface(&ddsd, &pdds, NULL) != DD_OK) return NULL; //加载图片 DDCopyBitmap(pdds, hbm, 0, 0, 0, 0); DeleteObject(hbm); return pdds; } //显示一个bmp到一个页面 HRESULT DDReLoadBitmap(IDirectDrawSurface *pdds, LPCSTR szBitmap) { HBITMAP hbm; HRESULT hr; //当一个资源来加载 hbm = (HBITMAP)LoadImage(GetModuleHandle(NULL), szBitmap, IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION); //失败,当一个文件加载 if (hbm == NULL) hbm = (HBITMAP)LoadImage(NULL, szBitmap, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE|LR_CREATEDIBSECTION); //仍然失败 if (hbm == NULL) { char str[128]; sprintf(str, "handle is null [%s]\n", szBitmap); OutputDebugString(str); return E_FAIL; } //把图片显示到页面 hr = DDCopyBitmap(pdds, hbm, 0, 0, 0, 0); if (hr != DD_OK) { OutputDebugString("ddcopybitmap failed\n"); } DeleteObject(hbm); return hr; } //在一个页面上显示一个bmp图片 extern "C" HRESULT DDCopyBitmap(IDirectDrawSurface *pdds, HBITMAP hbm, int x, int y, int dx, int dy) { HDC hdcImage; HDC hdc; BITMAP bm; DDSURFACEDESC ddsd; HRESULT hr; if (hbm == NULL || pdds == NULL) return E_FAIL; pdds->Restore(); //创建一个和当前屏幕相关的 memory device context hdcImage = CreateCompatibleDC(NULL); if (!hdcImage) OutputDebugString("createcompatible dc failed\n"); SelectObject(hdcImage, hbm); //得到bmp的大小 GetObject(hbm, sizeof(bm), &bm); dx = dx == 0 ? bm.bmWidth : dx; // 只要传进来的参数不是0,就使用传进来的参数 dy = dy == 0 ? bm.bmHeight : dy; //得到页面的大小 ddsd.dwSize = sizeof(ddsd); ddsd.dwFlags = DDSD_HEIGHT | DDSD_WIDTH; pdds->GetSurfaceDesc(&ddsd); if ((hr = pdds->GetDC(&hdc)) == DD_OK) { //缩放blt StretchBlt(hdc, 0, 0, ddsd.dwWidth, ddsd.dwHeight, hdcImage, x, y, dx, dy, SRCCOPY); pdds->ReleaseDC(hdc); } DeleteDC(hdcImage); return hr; } //从一个bmp图片创建一个调色板,要是没有的话就创建一个缺省的调色板 extern "C" IDirectDrawPalette * DDLoadPalette(IDirectDraw *pdd, LPCSTR szBitmap) { IDirectDrawPalette* ddpal; int i; int n; int fh; HRSRC h; LPBITMAPINFOHEADER lpbi; PALETTEENTRY ape[256]; RGBQUAD * prgb; //创建一个缺省的调色板 for (i=0; i<256; i++) { //0x07 = 00000111b 0x03 = 00000011b //3 bit 描述红色, 3 bit 描述绿色, 2 bit 描述蓝色 //为什么呢?简单,让调色板的序号和颜色直接挂上钩 ape[i].peRed = (BYTE)(((i >> 5) & 0x07) * 255 / 7); ape[i].peGreen = (BYTE)(((i >> 2) & 0x07) * 255 / 7); ape[i].peBlue = (BYTE)(((i >> 0) & 0x03) * 255 / 3); ape[i].peFlags = (BYTE)0; } //从bmp图片加载 if (szBitmap && (h = FindResource(NULL, szBitmap, RT_BITMAP))) { lpbi = (LPBITMAPINFOHEADER)LockResource(LoadResource(NULL, h)); if (!lpbi) OutputDebugString("lock resource failed\n"); prgb = (RGBQUAD*)((BYTE*)lpbi + lpbi->biSize); if (lpbi == NULL || lpbi->biSize < sizeof(BITMAPINFOHEADER)) n = 0; else if (lpbi->biBitCount > 8) n = 0; else if (lpbi->biClrUsed == 0) n = 1 << lpbi->biBitCount; else n = lpbi->biClrUsed; //BGR转化成RGB for(i=0; i<n; i++ ) { ape[i].peRed = prgb[i].rgbRed; ape[i].peGreen = prgb[i].rgbGreen; ape[i].peBlue = prgb[i].rgbBlue; ape[i].peFlags = 0; } } else if (szBitmap && (fh = _lopen(szBitmap, OF_READ)) != -1) { BITMAPFILEHEADER bf; BITMAPINFOHEADER bi; _lread(fh, &bf, sizeof(bf)); _lread(fh, &bi, sizeof(bi)); _lread(fh, ape, sizeof(ape)); _lclose(fh); if (bi.biSize != sizeof(BITMAPINFOHEADER)) n = 0; else if (bi.biBitCount > 8) n = 0; else if (bi.biClrUsed == 0) n = 1 << bi.biBitCount; else n = bi.biClrUsed; //同样的方法 for(i=0; i<n; i++ ) { BYTE r = ape[i].peRed; ape[i].peRed = ape[i].peBlue; ape[i].peBlue = r; } } //创建调色板 pdd->CreatePalette(DDPCAPS_8BIT, ape, &ddpal, NULL); return ddpal; } //获得指定颜色所对应的调色板索引 extern "C" DWORD DDColorMatch(IDirectDrawSurface *pdds, COLORREF rgb) { COLORREF rgbT; HDC hdc; DWORD dw = CLR_INVALID; DDSURFACEDESC ddsd; HRESULT hres; if (rgb != CLR_INVALID && pdds->GetDC(&hdc) == DD_OK) { rgbT = GetPixel(hdc, 0, 0); // 保存当前值 SetPixel(hdc, 0, 0, rgb); // 设置成我们的值 pdds->ReleaseDC(hdc); } //读回我们的值 ddsd.dwSize = sizeof(ddsd); while ((hres = pdds->Lock(NULL, &ddsd, 0, NULL)) == DDERR_WASSTILLDRAWING) ; if (hres == DD_OK) { dw = *(DWORD *)ddsd.lpSurface; // 转化成DWORD dw &= (1 << ddsd.ddpfPixelFormat.dwRGBBitCount)-1; // mask it to bpp pdds->Unlock(NULL); } if (rgb != CLR_INVALID && pdds->GetDC(&hdc) == DD_OK) { SetPixel(hdc, 0, 0, rgbT); //恢复原来的值 pdds->ReleaseDC(hdc); } return dw; } //设置透明色 extern "C" HRESULT DDSetColorKey(IDirectDrawSurface *pdds, COLORREF rgb) { DDCOLORKEY ddck; //颜色转化,要是有调色板的话,转化成索引值 ddck.dwColorSpaceLowValue = DDColorMatch(pdds, rgb); ddck.dwColorSpaceHighValue = ddck.dwColorSpaceLowValue; return pdds->SetColorKey(DDCKEY_SRCBLT, &ddck); }