2 // ------------------------------------------------------------------
3 // Windows 2000 Graphics API Black Book
4 // Chapter 1 - Listing 1.5 (StretchBlt Zooming Demo)
6 // Created by Damon Chandler <dmc27@ee.cornell.edu>
7 // Updates can be downloaded at: <www.coriolis.com>
9 // Please do not hesistate to e-mail me at dmc27@ee.cornell.edu
10 // if you have any questions about this code.
11 // ------------------------------------------------------------------
14 //>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
16 //<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
20 const int ID_LISTBOX = 101;
23 const char* WndClassName = "GMainWnd";
24 LRESULT CALLBACK MainWndProc(HWND HWnd, UINT Msg, WPARAM WParam,
28 int APIENTRY WinMain(HINSTANCE HInstance, HINSTANCE HPrevInstance,
29 LPTSTR lpCmdLine, int nCmdShow)
34 memset(&wc, 0, sizeof(WNDCLASS));
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;
43 if (RegisterClass(&wc))
46 CreateWindow(WndClassName, TEXT("StretchBlt Zooming Demo"),
47 WS_OVERLAPPEDWINDOW | WS_CAPTION |
48 WS_VISIBLE | WS_CLIPSIBLINGS,
50 NULL, NULL, HInst, NULL);
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),
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%"));
80 ShowWindow(HWnd, nCmdShow);
84 while (GetMessage(&msg, NULL, 0, 0))
86 TranslateMessage(&msg);
87 DispatchMessage(&msg);
93 //------------------------------------------------------------------
98 const char* filename = "LENA.BMP";
100 HBITMAP HOldBmp = NULL;
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};
108 LRESULT CALLBACK MainWndProc(HWND HWnd, UINT Msg, WPARAM WParam,
115 // create a memory DC
116 HMemDC = CreateCompatibleDC(NULL);
119 // load a bitmap from file
121 static_cast<HBITMAP>(
122 LoadImage(HInst, filename, IMAGE_BITMAP,
123 0, 0, LR_LOADFROMFILE)
127 // extract dimensions of the bitmap
128 GetObject(HBmp, sizeof(BITMAP), &bmp);
130 // associate the bitmap with the memory DC
131 HOldBmp = static_cast<HBITMAP>(
132 SelectObject(HMemDC, HBmp)
139 if (WParam == MAKEWPARAM(ID_LISTBOX, LBN_SELCHANGE))
141 switch (SNDMSG(HListBox, LB_GETCURSEL, 0, 0))
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;
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);
160 bool zoom_in = (new_width > RDest.right - RDest.left);
162 // caculate the area that needs to be updated
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)
169 // adjust the dimenstions of the
170 // destination rectangle
171 RDest.right = RDest.left + new_width;
172 RDest.bottom = RDest.top + new_height;
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);
179 CombineRgn(HUpdateRgn, HUpdateRgn, HDestRgn, RGN_XOR);
182 if (result != NULLREGION && result != ERROR)
184 InvalidateRgn(HWnd, HUpdateRgn, true);
185 RedrawWindow(HWnd, &RDest, NULL, RDW_NOERASE | RDW_INVALIDATE);
187 else if (result == NULLREGION)
189 InvalidateRect(HWnd, &RUpdate, zoom_in ? false : true);
193 DeleteObject(HUpdateRgn);
194 DeleteObject(HDestRgn);
201 const HDC Hdc = BeginPaint(HWnd, &ps);
207 // TODO: add palette support (see Chapter 9)...
210 if (RDest.right - RDest.left > 0)
212 // use BitBlt when not zooming
213 if (zoom_factor == 1.0)
215 BitBlt(Hdc, RDest.left, RDest.top,
216 RDest.right - RDest.left,
217 RDest.bottom - RDest.top,
223 if (zoom_factor < 1.0)
225 SetStretchBltMode(Hdc, COLORONCOLOR);
228 // render the zoomed image
229 StretchBlt(Hdc, RDest.left, RDest.top,
230 RDest.right - RDest.left,
231 RDest.bottom - RDest.top,
233 bmp.bmWidth, bmp.bmHeight,
250 DeleteObject(SelectObject(HMemDC, HOldBmp));
257 return DefWindowProc(HWnd, Msg, WParam, LParam);
259 //------------------------------------------------------------------