DirectDraw创建Windows窗口
KDDrawWindow.cpp
1 #define STRICT 2 #define WIN32_LEAN_AND_MEAN 3 4 #include <windows.h> 5 #include <assert.h> 6 #include <tchar.h> 7 #include <ddraw.h> 8 9 #include "KWindow.h" 10 #pragma comment(lib,"ddraw") 11 12 const TCHAR szMessage[] = _T("Hello World!"); 13 const TCHAR szFace[] = _T("Times New Roman"); 14 const TCHAR szHint[] = _T("press ESC to quit."); 15 const TCHAR szProgram[] = _T("HelloWorld4"); 16 17 class KDDrawWindow : public KWindow 18 { 19 LPDIRECTDRAW lpdd; 20 LPDIRECTDRAWSURFACE lpddsprimary; 21 22 void OnKeyDown(WPARAM wParam, LPARAM lParam) 23 { 24 if(wParam == VK_ESCAPE) 25 { 26 PostMessage(m_hWnd, WM_CLOSE, 0, 0); 27 } 28 } 29 30 void Blend(int left, int right, int top, int bottom); 31 32 void OnDraw(HDC hdc) 33 { 34 TextOut(hdc, 0, 0, szHint, lstrlen(szHint)); 35 CenterText(hdc, GetSystemMetrics(SM_CXSCREEN) / 2, 36 GetSystemMetrics(SM_CYSCREEN) / 2, 37 szFace, szMessage, 48); 38 Blend(80, 560, 160, 250); 39 } 40 41 public: 42 KDDrawWindow() 43 { 44 lpdd = NULL; 45 lpddsprimary = NULL; 46 } 47 48 ~KDDrawWindow() 49 { 50 if(lpddsprimary) 51 { 52 lpddsprimary->Release(); 53 lpddsprimary = NULL; 54 } 55 56 if(lpdd) 57 { 58 lpdd->Release(); 59 lpdd = NULL; 60 } 61 } 62 63 bool CreateSurface(); 64 }; 65 66 bool KDDrawWindow::CreateSurface() 67 { 68 HRESULT hr; 69 hr = DirectDrawCreate(NULL, &lpdd, NULL); 70 if(hr != DD_OK) 71 return false; 72 73 hr = lpdd->SetCooperativeLevel(m_hWnd, DDSCL_FULLSCREEN | DDSCL_EXCLUSIVE); 74 if(hr != DD_OK) 75 return false; 76 77 hr = lpdd->SetDisplayMode(640, 480, 32); 78 if(hr != DD_OK) 79 return false; 80 81 DDSURFACEDESC ddsd; 82 memset(&ddsd, 0, sizeof(ddsd)); 83 ddsd.dwSize = sizeof(ddsd); 84 ddsd.dwFlags = DDSD_CAPS; 85 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE; 86 87 return lpdd->CreateSurface(&ddsd, &lpddsprimary, NULL) == DD_OK; 88 } 89 90 void inline Blend(unsigned char* dest, unsigned char* src) 91 { 92 if(!dest || !src) 93 return; 94 95 dest[0] = (dest[0] + src[0]) / 2; 96 dest[1] = (dest[1] + src[1]) / 2; 97 dest[2] = (dest[2] + src[2]) / 2; 98 } 99 100 void KDDrawWindow::Blend(int left, int right, int top, int bottom) 101 { 102 DDSURFACEDESC ddsd; 103 memset(&ddsd, 0, sizeof(ddsd)); 104 ddsd.dwSize = sizeof(ddsd); 105 106 HRESULT hr = lpddsprimary->Lock(NULL, &ddsd, DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT, NULL); 107 assert(hr == DD_OK); 108 109 unsigned char* screen = (unsigned char*)ddsd.lpSurface; 110 111 for(int y = top; y < bottom; ++y) 112 { 113 unsigned char* pixel = screen + y * ddsd.lPitch + left * 4; 114 for(int x = left; x < right; ++x, pixel += 4) 115 { 116 if(pixel[0] != 255 || pixel[1] != 255 || pixel[2] != 255) 117 { 118 ::Blend(pixel - 4, pixel); //left 119 ::Blend(pixel + 4, pixel); //right 120 ::Blend(pixel - ddsd.lPitch, pixel); //up 121 ::Blend(pixel + ddsd.lPitch, pixel); //down 122 } 123 } 124 } 125 126 lpddsprimary->Unlock(ddsd.lpSurface); 127 } 128 129 int WINAPI WinMain( _In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPSTR lpCmdLine, _In_ int nShowCmd ) 130 { 131 KDDrawWindow win; 132 win.CreateEx(0, szProgram, szProgram, WS_POPUP, GetSystemMetrics(SM_CXSCREEN) / 4, GetSystemMetrics(SM_CXSCREEN) / 4, 133 GetSystemMetrics(SM_CXSCREEN) / 2, GetSystemMetrics(SM_CYSCREEN) / 2, 134 NULL, NULL, hInstance); 135 136 win.CreateSurface(); 137 win.ShowWindow(nShowCmd); 138 win.UpdateWindow(); 139 140 return win.MessageLoop(); 141 }