/*   オフスクリーンサーフェスの透過処理 1999/ 3/29 宍戸 輝光 */ #include #include #include LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM); void draw(void); LPDIRECTDRAW lpDD=NULL; LPDIRECTDRAWSURFACE lpDDSPrimary=NULL,lpDDSBack=NULL,lpDDSOff=NULL; DDSURFACEDESC ddsd,ddsdo; DDSCAPS ddscaps; LPDIRECTDRAWPALETTE lpDPalette; LPBYTE lpBG; int iX=288,iY=208; int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow){ MSG msg; WNDCLASSEX wndclass ; PALETTEENTRY pePal[256]; int i; LPBYTE lpBuf; wndclass.cbSize = sizeof(wndclass); wndclass.style = CS_HREDRAW | CS_VREDRAW; wndclass.lpfnWndProc = WndProc; wndclass.cbClsExtra = 0; wndclass.cbWndExtra = 0; wndclass.hInstance = hInstance; wndclass.hIcon = NULL; wndclass.hCursor = LoadCursor(NULL,IDC_ARROW); wndclass.hbrBackground = (HBRUSH)GetStockObject(LTGRAY_BRUSH); wndclass.lpszMenuName = NULL; wndclass.lpszClassName = "CWindow"; wndclass.hIconSm = NULL; RegisterClassEx (&wndclass); HWND hwnd=CreateWindowEx(WS_EX_TOPMOST,"CWindow",NULL, WS_POPUP,0,0,640,480,NULL,NULL,hInstance,NULL); ShowWindow (hwnd,iCmdShow); // ウインドウを表示 UpdateWindow (hwnd); DirectDrawCreate(NULL,&lpDD,NULL); // DirectDrawオブジェクト作成 lpDD->SetCooperativeLevel(hwnd, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN); lpDD->SetDisplayMode(640,480,8); // 画面を640*480/8Bit モードに設定 FillMemory(&ddsd,0,sizeof(ddsd)); // プライマリサーフェス作成 ddsd.dwSize=sizeof(ddsd); ddsd.dwFlags=DDSD_CAPS| DDSD_BACKBUFFERCOUNT; ddsd.ddsCaps.dwCaps=DDSCAPS_PRIMARYSURFACE| DDSCAPS_FLIP | DDSCAPS_COMPLEX; ddsd.dwBackBufferCount = 1; lpDD->CreateSurface(&ddsd,&lpDDSPrimary,NULL); FillMemory(&ddsdo,0,sizeof(ddsdo)); // オフスクリーンサーフェス作成 ddsdo.dwSize=sizeof(ddsdo); ddsdo.dwFlags=DDSD_CAPS| DDSD_WIDTH| DDSD_HEIGHT; ddsdo.ddsCaps.dwCaps=DDSCAPS_OFFSCREENPLAIN; ddsdo.dwWidth=64; ddsdo.dwHeight=64; lpDD->CreateSurface(&ddsdo,&lpDDSOff,NULL); DDCOLORKEY ddck; ddck.dwColorSpaceLowValue=0; ddck.dwColorSpaceHighValue=0; lpDDSOff->SetColorKey(DDCKEY_SRCBLT,&ddck); lpDDSOff->Lock(NULL,&ddsdo,DDLOCK_WAIT,NULL); lpBuf=(BYTE*)ddsdo.lpSurface; // オフスクリーンサーフェスのポインタ FillMemory(lpBuf,64*64,1); for (i=16;i<48;i++) FillMemory(lpBuf+i*64+16,32,0); FillMemory(lpBuf+64*32+16,32,2); for (i=16;i<48;i++) lpBuf[32+i*64]=2; lpDDSOff->Unlock(NULL); // バックバッファ取得 ddscaps.dwCaps = DDSCAPS_BACKBUFFER; lpDDSPrimary->GetAttachedSurface(&ddscaps,&lpDDSBack); for (i=192;i<256;i++) { // パレット作成 pePal[i].peRed=i; pePal[i].peGreen=i; pePal[i].peBlue=i; pePal[i].peFlags=NULL; } pePal[1].peRed=64; pePal[1].peGreen=32; pePal[1].peBlue=192; pePal[1].peFlags=NULL; pePal[2].peRed=0; pePal[2].peGreen=0; pePal[2].peBlue=0; pePal[2].peFlags=NULL; pePal[3].peRed=255; pePal[3].peGreen=0; pePal[3].peBlue=0; pePal[3].peFlags=NULL; lpDD->CreatePalette(DDPCAPS_8BIT,pePal,&lpDPalette,NULL); lpDPalette->SetEntries(0,0,256,pePal); lpDDSPrimary->SetPalette(lpDPalette); // パレット設定 srand((unsigned)time(NULL)); // 背景作成 lpBG=(LPBYTE)GlobalAlloc(GPTR,640*480); for (i=0;i<640*480;i++) lpBG[i]=rand() % 64+192; while (1) { /* メインループ */ if (PeekMessage (&msg,NULL,0,0,PM_NOREMOVE)) { if (!GetMessage (&msg,NULL,0,0)) // メッセージ処理 return msg.wParam ; TranslateMessage(&msg); DispatchMessage(&msg); } else draw(); // 描画処理 } } void draw(void) { // バックバッファに描画、フリップ RECT rec; HDC hdc; // カーソルキーで移動 if (GetAsyncKeyState(VK_UP)<0 && iY>0) iY--; if (GetAsyncKeyState(VK_RIGHT)<0 && iX+64<639) iX++; if (GetAsyncKeyState(VK_DOWN)<0 && iY+64<479) iY++; if (GetAsyncKeyState(VK_LEFT)<0 && iX>0) iX--; lpDDSBack->Lock(NULL,&ddsd,DDLOCK_WAIT,NULL); LPBYTE lpBuf=(BYTE*)ddsd.lpSurface; // 背景を転送 CopyMemory(lpBuf,lpBG,640*480); lpDDSBack->Unlock(NULL); lpDDSBack->GetDC(&hdc); SetTextColor(hdc,0x000000ff); SetBkMode(hdc,TRANSPARENT); rec.left=0; rec.top=64; rec.right=639; rec.bottom=128; DrawText(hdc,"DirectDraw サーフェス透過処理テスト",-1,&rec, DT_CENTER|DT_VCENTER); lpDDSBack->ReleaseDC(hdc); rec.left=0; rec.top=0; rec.right=63; rec.bottom=63; // スプライトを透過処理で転送 lpDDSBack->BltFast(iX,iY,lpDDSOff,&rec,DDBLTFAST_SRCCOLORKEY); lpDDSPrimary->Flip(NULL,DDFLIP_WAIT); } LRESULT CALLBACK WndProc (HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam) { switch (iMsg) { case WM_KEYDOWN: if (wParam==VK_ESCAPE) // エスケープキーが押されたら終了 PostMessage(hwnd,WM_CLOSE,0,0); break; case WM_DESTROY : // 終了処理 lpDD->RestoreDisplayMode(); // 画面モードを元に戻す if (lpDDSOff) // オフスクリーンサーフェス解放 lpDDSOff->Release(); if (lpDDSBack) // バックバッファ解放 lpDDSBack->Release(); if (lpDDSPrimary) // プライマリサーフェス解放 lpDDSPrimary->Release(); if (lpDD) // DirectDrawオブジェクト解放 lpDD->Release(); GlobalFree(lpBG); // 背景ビットマップのバッファ解放 PostQuitMessage(0); return 0; } return DefWindowProc (hwnd, iMsg, wParam, lParam) ; }