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 // ------------------------------------------------------------------
13 // Modified by Aleksey Bragin (aleksey at studiocerebral.com)
14 // to support non-uniform scaling, and output via sretchdibits
15 // (type something in the command line to invoke this mode,
16 // in future it will be source BPP)
18 //>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
21 //<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
26 const int ID_LISTBOX
= 101;
27 const int ID_LISTBOX2
= 102;
28 BOOL useDIBits
=FALSE
; // How to display the image - via StretchDIBits
33 const char* WndClassName
= "GMainWnd";
34 LRESULT CALLBACK
MainWndProc(HWND HWnd
, UINT Msg
, WPARAM WParam
,
38 int APIENTRY
WinMain(HINSTANCE HInstance
, HINSTANCE HPrevInstance
,
39 LPTSTR lpCmdLine
, int nCmdShow
)
42 HPrevInst
= HPrevInstance
;
46 memset(&wc
, 0, sizeof(WNDCLASS
));
48 wc
.style
= CS_VREDRAW
| CS_HREDRAW
| CS_DBLCLKS
;
49 wc
.lpfnWndProc
= MainWndProc
;
50 wc
.hInstance
= HInstance
;
51 wc
.hCursor
= LoadCursor(NULL
, IDC_ARROW
);
52 wc
.hbrBackground
= reinterpret_cast<HBRUSH
>(COLOR_BTNFACE
+ 1);
53 wc
.lpszClassName
= WndClassName
;
55 if (RegisterClass(&wc
))
58 CreateWindow(WndClassName
, TEXT("StretchBlt NonUniform Zooming Demo"),
59 WS_OVERLAPPEDWINDOW
| WS_CAPTION
|
60 WS_VISIBLE
| WS_CLIPSIBLINGS
,
62 NULL
, NULL
, HInst
, NULL
);
67 CreateWindowEx(WS_EX_CLIENTEDGE
, "LISTBOX", "",
68 LBS_NOTIFY
| WS_CHILD
| WS_VISIBLE
,
69 530, 5, 130, 150, HWnd
,
70 reinterpret_cast<HMENU
>(ID_LISTBOX
),
73 CreateWindowEx(WS_EX_CLIENTEDGE
, "LISTBOX", "",
74 LBS_NOTIFY
| WS_CHILD
| WS_VISIBLE
,
75 530, 5+170, 130, 150, HWnd
,
76 reinterpret_cast<HMENU
>(ID_LISTBOX2
),
79 if (HListBox
&& VListBox
)
82 SNDMSG(HListBox
, LB_ADDSTRING
, 0,
83 reinterpret_cast<LPARAM
>("Zoom 25%"));
84 SNDMSG(HListBox
, LB_ADDSTRING
, 0,
85 reinterpret_cast<LPARAM
>("Zoom 50%"));
86 SNDMSG(HListBox
, LB_ADDSTRING
, 0,
87 reinterpret_cast<LPARAM
>("Zoom 75%"));
88 SNDMSG(HListBox
, LB_ADDSTRING
, 0,
89 reinterpret_cast<LPARAM
>("Zoom 100%"));
90 SNDMSG(HListBox
, LB_ADDSTRING
, 0,
91 reinterpret_cast<LPARAM
>("Zoom 125%"));
92 SNDMSG(HListBox
, LB_ADDSTRING
, 0,
93 reinterpret_cast<LPARAM
>("Zoom 150%"));
94 SNDMSG(HListBox
, LB_ADDSTRING
, 0,
95 reinterpret_cast<LPARAM
>("Zoom 200%"));
96 SNDMSG(HListBox
, LB_ADDSTRING
, 0,
97 reinterpret_cast<LPARAM
>("Zoom 300%"));
99 SNDMSG(VListBox
, LB_ADDSTRING
, 0,
100 reinterpret_cast<LPARAM
>("Zoom 25%"));
101 SNDMSG(VListBox
, LB_ADDSTRING
, 0,
102 reinterpret_cast<LPARAM
>("Zoom 50%"));
103 SNDMSG(VListBox
, LB_ADDSTRING
, 0,
104 reinterpret_cast<LPARAM
>("Zoom 75%"));
105 SNDMSG(VListBox
, LB_ADDSTRING
, 0,
106 reinterpret_cast<LPARAM
>("Zoom 100%"));
107 SNDMSG(VListBox
, LB_ADDSTRING
, 0,
108 reinterpret_cast<LPARAM
>("Zoom 125%"));
109 SNDMSG(VListBox
, LB_ADDSTRING
, 0,
110 reinterpret_cast<LPARAM
>("Zoom 150%"));
111 SNDMSG(VListBox
, LB_ADDSTRING
, 0,
112 reinterpret_cast<LPARAM
>("Zoom 200%"));
113 SNDMSG(VListBox
, LB_ADDSTRING
, 0,
114 reinterpret_cast<LPARAM
>("Zoom 300%"));
118 ShowWindow(HWnd
, nCmdShow
);
122 while (GetMessage(&msg
, NULL
, 0, 0))
124 TranslateMessage(&msg
);
125 DispatchMessage(&msg
);
131 //------------------------------------------------------------------
137 char *bbits
= NULL
; // bitmap bits
138 const char* filename
= "LENA.BMP";
140 HBITMAP HOldBmp
= NULL
;
143 float zoom_factor_h
= 0.5;
144 float zoom_factor_v
= 0.5;
145 RECT RDest
= {5, 5, 0, 0};
146 enum {ID_ZOOM25
, ID_ZOOM50
, ID_ZOOM75
, ID_ZOOM100
,
147 ID_ZOOM125
, ID_ZOOM150
, ID_ZOOM200
, ID_ZOOM300
};
149 LRESULT CALLBACK
MainWndProc(HWND HWnd
, UINT Msg
, WPARAM WParam
,
157 if (strlen(cmdline
) != 0)
165 // create a memory DC
166 HMemDC
= CreateCompatibleDC(NULL
);
169 // load a bitmap from file
171 static_cast<HBITMAP
>(
172 LoadImage(HInst
, filename
, IMAGE_BITMAP
,
173 0, 0, LR_LOADFROMFILE
)
177 // extract dimensions of the bitmap
178 GetObject(HBmp
, sizeof(BITMAP
), &bmp
);
180 // fill the BITMAPINFO stucture for further use by StretchDIBits
181 bmInfo
.bmiHeader
.biSize
= sizeof(BITMAPINFOHEADER
);
182 bmInfo
.bmiHeader
.biWidth
= bmp
.bmWidth
;
183 bmInfo
.bmiHeader
.biHeight
= bmp
.bmHeight
;
184 bmInfo
.bmiHeader
.biPlanes
= 1;//bmp.bmPlanes;
185 bmInfo
.bmiHeader
.biBitCount
= bmp
.bmBitsPixel
;
186 bmInfo
.bmiHeader
.biCompression
= BI_RGB
;
187 bmInfo
.bmiHeader
.biSizeImage
= 0;
188 bmInfo
.bmiHeader
.biXPelsPerMeter
= 0;
189 bmInfo
.bmiHeader
.biClrImportant
= 0;
190 bmInfo
.bmiHeader
.biClrUsed
= 0;
192 // associate the bitmap with the memory DC
193 HOldBmp
= static_cast<HBITMAP
>(
194 SelectObject(HMemDC
, HBmp
)
199 bbits
= new char[bmp
.bmHeight
*bmp
.bmWidthBytes
*(bmp
.bmBitsPixel
/ 8)];
200 //GetDIBits(HMemDC, HBmp, 0, bmp.bmHeight, bbits, &bmInfo, DIB_RGB_COLORS);
202 // Here goes a temp hack, since GetDIBits doesn't exist in ReactOS yet
203 FILE *f
= fopen(filename
, "rb");
204 BITMAPFILEHEADER bmpHeader
;
206 fread(&bmpHeader
, sizeof(BITMAPFILEHEADER
), 1, f
);
207 fread(&bmInfo
, sizeof(BITMAPINFO
), 1, f
);
208 fseek(f
, bmpHeader
.bfOffBits
, SEEK_SET
);
209 fread(bbits
, bmp
.bmHeight
*bmp
.bmWidthBytes
*(bmp
.bmBitsPixel
/ 8), 1, f
);
218 if (WParam
== MAKEWPARAM(ID_LISTBOX
, LBN_SELCHANGE
) ||
219 WParam
== MAKEWPARAM(ID_LISTBOX2
, LBN_SELCHANGE
))
221 switch (SNDMSG(HListBox
, LB_GETCURSEL
, 0, 0))
223 case ID_ZOOM25
: zoom_factor_h
= 0.25; break;
224 case ID_ZOOM50
: zoom_factor_h
= 0.50; break;
225 case ID_ZOOM75
: zoom_factor_h
= 0.75; break;
226 case ID_ZOOM100
: zoom_factor_h
= 1.00; break;
227 case ID_ZOOM125
: zoom_factor_h
= 1.25; break;
228 case ID_ZOOM150
: zoom_factor_h
= 1.50; break;
229 case ID_ZOOM200
: zoom_factor_h
= 2.00; break;
230 case ID_ZOOM300
: zoom_factor_h
= 3.00; break;
233 switch (SNDMSG(VListBox
, LB_GETCURSEL
, 0, 0))
235 case ID_ZOOM25
: zoom_factor_v
= 0.25; break;
236 case ID_ZOOM50
: zoom_factor_v
= 0.50; break;
237 case ID_ZOOM75
: zoom_factor_v
= 0.75; break;
238 case ID_ZOOM100
: zoom_factor_v
= 1.00; break;
239 case ID_ZOOM125
: zoom_factor_v
= 1.25; break;
240 case ID_ZOOM150
: zoom_factor_v
= 1.50; break;
241 case ID_ZOOM200
: zoom_factor_v
= 2.00; break;
242 case ID_ZOOM300
: zoom_factor_v
= 3.00; break;
245 // calculate the new width and height
246 const int new_width
=
247 static_cast<int>(zoom_factor_h
* bmp
.bmWidth
);
248 const int new_height
=
249 static_cast<int>(zoom_factor_v
* bmp
.bmHeight
);
252 bool zoom_in
= (new_width
> RDest
.right
- RDest
.left
);
254 // caculate the area that needs to be updated
256 RDest
.left
, RDest
.top
,
257 RDest
.left
+ max(new_width
, RDest
.right
- RDest
.left
),
258 RDest
.top
+ max(new_height
, RDest
.bottom
- RDest
.top
)
261 // adjust the dimenstions of the
262 // destination rectangle
263 RDest
.right
= RDest
.left
+ new_width
;
264 RDest
.bottom
= RDest
.top
+ new_height
;
266 // create an update region from the XOR combination
267 // of the update and destination rectangles
268 HRGN HUpdateRgn
= CreateRectRgnIndirect(&RUpdate
);
269 HRGN HDestRgn
= CreateRectRgnIndirect(&RDest
);
271 CombineRgn(HUpdateRgn
, HUpdateRgn
, HDestRgn
, RGN_XOR
);
274 if (result
!= NULLREGION
&& result
!= ERROR
)
276 InvalidateRgn(HWnd
, HUpdateRgn
, true);
277 RedrawWindow(HWnd
, &RDest
, NULL
, RDW_NOERASE
| RDW_INVALIDATE
);
279 else if (result
== NULLREGION
)
281 InvalidateRect(HWnd
, &RUpdate
, zoom_in
? false : true);
285 DeleteObject(HUpdateRgn
);
286 DeleteObject(HDestRgn
);
293 const HDC Hdc
= BeginPaint(HWnd
, &ps
);
299 // TODO: add palette support (see Chapter 9)...
303 if (RDest
.right
- RDest
.left
> 0)
305 if (zoom_factor_h
< 1.0 || zoom_factor_v
< 1.0)
307 SetStretchBltMode(Hdc
, COLORONCOLOR
);
310 // render the zoomed image
311 StretchDIBits(Hdc
, RDest
.left
, RDest
.top
,
312 RDest
.right
- RDest
.left
,
313 RDest
.bottom
- RDest
.top
,
315 bmp
.bmWidth
, bmp
.bmHeight
,
323 if (RDest
.right
- RDest
.left
> 0)
326 // use BitBlt when not zooming
327 if (zoom_factor_h
== 1.0 && zoom_factor_v
== 1.0)
329 BitBlt(Hdc
, RDest
.left
, RDest
.top
,
330 RDest
.right
- RDest
.left
,
331 RDest
.bottom
- RDest
.top
,
337 if (zoom_factor_h
< 1.0 || zoom_factor_v
< 1.0)
339 SetStretchBltMode(Hdc
, COLORONCOLOR
);
342 // render the zoomed image
343 StretchBlt(Hdc
, RDest
.left
, RDest
.top
,
344 RDest
.right
- RDest
.left
,
345 RDest
.bottom
- RDest
.top
,
347 bmp
.bmWidth
, bmp
.bmHeight
,
365 DeleteObject(SelectObject(HMemDC
, HOldBmp
));
375 return DefWindowProc(HWnd
, Msg
, WParam
, LParam
);
377 //------------------------------------------------------------------