1 2 // ------------------------------------------------------------------ 3 // Windows 2000 Graphics API Black Book 4 // Chapter 2 - Listing 2.1 (PatBlt Tracking Rect Demo) 5 // 6 // Created by Damon Chandler <dmc27@ee.cornell.edu> 7 // Updates can be downloaded at: <www.coriolis.com> 8 // 9 // Please do not hesistate to e-mail me at dmc27@ee.cornell.edu 10 // if you have any questions about this code. 11 // ------------------------------------------------------------------ 12 13 14 //>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 15 #include <windows.h> 16 //<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< 17 18 19 HINSTANCE HInst; 20 const char* WndClassName = "GMainWnd"; 21 LRESULT CALLBACK MainWndProc(HWND HWnd, UINT Msg, WPARAM WParam, 22 LPARAM LParam); 23 24 25 int APIENTRY WinMain(HINSTANCE HInstance, HINSTANCE, LPTSTR, 26 int nCmdShow) 27 { 28 HInst = HInstance; 29 30 WNDCLASS wc; 31 memset(&wc, 0, sizeof(WNDCLASS)); 32 33 wc.style = CS_VREDRAW | CS_HREDRAW; 34 wc.lpszClassName = WndClassName; 35 wc.lpfnWndProc = MainWndProc; 36 wc.hInstance = HInstance; 37 wc.hCursor = LoadCursor(NULL, IDC_ARROW); 38 wc.hbrBackground = static_cast<HBRUSH>( 39 GetStockObject(BLACK_BRUSH) 40 ); 41 42 if (RegisterClass(&wc)) 43 { 44 HWND HWnd = 45 CreateWindow(WndClassName, 46 TEXT("PatBlt Tracking Rect Demo"), 47 WS_OVERLAPPEDWINDOW | WS_CAPTION | 48 WS_VISIBLE | WS_CLIPCHILDREN, 49 CW_USEDEFAULT, CW_USEDEFAULT, 640, 480, 50 NULL, NULL, HInst, NULL); 51 52 if (HWnd) 53 { 54 ShowWindow(HWnd, nCmdShow); 55 UpdateWindow(HWnd); 56 57 MSG msg; 58 while (GetMessage(&msg, NULL, 0, 0)) 59 { 60 TranslateMessage(&msg); 61 DispatchMessage(&msg); 62 } 63 } 64 } 65 return 0; 66 } 67 //------------------------------------------------------------------ 68 69 70 // image related 71 HDC HMemDC = NULL; 72 HBITMAP HOldBmp = NULL; 73 const char* filename = "PENGUIN.BMP"; 74 RECT RImage = {225, 110, 225, 110}; 75 76 // tracking related 77 bool is_tracking = false; 78 HDC HScreenDC = NULL; 79 POINT PMouse = {0, 0}; 80 RECT RTrack = {0, 0, 0, 0}; 81 const int line_width = 5; 82 83 84 // utility function to map to/from window coordinates 85 void MapRect(IN HWND HWndFrom, IN HWND HWndTo, IN OUT RECT& RMap) 86 { 87 MapWindowPoints( 88 HWndFrom, HWndTo, 89 reinterpret_cast<LPPOINT>(&RMap), 2 90 ); 91 } 92 //------------------------------------------------------------------ 93 94 95 // utility function that uses the PatBlt function to 96 // render a tracking rectangle 97 void RenderTrackingRect(IN HDC HDestDC, IN const RECT& RRender) 98 { 99 const int width = RRender.right - RRender.left; 100 const int height = RRender.bottom - RRender.top; 101 const DWORD dwROP3 = DSTINVERT; // experiment with others 102 103 // render top bar 104 PatBlt(HDestDC, 105 RRender.left, RRender.top, 106 width, line_width, 107 dwROP3); 108 // render bottom bar 109 PatBlt(HDestDC, 110 RRender.left, RRender.bottom - line_width, 111 width, line_width, 112 dwROP3); 113 // render left bar 114 PatBlt(HDestDC, 115 RRender.left, RRender.top + line_width, 116 line_width, height - (2 * line_width), 117 dwROP3); 118 // render right bar 119 PatBlt(HDestDC, 120 RRender.right - line_width, RRender.top + line_width, 121 line_width, height - (2 * line_width), 122 dwROP3); 123 124 } 125 //------------------------------------------------------------------ 126 127 128 LRESULT CALLBACK MainWndProc(HWND HWnd, UINT Msg, WPARAM WParam, 129 LPARAM LParam) 130 { 131 switch (Msg) 132 { 133 case WM_CREATE: 134 { 135 // create a memory DC 136 HMemDC = CreateCompatibleDC(NULL); 137 if (HMemDC) 138 { 139 // load the penguin bitmap 140 HBITMAP HBmp = static_cast<HBITMAP>( 141 LoadImage(HInst, filename, IMAGE_BITMAP, 0, 0, 142 LR_LOADFROMFILE | LR_DEFAULTSIZE) 143 ); 144 if (HBmp) 145 { 146 // get the bitmap's dimensions 147 BITMAP bmp; 148 if (GetObject(HBmp, sizeof(BITMAP), &bmp)) 149 { 150 RImage.right += bmp.bmWidth; 151 RImage.bottom += bmp.bmHeight; 152 153 // realize the bitmap 154 HOldBmp = static_cast<HBITMAP>( 155 SelectObject(HMemDC, HBmp) 156 ); 157 } 158 else DeleteObject(HBmp); 159 } 160 } 161 break; 162 } 163 case WM_LBUTTONDOWN: 164 { 165 PMouse.x = LOWORD(LParam); 166 PMouse.y = HIWORD(LParam); 167 168 RECT RClient; 169 if (PtInRect(&RImage, PMouse) && 170 GetClientRect(HWnd, &RClient)) 171 { 172 MapRect(HWnd, HWND_DESKTOP, RClient); 173 ClipCursor(&RClient); 174 175 // grab a handle to the screen DC and clip 176 // all output to the client area of our window 177 HScreenDC = GetDC(NULL); 178 HRGN HClipRgn = CreateRectRgnIndirect(&RClient); 179 SelectClipRgn(HScreenDC, HClipRgn); 180 DeleteObject(HClipRgn); 181 182 CopyRect(&RTrack, &RImage); 183 MapRect(HWnd, HWND_DESKTOP, RTrack); 184 185 // render the first tracking rect 186 RenderTrackingRect(HScreenDC, RTrack); 187 is_tracking = true; 188 } 189 break; 190 } 191 case WM_MOUSEMOVE: 192 { 193 if (HScreenDC && is_tracking) 194 { 195 POINT PCurrent = {LOWORD(LParam), HIWORD(LParam)}; 196 const int dX = PCurrent.x - PMouse.x; 197 const int dY = PCurrent.y - PMouse.y; 198 199 // erase the previous rectangle 200 RenderTrackingRect(HScreenDC, RTrack); 201 // update the postion 202 OffsetRect(&RTrack, dX, dY); 203 // render the new tracking rectangle 204 RenderTrackingRect(HScreenDC, RTrack); 205 206 // update the mouse position 207 memcpy(&PMouse, &PCurrent, sizeof(POINT)); 208 } 209 break; 210 } 211 case WM_LBUTTONUP: 212 { 213 // clean up 214 if (is_tracking) 215 { 216 is_tracking = false; 217 SelectClipRgn(HScreenDC, NULL); 218 ReleaseDC(NULL, HScreenDC); 219 220 InvalidateRect(HWnd, &RImage, true); 221 CopyRect(&RImage, &RTrack); 222 MapRect(HWND_DESKTOP, HWnd, RImage); 223 InvalidateRect(HWnd, &RImage, true); 224 225 ClipCursor(NULL); 226 } 227 break; 228 } 229 case WM_PAINT: 230 { 231 PAINTSTRUCT ps; 232 HDC Hdc = BeginPaint(HWnd, &ps); 233 try 234 { 235 // 236 // TODO: Add palette support... 237 // 238 239 // render the penguin 240 BitBlt(Hdc, RImage.left, RImage.top, 241 RImage.right - RImage.left, 242 RImage.bottom - RImage.top, 243 HMemDC, 0, 0, 244 SRCCOPY); 245 } 246 catch (...) 247 { 248 EndPaint(HWnd, &ps); 249 } 250 EndPaint(HWnd, &ps); 251 break; 252 } 253 case WM_DESTROY: 254 { 255 // clean up 256 if (HOldBmp) 257 { 258 DeleteObject(SelectObject(HMemDC, HOldBmp)); 259 } 260 if (HMemDC) 261 { 262 DeleteDC(HMemDC); 263 } 264 PostQuitMessage(0); 265 return 0; 266 } 267 } 268 return DefWindowProc(HWnd, Msg, WParam, LParam); 269 } 270 //------------------------------------------------------------------ 271