/* 模块名: DDCom.cpp 为DirectDraw提供一次封装。 Magix - Heartblue all right reserved 2001 - 10 -1 2002 - 1 提供对写显存的支持。 2002 - 7 提供对读显存的支持,改进了对写显存的算法 由于本人的懒惰。没有对表面的丢失,和裁减器提供支持。 现在Heartblue正在研究 D3D 和 OGL 实在没有时间。能用就先用着了 */ #include "ddraw.h" #include "windows.h" #include "ddcom.h" #include "math.h" #include "AppCom.h" //========================================= // Function Name: DDErroInfo // Description : 打印错误信息 //========================================= void DDErroInfo(char* strInfo) { MessageBox(g_AppData.hWnd,strInfo,"DirectX 错误",MB_OK); } //+++++++++++++++++++++++++++++++++++++++++++++++ //========================================= // Function Name: DDExit // Description : 打印错误信息并退出 //========================================= void DDExit(char* strInfo) { MessageBox(g_AppData.hWnd,strInfo,"DirectX 错误",MB_OK); PostQuitMessage(0); } //++++++++++++++++++++++++++++++++++++++++ //====================================== // Function Name: DDrawInit // Description : 初始化Direct Draw //======================================= BOOL DDrawInit(HWND hWnd,LPDIRECTDRAW7* lppDD7,BOOL fFullScreen,GUID FAR *lpGUID) { //Create DirectDraw HRESULT hr=DirectDrawCreateEx(lpGUID,(void**)lppDD7,IID_IDirectDraw7,NULL); if(hr==DDERR_INVALIDDIRECTDRAWGUID) { DDExit("需要DirectX7.0版本,请升级你DirectX到7.0版!"); return FALSE; } if (hr!=DD_OK) { DDExit("创建DirectDraw时发生错误!"); return FALSE; } //Direct Draw Creat Success //Set Cooperateive Level if(fFullScreen) //FullScreen hr=(*lppDD7)->SetCooperativeLevel(hWnd,DDSCL_FULLSCREEN|DDSCL_EXCLUSIVE); else //Normal Mode hr=(*lppDD7)->SetCooperativeLevel(NULL,DDSCL_NORMAL); //Set Cooperative Level Faile switch (hr) { case DDERR_EXCLUSIVEMODEALREADYSET: DDExit("不能同时运行两个全屏幕的DX程序"); return FALSE; case DDERR_HWNDALREADYSET : DDErroInfo("合作级别已经设置"); return FALSE; case DDERR_OUTOFMEMORY : DDExit("内存不足"); return FALSE; } if(hr!=DD_OK) { DDExit("程序初始化失败"); return FALSE; } return TRUE; } //+++++++++++++++++++++++++++++++++++++++++++ //======================================== // Function Name: ReleaseDDraw // Description : Release Directx object //======================================== void ReleaseDDraw(LPDIRECTDRAW7 lpDD7) { if(lpDD7) { lpDD7->RestoreDisplayMode(); lpDD7->Release(); } } //++++++++++++++++++++++++++++++++++++++++++++++ //========================================= // Function Name: CreateMainSurface // Description : 创建DIRECTX 主表面 //========================================= BOOL CreateMainSurface(LPDIRECTDRAW7 lpDD7,LPDIRECTDRAWSURFACE7 *lppDDS) { DDSURFACEDESC2 ddsd; ZeroMemory(&ddsd,sizeof(ddsd)); ddsd.dwSize=sizeof(ddsd); ddsd.dwFlags=DDSD_CAPS; ddsd.ddsCaps.dwCaps=DDSCAPS_PRIMARYSURFACE|DDSCAPS_VIDEOMEMORY; if(lpDD7==NULL) { DDExit("创建主表面失败!DirectDraw对象未创建。"); return FALSE; } HRESULT hr=lpDD7->CreateSurface(&ddsd,lppDDS,NULL); if(hr!=DD_OK) { DDExit("创建主表面失败!"); return FALSE; } return TRUE; } //+++++++++++++++++++++++++++++++++++++++++ //========================================= // Function Name: CreateFilpSurface // Description : 创建DIRECTX 翻转表面 //========================================= BOOL CreateFilpSurface(LPDIRECTDRAW7 lpDD7, //DirectDrawObject IN LPDIRECTDRAWSURFACE7 *lppDDSPrim, //Main surface OUT LPDIRECTDRAWSURFACE7 *lppDDSBack, //Back Surface OUT int nBuffer, DWORD dwFlag) //The number of the backbuffer IN { DDSURFACEDESC2 ddsd; ZeroMemory(&ddsd, sizeof(ddsd)); ddsd.dwSize = sizeof(ddsd); ddsd.dwFlags = DDSD_CAPS|DDSD_BACKBUFFERCOUNT; ddsd.ddsCaps.dwCaps = dwFlag; ddsd.dwBackBufferCount =1; if(lpDD7==NULL) { DDExit("创建主表面失败!DirectDraw对象未创建。"); return FALSE; } HRESULT hr=lpDD7->CreateSurface(&ddsd,lppDDSPrim,NULL); if(hr!=DD_OK) { DDExit("创建主表面失败!"); return FALSE; } //===Get BackBuffer========== DDSCAPS2 ddscaps; ZeroMemory(&ddscaps, sizeof(ddscaps)); ddscaps.dwCaps = DDSCAPS_BACKBUFFER; hr=(*lppDDSPrim)->GetAttachedSurface(&ddscaps, lppDDSBack); if(hr!=DD_OK) { DDExit("创建后备表面失败!"); return FALSE; } return TRUE; } //========================================= // Function Name: CreateSurface // Description : 创建DIRECTX 表面 //========================================= BOOL CreateSurface( LPDIRECTDRAW7 lpDD7, //DirectDraw Object LPDIRECTDRAWSURFACE7 *lppDDS, //The surface want to be created DWORD width,DWORD height, //The Width and the height DWORD dwFlag)//Addition Flags { DDSURFACEDESC2 ddsd; ZeroMemory(&ddsd,sizeof(ddsd)); ddsd.dwSize = sizeof(ddsd); ddsd.dwFlags = DDSD_CAPS|DDSD_HEIGHT|DDSD_WIDTH; ddsd.ddsCaps.dwCaps=dwFlag; ddsd.dwHeight=height; ddsd.dwWidth=width; if(lpDD7==NULL) { DDExit("创建表面失败!DirectDraw对象未创建。"); return FALSE; } HRESULT hr=lpDD7->CreateSurface(&ddsd,lppDDS,NULL); if(hr!=DD_OK) { DDExit("创建表面失败!"); return FALSE; } return TRUE; } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++ //===================================================== // Function Name: CreateOffScreenSurface // Description : Create a offscreen surface //===================================================== BOOL CreateOffScreenSurface( LPDIRECTDRAW7 lpDD7, //DirectDraw Object LPDIRECTDRAWSURFACE7 *lppDDS, //The surface want to be created DWORD width,DWORD height ) { return CreateSurface( lpDD7, //DirectDraw Object lppDDS, //The surface want to be created width, height, DDSCAPS_OFFSCREENPLAIN); } //+++++++++++++++++++++++++++++++++++++++++++++++++++++ //===================================================== // Function Name: CreateSystemMemSurface // Description : Create a offscreen surface On system memory //===================================================== BOOL CreateSystemMemSurface( LPDIRECTDRAW7 lpDD7, //DirectDraw Object LPDIRECTDRAWSURFACE7 *lppDDS, //The surface want to be created DWORD width,DWORD height ) { return CreateSurface( lpDD7, //DirectDraw Object lppDDS, //The surface want to be created width, height, DDSCAPS_SYSTEMMEMORY); } //+++++++++++++++++++++++++++++++++++++++++++++++++++++ //============================================ // Function Name: LoadBmpFromFile // Description : Load a bitmap From File //============================================ HBITMAP LoadBitmapFromFile(char* fileName,BITMAP *bmp) { HBITMAP hbmp=NULL; //Load the bitmap hbmp=(HBITMAP)LoadImage( NULL,fileName, IMAGE_BITMAP,NULL,NULL, LR_DEFAULTSIZE|LR_LOADFROMFILE); if(hbmp==NULL) { DDExit("无效的位图或无效的文件名!"); return NULL; } if(hbmp!=NULL && bmp!=NULL) { GetObject(hbmp,sizeof(BITMAP),(void*)bmp); } return hbmp; } //+++++++++++++++++++++++++++++++++++++++++ //=========================================================== // Function Name : LoadDibSurface // Description : Load a BitMap From a DIB data //========================================================== BOOL LoadDibSurface(DIBMAP dib ,LPDIRECTDRAWSURFACE7 surface) { DRAWSTRUCT ds; COLOR p; BeginDraw(&ds,surface); for(int i=0;i<dib.height;i++) for(int="" j="0;j<dib.width;j++)" getcolor(dib,j,i,&p);="" setcolor(ds,j,i,&p);="" enddraw(surface);="" 1;="" name="" loadbitmapresource="" from="" a="" resource="" id="" loadbitmapresource(hinstance="" hinst,uint="" ubmpid,bitmap="" *bmp)="" hbitmap="" load="" the="" bitmap="" hbmp="NULL;" if(hbmp="=NULL)" 无效的位图或无效的文件名!="" null;="" if(hbmp!="NULL" &&="" bmp!="NULL)" getobject(hbmp,sizeof(bitmap),(void*)bmp);="" hbmp;="" +++++++++++++++++++++++++++++++++++++++++="" function="" name:="" ddexitfullscreen="" description="" :="" 退出全屏幕状态="" bool="" ddfullscreen(lpdirectdraw7="" lpdd7)="" if(lpdd7="=NULL)" {="" ddexit(="" 设置分辨率错误!directdraw对象未创建。="" );="" return="" false;="" }="" if(lpdd7-="">SetDisplayMode(g_AppData.xLine,g_AppData.yLine,g_AppData.colorBit,0,0)!=DD_OK) { DDExit("设置分辨率错误!终止程序"); return FALSE; } return TRUE; } //++++++++++++++++++++++++++++++++++++++++ //========================================= // Function Name: DDExitFullScreen // Description : 退出全屏幕状态 //========================================= BOOL DDExitFullScreen(LPDIRECTDRAW7 lpDD7) { if(lpDD7==NULL) { DDExit("恢复分辨率错误!DirectDraw对象未创建。"); return FALSE; } return lpDD7->RestoreDisplayMode(); } //++++++++++++++++++++++++++++++++++++++++++ //========================================== // Function Name: DDBmpToSurface // Description : 把哟个位图加载到一个表面 //============================================ BOOL DDBmpToSurface(LPDIRECTDRAWSURFACE7 pdds, HBITMAP hbm) { HDC hdcImage; HDC hdc; DDSURFACEDESC2 ddsd; BOOL retValue; HRESULT hr; if (hbm == NULL) { DDExit("无效位图"); return FALSE; } if (pdds == NULL) { DDExit("无效表面"); return FALSE; } // Create compatible DC and select bitmap into it hdcImage = CreateCompatibleDC(NULL); if (!hdcImage) { DDExit("内部错误,创建DC失败"); return FALSE; } SelectObject(hdcImage, hbm); // Get size of surface ddsd.dwSize = sizeof(ddsd); ddsd.dwFlags = DDSD_HEIGHT | DDSD_WIDTH; pdds->GetSurfaceDesc(&ddsd); if ((hr = pdds->GetDC(&hdc)) != DD_OK) { DDExit("内部错误,创建DC失败"); return FALSE; } retValue = BitBlt(hdc, 0, 0, ddsd.dwWidth, ddsd.dwHeight, hdcImage, 0, 0, SRCCOPY); // Release surface immediately pdds->ReleaseDC(hdc); if(retValue == FALSE) { DDExit("内部错误:位图传输失败!"); return FALSE; } DeleteDC(hdcImage); return TRUE; } //++++++++++ //Call this faunction before call DrawPixel+++++++++++++++++++++++++++++++++ BOOL BeginDraw(DRAWSTRUCT* pDS,LPDIRECTDRAWSURFACE7 pdds) { DDSURFACEDESC2 ddsd; ddsd.dwSize = sizeof (DDSURFACEDESC2); pdds->Lock(NULL,&ddsd,DDLOCK_WAIT,NULL); pDS->lpSurface = (BYTE*)ddsd.lpSurface;//The Memory address of the surface pDS->lPitch = ddsd.lPitch;//Line size; return true; } //===Draw a pixel to a locked surface void SetColor(DRAWSTRUCT& DS,int x,int y,COLORREF cl) { BYTE *pLine=DS.lpSurface+y*DS.lPitch+4*x; *(pLine++)=0x000000ff&cl>>16; *(pLine++)=(0x0000ff00&cl)>>8; *(pLine++)=(0x00ff0000&cl); *pLine=(0xff000000&cl)>>24; } void SetColor(DRAWSTRUCT& DS,int x,int y,COLOR* pc) { BYTE *pLine=DS.lpSurface+y*DS.lPitch+4*x; *(pLine++)=pc->b; *(pLine++)=pc->g; *(pLine++)=pc->r; *pLine=pc->a; } void GetColor(DRAWSTRUCT& DS,int x,int y,COLOR* pc) { BYTE *pLine=DS.lpSurface+y*DS.lPitch+4*x; pc->b=*(pLine++);//=0x000000ff&cl; pc->g=*(pLine++);//=(0x0000ff00&cl)>>8; pc->r=*(pLine++);//=(0x00ff0000&cl)>>16; pc->a=*pLine;//=(0xff000000&cl)>>24; } //=====Call this faunction after call DrawPixel BOOL EndDraw(LPDIRECTDRAWSURFACE7 pdds) { pdds->Unlock(NULL); return true; } LONG GetPitch(DRAWSTRUCT* pDS) { return pDS->lPitch; } BYTE* GetSurface(DRAWSTRUCT DS) { return DS.lpSurface; } //========================================================= // Function Name : DDEnumCallback // Description : 枚举显示驱动程序的回调函数 //========================================================= BOOL WINAPI DisplayDriverProc( GUID FAR *lpGUID, LPSTR lpDriverDescription, LPSTR lpDriverName, LPVOID lpContext) { PDDENUMINFO pei=(PDDENUMINFO)lpContext; static int n=0; static int Max=pei->Totol; PDRIVERINFO pdi=(PDRIVERINFO)(lpContext); strcpy(pei->pdi[n].DriverDescription,lpDriverDescription); strcpy(pei->pdi[n].DriverName,lpDriverName); pei->pdi[n].guid=*lpGUID; n++; pei->Totol=n; if(n>Max) return 0; else return 1; } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ //=============================================== // Function name : DisplayModeProc // Description : The CallBack function of the enumdiaplaymodes //================================================ HRESULT WINAPI DisplayModeProc(LPDDSURFACEDESC2 pSurface,LPVOID pContext) { static int n = 0; //可用的显示模式数 int *pArry = (int*)pContext; static int Max = pArry[0]; //可以保存的显示模式数 PDISPLAYMODE pdm = (PDISPLAYMODE)( (int*)pContext+1); //Saveing the Modes pdm[n].xPixel =pSurface->dwWidth; pdm[n].yPixel =pSurface->dwHeight; pdm[n].colorBit =pSurface->ddpfPixelFormat.dwRGBBitCount; pdm[n].flesh =pSurface->dwRefreshRate; //======== n++; pArry[0]=n; if(n>Max) return DDENUMRET_CANCEL;//Exit Enum else return DDENUMRET_OK; //Continus } //++++++++++++++++++++++++++++++++++++++++++++++++++ //====================================================== // Function Name : HasDisplayMode // Description : Test if the Display Modes is availide //====================================================== BOOL HasDisplayMode(LPDIRECTDRAW7 lpDD7,int x,int y,int depth,int flesh) { if(flesh) { int context[801]; context[0]=200; lpDD7->EnumDisplayModes(DDEDM_REFRESHRATES, NULL, (LPVOID)context, DisplayModeProc); int Max=context[0]; PDISPLAYMODE pdm=(PDISPLAYMODE)(context+1); for(int i=0;i<max;i++) if(="" pdm[i].xpixel="=x" pdm[i].ypixel="=y" pdm[i].colorbit="=depth" &&="" pdm[i].flesh="=flesh)" true;="" return="" false;="" }="" else="" {="" int="" context[201];="" context[0]="50;" lpdd7-="">EnumDisplayModes(0, NULL, (LPVOID)context, DisplayModeProc); int Max=context[0];//Tatol Modes PDISPLAYMODE pdm=(PDISPLAYMODE)(context+1); //Test the Given Mode for(int i=0;i<max;i++) if(="" pdm[i].xpixel="=x" pdm[i].ypixel="=y" &&="" pdm[i].colorbit="=depth)" true;="" return="" false;="" }="" ++++++++++++++++++++++++++++++++++++++++++++++++++++++="" function="" name:="" max="" description="" :="" find="" and="" min="" in="" the="" two="" number="" long="" min(long="" a,long="" b)="" {="" if(a="">b)return b; return a; } LONG Max(LONG a,LONG b) { if(a>b)return a; return b; } //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ //========================================================== // Function Name: Dist // Description : Get the distance of the tow point //========================================================== double Dist(POINT a,POINT b) { return sqrt( (a.x-b.x)*(a.x-b.x)+(a.y -b.y)*(a.y -b.y) ); } LONG Dist2(POINT a,POINT b) { return (a.x-b.x)*(a.x-b.x)+(a.y -b.y)*(a.y -b.y); } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ //+++++++++++++++++++++++++++++++++++++++++++ LPDIRECTDRAWCLIPPER g_lpDDC; void SetClipper(LPDIRECTDRAW7 lpDD7,LPDIRECTDRAWSURFACE7 lpDDS) { lpDD7->CreateClipper(0,&g_lpDDC,NULL); g_lpDDC->SetHWnd(0,g_AppData.hWnd); lpDDS->SetClipper(g_lpDDC); } void ReleaseClipper() { g_lpDDC->Release(); }