承接前三篇,本文呈現完整的 main.cpp 實作碼,示範 DirectDraw 物件建立、協作等級設定、顯示模式切換、主/離螢幕圖面建立、位圖載入與 BitBlt 複製、圖面遺失與恢復全流程。
// 關鍵介面指標
LPDIRECTDRAW lpDD;
LPDIRECTDRAW2 lpDD2;
LPDIRECTDRAWSURFACE lpDDPrimary; // 主圖面
LPDIRECTDRAWSURFACE lpDDOffScreen; // 離螢幕圖面
DDSURFACEDESC ddsd;
DirectDrawCreate(NULL, &lpDD, NULL);
lpDD->QueryInterface(IID_IDirectDraw2, (LPVOID*)&lpDD2);
lpDD->Release(); // 釋放舊介面
lpDD2->SetCooperativeLevel(Handle,
DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN | DDSCL_NOWINDOWCHANGES);
lpDD2->SetDisplayMode(800, 600, 16, 0, 0);
ZeroMemory(&ddsd, sizeof(ddsd));
ddsd.dwSize = sizeof(ddsd);
ddsd.dwFlags = DDSD_CAPS;
ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
lpDD2->CreateSurface(&ddsd, &lpDDPrimary, NULL);
ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH;
ddsd.dwHeight = 100; ddsd.dwWidth = 100;
ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
lpDD2->CreateSurface(&ddsd, &lpDDOffScreen, NULL);
HDC hdc, hdcImage;
HBITMAP hbm = (HBITMAP)LoadImage(NULL, "view.bmp", IMAGE_BITMAP,
100, 100, LR_LOADFROMFILE | LR_CREATEDIBSECTION);
hdcImage = CreateCompatibleDC(NULL);
SelectObject(hdcImage, hbm);
lpDDOffScreen->GetDC(&hdc);
BitBlt(hdc, 0, 0, 100, 100, hdcImage, 0, 0, SRCCOPY);
lpDDOffScreen->ReleaseDC(hdc);
// 清理 GDI 物件
DeleteDC(hdcImage); DeleteObject(hbm);
HDC hdcPrimary, hdcOffScreen;
lpDDPrimary->GetDC(&hdcPrimary);
lpDDOffScreen->GetDC(&hdcOffScreen);
BitBlt(hdcPrimary, 200, 0, 100, 100, hdcOffScreen, 0, 0, SRCCOPY);
lpDDPrimary->ReleaseDC(hdcPrimary);
lpDDOffScreen->ReleaseDC(hdcOffScreen);
// 切換解析度導致圖面遺失
lpDD2->SetDisplayMode(640, 480, 16, 0, 0);
// 恢復解析度並還原圖面
lpDD2->SetDisplayMode(800, 600, 16, 0, 0);
lpDDPrimary->Restore();
lpDDOffScreen->Restore();
// 重新載入圖形資料
範例以 9 個按鈕串聯完整流程:
GetDC/ReleaseDC 必須成對呼叫,否則會鎖定圖面。Restore 才會成功。