update for HEAD-2003091401
[reactos.git] / apps / tests / patblt / patblt.cpp
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 //------------------------------------------------------------------