update for HEAD-2003021201
[reactos.git] / apps / tests / stretchblt / stretchblt.cpp
1
2 // ------------------------------------------------------------------
3 // Windows 2000 Graphics API Black Book
4 // Chapter 1 - Listing 1.5 (StretchBlt Zooming 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 HWND HListBox = NULL;
20 const int ID_LISTBOX = 101;
21
22 HINSTANCE HInst;
23 const char* WndClassName = "GMainWnd";
24 LRESULT CALLBACK MainWndProc(HWND HWnd, UINT Msg, WPARAM WParam, 
25    LPARAM LParam);
26
27
28 int APIENTRY WinMain(HINSTANCE HInstance, HINSTANCE HPrevInstance,
29     LPTSTR lpCmdLine, int nCmdShow)
30 {
31    HInst = HInstance;
32
33    WNDCLASS wc;
34    memset(&wc, 0, sizeof(WNDCLASS));
35     
36    wc.style = CS_VREDRAW | CS_HREDRAW | CS_DBLCLKS;
37    wc.lpfnWndProc = MainWndProc;
38    wc.hInstance = HInstance;
39    wc.hCursor = LoadCursor(NULL, IDC_ARROW);
40    wc.hbrBackground = reinterpret_cast<HBRUSH>(COLOR_BTNFACE + 1);
41    wc.lpszClassName = WndClassName;
42
43    if (RegisterClass(&wc))
44    {
45       HWND HWnd = 
46          CreateWindow(WndClassName, TEXT("StretchBlt Zooming Demo"),
47                       WS_OVERLAPPEDWINDOW | WS_CAPTION | 
48                       WS_VISIBLE | WS_CLIPSIBLINGS,
49                       0, 0, 675, 560,
50                       NULL, NULL, HInst, NULL);
51                                  
52       if (HWnd)
53       {
54          HListBox =
55             CreateWindowEx(WS_EX_CLIENTEDGE, "LISTBOX", "", 
56                            LBS_NOTIFY | WS_CHILD | WS_VISIBLE, 
57                            530, 5, 130, 150, HWnd, 
58                            reinterpret_cast<HMENU>(ID_LISTBOX),
59                            HInst, NULL);
60          if (HListBox)
61          {
62             SNDMSG(HListBox, LB_ADDSTRING, 0, 
63                    reinterpret_cast<LPARAM>("Zoom 25%"));
64             SNDMSG(HListBox, LB_ADDSTRING, 0, 
65                    reinterpret_cast<LPARAM>("Zoom 50%"));
66             SNDMSG(HListBox, LB_ADDSTRING, 0, 
67                    reinterpret_cast<LPARAM>("Zoom 75%"));
68             SNDMSG(HListBox, LB_ADDSTRING, 0, 
69                    reinterpret_cast<LPARAM>("Zoom 100%"));
70             SNDMSG(HListBox, LB_ADDSTRING, 0, 
71                    reinterpret_cast<LPARAM>("Zoom 125%"));
72             SNDMSG(HListBox, LB_ADDSTRING, 0, 
73                    reinterpret_cast<LPARAM>("Zoom 150%"));
74             SNDMSG(HListBox, LB_ADDSTRING, 0, 
75                    reinterpret_cast<LPARAM>("Zoom 200%"));
76             SNDMSG(HListBox, LB_ADDSTRING, 0, 
77                    reinterpret_cast<LPARAM>("Zoom 300%"));
78          }
79
80          ShowWindow(HWnd, nCmdShow);
81          UpdateWindow(HWnd);
82
83          MSG msg;
84          while (GetMessage(&msg, NULL, 0, 0))
85          {
86              TranslateMessage(&msg);
87              DispatchMessage(&msg);
88          }      
89       }
90     }
91     return 0;
92 }
93 //------------------------------------------------------------------
94
95
96 // image related
97 BITMAP bmp;
98 const char* filename = "LENA.BMP";
99 HDC HMemDC = NULL;
100 HBITMAP HOldBmp = NULL;
101
102 // zooming related
103 float zoom_factor = 0.5;
104 RECT RDest = {5, 5, 0, 0};
105 enum {ID_ZOOM25, ID_ZOOM50, ID_ZOOM75, ID_ZOOM100, 
106       ID_ZOOM125, ID_ZOOM150, ID_ZOOM200, ID_ZOOM300};
107
108 LRESULT CALLBACK MainWndProc(HWND HWnd, UINT Msg, WPARAM WParam, 
109    LPARAM LParam)
110 {
111    switch (Msg)
112    {
113       case WM_CREATE:
114       {         
115          // create a memory DC
116          HMemDC = CreateCompatibleDC(NULL);
117          if (HMemDC)
118          {
119             // load a bitmap from file
120             HBITMAP HBmp = 
121                static_cast<HBITMAP>(
122                   LoadImage(HInst, filename, IMAGE_BITMAP, 
123                             0, 0, LR_LOADFROMFILE)
124                             );  
125             if (HBmp)
126             { 
127                // extract dimensions of the bitmap
128                GetObject(HBmp, sizeof(BITMAP), &bmp);
129
130                // associate the bitmap with the memory DC
131                HOldBmp = static_cast<HBITMAP>(
132                   SelectObject(HMemDC, HBmp)
133                   );
134             }
135          }         
136       }
137       case WM_COMMAND:
138       {
139          if (WParam == MAKEWPARAM(ID_LISTBOX, LBN_SELCHANGE))
140          {
141             switch (SNDMSG(HListBox, LB_GETCURSEL, 0, 0))
142             {
143                case ID_ZOOM25: zoom_factor = 0.25; break;
144                case ID_ZOOM50: zoom_factor = 0.50; break;
145                case ID_ZOOM75: zoom_factor = 0.75; break;
146                case ID_ZOOM100: zoom_factor = 1.00; break;
147                case ID_ZOOM125: zoom_factor = 1.25; break;
148                case ID_ZOOM150: zoom_factor = 1.50; break;
149                case ID_ZOOM200: zoom_factor = 2.00; break;
150                case ID_ZOOM300: zoom_factor = 3.00; break;
151             }
152
153             // calculate the new width and height
154             const int new_width = 
155                static_cast<int>(zoom_factor * bmp.bmWidth);
156             const int new_height = 
157                static_cast<int>(zoom_factor * bmp.bmHeight);
158
159             // is zooming in?
160             bool zoom_in = (new_width > RDest.right - RDest.left);
161
162             // caculate the area that needs to be updated 
163             RECT RUpdate = {
164                RDest.left, RDest.top,
165                RDest.left + max(new_width, RDest.right - RDest.left),
166                RDest.top + max(new_height, RDest.bottom - RDest.top)
167                };
168
169             // adjust the dimenstions of the
170             // destination rectangle
171             RDest.right = RDest.left + new_width;               
172             RDest.bottom = RDest.top + new_height;            
173
174             // create an update region from the XOR combination
175             // of the update and destination rectangles
176             HRGN HUpdateRgn = CreateRectRgnIndirect(&RUpdate);
177             HRGN HDestRgn = CreateRectRgnIndirect(&RDest);
178             int result = 
179                CombineRgn(HUpdateRgn, HUpdateRgn, HDestRgn, RGN_XOR);
180
181             // incite a repaint
182             if (result != NULLREGION && result != ERROR)
183             {              
184                InvalidateRgn(HWnd, HUpdateRgn, true);               
185                RedrawWindow(HWnd, &RDest, NULL, RDW_NOERASE | RDW_INVALIDATE);
186             }
187             else if (result == NULLREGION)
188             {
189                InvalidateRect(HWnd, &RUpdate, zoom_in ? false : true);
190             }
191
192             // clean up
193             DeleteObject(HUpdateRgn);
194             DeleteObject(HDestRgn);
195          }
196          break;
197       }
198       case WM_PAINT:
199       {
200          PAINTSTRUCT ps;
201          const HDC Hdc = BeginPaint(HWnd, &ps);
202 #if 0
203          try
204 #endif
205          {
206             //
207             // TODO: add palette support (see Chapter 9)...
208             //
209
210             if (RDest.right - RDest.left > 0)
211             {
212                // use BitBlt when not zooming
213                if (zoom_factor == 1.0)
214                {
215                   BitBlt(Hdc, RDest.left, RDest.top, 
216                          RDest.right - RDest.left, 
217                          RDest.bottom - RDest.top,
218                          HMemDC, 0, 0, 
219                          SRCCOPY);  
220                }
221                else
222                {
223                   if (zoom_factor < 1.0)
224                   {
225                      SetStretchBltMode(Hdc, COLORONCOLOR);
226                   }
227
228                   // render the zoomed image
229                   StretchBlt(Hdc, RDest.left, RDest.top, 
230                              RDest.right - RDest.left, 
231                              RDest.bottom - RDest.top,
232                              HMemDC, 0, 0, 
233                              bmp.bmWidth, bmp.bmHeight,
234                              SRCCOPY);  
235                }
236             }
237          }
238 #if 0           
239          catch (...)
240 #endif
241          {
242             EndPaint(HWnd, &ps);
243          }
244          EndPaint(HWnd, &ps);
245          break;
246       }
247       case WM_DESTROY:
248       {
249          // clean up
250          DeleteObject(SelectObject(HMemDC, HOldBmp));
251          DeleteDC(HMemDC);
252
253          PostQuitMessage(0);
254          return 0;
255       }
256    }
257    return DefWindowProc(HWnd, Msg, WParam, LParam);
258 }
259 //------------------------------------------------------------------
260
261
262