diff --git a/reactos/apps/tests/bitblt/bitblt.cpp b/reactos/apps/tests/bitblt/bitblt.cpp new file mode 100644 index 00000000000..f49bfb791fb --- /dev/null +++ b/reactos/apps/tests/bitblt/bitblt.cpp @@ -0,0 +1,138 @@ + +// ------------------------------------------------------------------ +// Windows 2000 Graphics API Black Book +// Chapter 1 - Listing 1.3 (BitBlt Bitmap Rendering Demo) +// +// Created by Damon Chandler +// Updates can be downloaded at: +// +// Please do not hesistate to e-mail me at dmc27@ee.cornell.edu +// if you have any questions about this code. +// ------------------------------------------------------------------ + + +//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +#include +//<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< + + +HINSTANCE HInst; +const char* WndClassName = "GMainWnd"; +LRESULT CALLBACK MainWndProc(HWND HWnd, UINT Msg, WPARAM WParam, + LPARAM LParam); + + +int APIENTRY WinMain(HINSTANCE HInstance, HINSTANCE HPrevInstance, + LPTSTR lpCmdLine, int nCmdShow) +{ + HInst = HInstance; + + WNDCLASS wc; + memset(&wc, 0, sizeof(WNDCLASS)); + + wc.style = CS_VREDRAW | CS_HREDRAW | CS_DBLCLKS; + wc.lpfnWndProc = MainWndProc; + wc.hInstance = HInstance; + wc.hCursor = LoadCursor(NULL, IDC_ARROW); + wc.hbrBackground = reinterpret_cast(COLOR_BTNFACE + 1); + wc.lpszClassName = WndClassName; + + if (RegisterClass(&wc)) + { + HWND HWnd = + CreateWindow( + WndClassName, TEXT("BitBlt Bitmap Rendering Demo"), + WS_OVERLAPPED | WS_SYSMENU | WS_CAPTION | + WS_VISIBLE | WS_CLIPSIBLINGS, + 0, 0, 220, 230, + NULL, NULL, HInst, NULL + ); + + if (HWnd) + { + ShowWindow(HWnd, nCmdShow); + UpdateWindow(HWnd); + + MSG msg; + while (GetMessage(&msg, NULL, 0, 0)) + { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + } + } + return 0; +} +//------------------------------------------------------------------ + + +// image related +BITMAP bmp; +LPCSTR filename = TEXT("lena.bmp"); +HDC HMemDC = NULL; +HBITMAP HOldBmp = NULL; + +LRESULT CALLBACK MainWndProc(HWND HWnd, UINT Msg, WPARAM WParam, + LPARAM LParam) +{ + switch (Msg) + { + case WM_CREATE: + { + // create a memory DC + HMemDC = CreateCompatibleDC(NULL); + if (HMemDC) + { + // load a bitmap from file + HBITMAP HBmp = + static_cast( + LoadImage(HInst, filename, IMAGE_BITMAP, + 0, 0, LR_LOADFROMFILE) + ); + if (HBmp) + { + // extract dimensions of the bitmap + GetObject(HBmp, sizeof(BITMAP), &bmp); + + // associate the bitmap with the memory DC + HOldBmp = static_cast( + SelectObject(HMemDC, HBmp) + ); + } + } + } + case WM_PAINT: + { + PAINTSTRUCT ps; + const HDC Hdc = BeginPaint(HWnd, &ps); + try + { + // + // TODO: add palette support (see Chapter 9)... + // + + BitBlt(Hdc, 20, 15, + bmp.bmWidth, bmp.bmHeight, + HMemDC, 0, 0, + SRCCOPY); + } + catch (...) + { + EndPaint(HWnd, &ps); + } + EndPaint(HWnd, &ps); + break; + } + case WM_DESTROY: + { + // clean up + DeleteObject(SelectObject(HMemDC, HOldBmp)); + DeleteDC(HMemDC); + + PostQuitMessage(0); + return 0; + } + } + return DefWindowProc(HWnd, Msg, WParam, LParam); +} +//------------------------------------------------------------------ diff --git a/reactos/apps/tests/bitblt/lena.bmp b/reactos/apps/tests/bitblt/lena.bmp new file mode 100644 index 00000000000..e9916963852 Binary files /dev/null and b/reactos/apps/tests/bitblt/lena.bmp differ diff --git a/reactos/apps/tests/bitblt/makefile b/reactos/apps/tests/bitblt/makefile new file mode 100644 index 00000000000..8ce98633074 --- /dev/null +++ b/reactos/apps/tests/bitblt/makefile @@ -0,0 +1,66 @@ +# Makefile - Proj_Listing1_5.dsp + +ifndef CFG +CFG=Proj_Listing1_5 - Win32 Debug +endif +CC=gcc +CFLAGS= +CXX=g++ +CXXFLAGS=$(CFLAGS) +RC=windres -O COFF +ifeq "$(CFG)" "Proj_Listing1_5 - Win32 Release" +CFLAGS+=-fexceptions -O2 -DWIN32 -DNDEBUG -D_WINDOWS -D_MBCS -W +LD=$(CXX) $(CXXFLAGS) +LDFLAGS= +LDFLAGS+=-Wl,--subsystem,windows +LIBS+=-lkernel32 -luser32 -lgdi32 +else +ifeq "$(CFG)" "Proj_Listing1_5 - Win32 Debug" +CFLAGS+=-fexceptions -g -O0 -DWIN32 -D_DEBUG -D_WINDOWS -D_MBCS -W +LD=$(CXX) $(CXXFLAGS) +LDFLAGS= +LDFLAGS+=-Wl,--subsystem,windows +LIBS+=-lkernel32 -luser32 -lgdi32 +endif +endif + +ifndef TARGET +TARGET=bitblt.exe +endif + +.PHONY: all +all: $(TARGET) + +%.o: %.c + $(CC) $(CFLAGS) $(CPPFLAGS) -o $@ -c $< + +%.o: %.cpp + $(CXX) $(CXXFLAGS) $(CPPFLAGS) -o $@ -c $< + +%.res: %.rc + $(RC) $(CPPFLAGS) -o $@ -i $< + +SOURCE_FILES= \ + bitblt.cpp + +HEADER_FILES= + +RESOURCE_FILES= + +SRCS=$(SOURCE_FILES) $(HEADER_FILES) $(RESOURCE_FILES) + +OBJS=$(patsubst %.rc,%.res,$(patsubst %.cpp,%.o,$(patsubst %.c,%.o,$(filter %.c %.cpp %.rc,$(SRCS))))) + +$(TARGET): $(OBJS) + $(LD) $(LDFLAGS) -o $@ $(OBJS) $(LIBS) + +.PHONY: clean +clean: + -del $(OBJS) $(TARGET) + +.PHONY: depends +depends: + -$(CXX) $(CXXFLAGS) $(CPPFLAGS) -MM $(filter %.c %.cpp,$(SRCS)) > Proj_Listing1_5.dep + +-include Proj_Listing1_5.dep + diff --git a/reactos/apps/tests/patblt/Penguin.bmp b/reactos/apps/tests/patblt/Penguin.bmp new file mode 100644 index 00000000000..ec4e1daaf93 Binary files /dev/null and b/reactos/apps/tests/patblt/Penguin.bmp differ diff --git a/reactos/apps/tests/patblt/makefile b/reactos/apps/tests/patblt/makefile new file mode 100644 index 00000000000..a433ac4d604 --- /dev/null +++ b/reactos/apps/tests/patblt/makefile @@ -0,0 +1,66 @@ +# Makefile - Proj_Listing2_1.dsp + +ifndef CFG +CFG=Proj_Listing2_1 - Win32 Debug +endif +CC=gcc +CFLAGS= +CXX=g++ +CXXFLAGS=$(CFLAGS) +RC=windres -O COFF +ifeq "$(CFG)" "Proj_Listing2_1 - Win32 Release" +CFLAGS+=-fexceptions -O2 -DWIN32 -DNDEBUG -D_WINDOWS -D_MBCS -W +LD=$(CXX) $(CXXFLAGS) +LDFLAGS= +LDFLAGS+=-Wl,--subsystem,windows +LIBS+=-lkernel32 -luser32 -lgdi32 +else +ifeq "$(CFG)" "Proj_Listing2_1 - Win32 Debug" +CFLAGS+=-fexceptions -g -O0 -DWIN32 -D_DEBUG -D_WINDOWS -D_MBCS -W +LD=$(CXX) $(CXXFLAGS) +LDFLAGS= +LDFLAGS+=-Wl,--subsystem,windows +LIBS+=-lkernel32 -luser32 -lgdi32 +endif +endif + +ifndef TARGET +TARGET=patblt.exe +endif + +.PHONY: all +all: $(TARGET) + +%.o: %.c + $(CC) $(CFLAGS) $(CPPFLAGS) -o $@ -c $< + +%.o: %.cpp + $(CXX) $(CXXFLAGS) $(CPPFLAGS) -o $@ -c $< + +%.res: %.rc + $(RC) $(CPPFLAGS) -o $@ -i $< + +SOURCE_FILES= \ + patblt.cpp + +HEADER_FILES= + +RESOURCE_FILES= + +SRCS=$(SOURCE_FILES) $(HEADER_FILES) $(RESOURCE_FILES) + +OBJS=$(patsubst %.rc,%.res,$(patsubst %.cpp,%.o,$(patsubst %.c,%.o,$(filter %.c %.cpp %.rc,$(SRCS))))) + +$(TARGET): $(OBJS) + $(LD) $(LDFLAGS) -o $@ $(OBJS) $(LIBS) + +.PHONY: clean +clean: + -del $(OBJS) $(TARGET) + +.PHONY: depends +depends: + -$(CXX) $(CXXFLAGS) $(CPPFLAGS) -MM $(filter %.c %.cpp,$(SRCS)) > Proj_Listing2_1.dep + +-include Proj_Listing2_1.dep + diff --git a/reactos/apps/tests/patblt/patblt.cpp b/reactos/apps/tests/patblt/patblt.cpp new file mode 100644 index 00000000000..84c5d7b26ac --- /dev/null +++ b/reactos/apps/tests/patblt/patblt.cpp @@ -0,0 +1,270 @@ + +// ------------------------------------------------------------------ +// Windows 2000 Graphics API Black Book +// Chapter 2 - Listing 2.1 (PatBlt Tracking Rect Demo) +// +// Created by Damon Chandler +// Updates can be downloaded at: +// +// Please do not hesistate to e-mail me at dmc27@ee.cornell.edu +// if you have any questions about this code. +// ------------------------------------------------------------------ + + +//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +#include +//<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< + + +HINSTANCE HInst; +const char* WndClassName = "GMainWnd"; +LRESULT CALLBACK MainWndProc(HWND HWnd, UINT Msg, WPARAM WParam, + LPARAM LParam); + + +int APIENTRY WinMain(HINSTANCE HInstance, HINSTANCE, LPTSTR, + int nCmdShow) +{ + HInst = HInstance; + + WNDCLASS wc; + memset(&wc, 0, sizeof(WNDCLASS)); + + wc.style = CS_VREDRAW | CS_HREDRAW; + wc.lpszClassName = WndClassName; + wc.lpfnWndProc = MainWndProc; + wc.hInstance = HInstance; + wc.hCursor = LoadCursor(NULL, IDC_ARROW); + wc.hbrBackground = static_cast( + GetStockObject(BLACK_BRUSH) + ); + + if (RegisterClass(&wc)) + { + HWND HWnd = + CreateWindow(WndClassName, + TEXT("PatBlt Tracking Rect Demo"), + WS_OVERLAPPEDWINDOW | WS_CAPTION | + WS_VISIBLE | WS_CLIPCHILDREN, + CW_USEDEFAULT, CW_USEDEFAULT, 640, 480, + NULL, NULL, HInst, NULL); + + if (HWnd) + { + ShowWindow(HWnd, nCmdShow); + UpdateWindow(HWnd); + + MSG msg; + while (GetMessage(&msg, NULL, 0, 0)) + { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + } + } + return 0; +} +//------------------------------------------------------------------ + + +// image related +HDC HMemDC = NULL; +HBITMAP HOldBmp = NULL; +const char* filename = "PENGUIN.BMP"; +RECT RImage = {225, 110, 225, 110}; + +// tracking related +bool is_tracking = false; +HDC HScreenDC = NULL; +POINT PMouse = {0, 0}; +RECT RTrack = {0, 0, 0, 0}; +const int line_width = 5; + + +// utility function to map to/from window coordinates +void MapRect(IN HWND HWndFrom, IN HWND HWndTo, IN OUT RECT& RMap) +{ + MapWindowPoints( + HWndFrom, HWndTo, + reinterpret_cast(&RMap), 2 + ); +} +//------------------------------------------------------------------ + + +// utility function that uses the PatBlt function to +// render a tracking rectangle +void RenderTrackingRect(IN HDC HDestDC, IN const RECT& RRender) +{ + const int width = RRender.right - RRender.left; + const int height = RRender.bottom - RRender.top; + const DWORD dwROP3 = DSTINVERT; // experiment with others + + // render top bar + PatBlt(HDestDC, + RRender.left, RRender.top, + width, line_width, + dwROP3); + // render bottom bar + PatBlt(HDestDC, + RRender.left, RRender.bottom - line_width, + width, line_width, + dwROP3); + // render left bar + PatBlt(HDestDC, + RRender.left, RRender.top + line_width, + line_width, height - (2 * line_width), + dwROP3); + // render right bar + PatBlt(HDestDC, + RRender.right - line_width, RRender.top + line_width, + line_width, height - (2 * line_width), + dwROP3); + +} +//------------------------------------------------------------------ + + +LRESULT CALLBACK MainWndProc(HWND HWnd, UINT Msg, WPARAM WParam, + LPARAM LParam) +{ + switch (Msg) + { + case WM_CREATE: + { + // create a memory DC + HMemDC = CreateCompatibleDC(NULL); + if (HMemDC) + { + // load the penguin bitmap + HBITMAP HBmp = static_cast( + LoadImage(HInst, filename, IMAGE_BITMAP, 0, 0, + LR_LOADFROMFILE | LR_DEFAULTSIZE) + ); + if (HBmp) + { + // get the bitmap's dimensions + BITMAP bmp; + if (GetObject(HBmp, sizeof(BITMAP), &bmp)) + { + RImage.right += bmp.bmWidth; + RImage.bottom += bmp.bmHeight; + + // realize the bitmap + HOldBmp = static_cast( + SelectObject(HMemDC, HBmp) + ); + } + else DeleteObject(HBmp); + } + } + break; + } + case WM_LBUTTONDOWN: + { + PMouse.x = LOWORD(LParam); + PMouse.y = HIWORD(LParam); + + RECT RClient; + if (PtInRect(&RImage, PMouse) && + GetClientRect(HWnd, &RClient)) + { + MapRect(HWnd, HWND_DESKTOP, RClient); + ClipCursor(&RClient); + + // grab a handle to the screen DC and clip + // all output to the client area of our window + HScreenDC = GetDC(NULL); + HRGN HClipRgn = CreateRectRgnIndirect(&RClient); + SelectClipRgn(HScreenDC, HClipRgn); + DeleteObject(HClipRgn); + + CopyRect(&RTrack, &RImage); + MapRect(HWnd, HWND_DESKTOP, RTrack); + + // render the first tracking rect + RenderTrackingRect(HScreenDC, RTrack); + is_tracking = true; + } + break; + } + case WM_MOUSEMOVE: + { + if (HScreenDC && is_tracking) + { + POINT PCurrent = {LOWORD(LParam), HIWORD(LParam)}; + const int dX = PCurrent.x - PMouse.x; + const int dY = PCurrent.y - PMouse.y; + + // erase the previous rectangle + RenderTrackingRect(HScreenDC, RTrack); + // update the postion + OffsetRect(&RTrack, dX, dY); + // render the new tracking rectangle + RenderTrackingRect(HScreenDC, RTrack); + + // update the mouse position + memcpy(&PMouse, &PCurrent, sizeof(POINT)); + } + break; + } + case WM_LBUTTONUP: + { + // clean up + if (is_tracking) + { + is_tracking = false; + SelectClipRgn(HScreenDC, NULL); + ReleaseDC(NULL, HScreenDC); + + InvalidateRect(HWnd, &RImage, true); + CopyRect(&RImage, &RTrack); + MapRect(HWND_DESKTOP, HWnd, RImage); + InvalidateRect(HWnd, &RImage, true); + + ClipCursor(NULL); + } + break; + } + case WM_PAINT: + { + PAINTSTRUCT ps; + HDC Hdc = BeginPaint(HWnd, &ps); + try + { + // + // TODO: Add palette support... + // + + // render the penguin + BitBlt(Hdc, RImage.left, RImage.top, + RImage.right - RImage.left, + RImage.bottom - RImage.top, + HMemDC, 0, 0, + SRCCOPY); + } + catch (...) + { + EndPaint(HWnd, &ps); + } + EndPaint(HWnd, &ps); + break; + } + case WM_DESTROY: + { + // clean up + if (HOldBmp) + { + DeleteObject(SelectObject(HMemDC, HOldBmp)); + } + if (HMemDC) + { + DeleteDC(HMemDC); + } + PostQuitMessage(0); + return 0; + } + } + return DefWindowProc(HWnd, Msg, WParam, LParam); +} +//------------------------------------------------------------------ diff --git a/reactos/apps/tests/stretchblt/lena.bmp b/reactos/apps/tests/stretchblt/lena.bmp new file mode 100644 index 00000000000..e9916963852 Binary files /dev/null and b/reactos/apps/tests/stretchblt/lena.bmp differ diff --git a/reactos/apps/tests/stretchblt/makefile b/reactos/apps/tests/stretchblt/makefile new file mode 100644 index 00000000000..fa3421f5af3 --- /dev/null +++ b/reactos/apps/tests/stretchblt/makefile @@ -0,0 +1,66 @@ +# Makefile - Proj_Listing1_5.dsp + +ifndef CFG +CFG=Proj_Listing1_5 - Win32 Debug +endif +CC=gcc +CFLAGS= +CXX=g++ +CXXFLAGS=$(CFLAGS) +RC=windres -O COFF +ifeq "$(CFG)" "Proj_Listing1_5 - Win32 Release" +CFLAGS+=-fexceptions -O2 -DWIN32 -DNDEBUG -D_WINDOWS -D_MBCS -W +LD=$(CXX) $(CXXFLAGS) +LDFLAGS= +LDFLAGS+=-Wl,--subsystem,windows +LIBS+=-lkernel32 -luser32 -lgdi32 +else +ifeq "$(CFG)" "Proj_Listing1_5 - Win32 Debug" +CFLAGS+=-fexceptions -g -O0 -DWIN32 -D_DEBUG -D_WINDOWS -D_MBCS -W +LD=$(CXX) $(CXXFLAGS) +LDFLAGS= +LDFLAGS+=-Wl,--subsystem,windows +LIBS+=-lkernel32 -luser32 -lgdi32 +endif +endif + +ifndef TARGET +TARGET=stretchblt.exe +endif + +.PHONY: all +all: $(TARGET) + +%.o: %.c + $(CC) $(CFLAGS) $(CPPFLAGS) -o $@ -c $< + +%.o: %.cpp + $(CXX) $(CXXFLAGS) $(CPPFLAGS) -o $@ -c $< + +%.res: %.rc + $(RC) $(CPPFLAGS) -o $@ -i $< + +SOURCE_FILES= \ + stretchblt.cpp + +HEADER_FILES= + +RESOURCE_FILES= + +SRCS=$(SOURCE_FILES) $(HEADER_FILES) $(RESOURCE_FILES) + +OBJS=$(patsubst %.rc,%.res,$(patsubst %.cpp,%.o,$(patsubst %.c,%.o,$(filter %.c %.cpp %.rc,$(SRCS))))) + +$(TARGET): $(OBJS) + $(LD) $(LDFLAGS) -o $@ $(OBJS) $(LIBS) + +.PHONY: clean +clean: + -del $(OBJS) $(TARGET) + +.PHONY: depends +depends: + -$(CXX) $(CXXFLAGS) $(CPPFLAGS) -MM $(filter %.c %.cpp,$(SRCS)) > Proj_Listing1_5.dep + +-include Proj_Listing1_5.dep + diff --git a/reactos/apps/tests/stretchblt/stretchblt.cpp b/reactos/apps/tests/stretchblt/stretchblt.cpp new file mode 100644 index 00000000000..40035f05efc --- /dev/null +++ b/reactos/apps/tests/stretchblt/stretchblt.cpp @@ -0,0 +1,258 @@ + +// ------------------------------------------------------------------ +// Windows 2000 Graphics API Black Book +// Chapter 1 - Listing 1.5 (StretchBlt Zooming Demo) +// +// Created by Damon Chandler +// Updates can be downloaded at: +// +// Please do not hesistate to e-mail me at dmc27@ee.cornell.edu +// if you have any questions about this code. +// ------------------------------------------------------------------ + + +//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +#include +//<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< + + +HWND HListBox = NULL; +const int ID_LISTBOX = 101; + +HINSTANCE HInst; +const char* WndClassName = "GMainWnd"; +LRESULT CALLBACK MainWndProc(HWND HWnd, UINT Msg, WPARAM WParam, + LPARAM LParam); + + +int APIENTRY WinMain(HINSTANCE HInstance, HINSTANCE HPrevInstance, + LPTSTR lpCmdLine, int nCmdShow) +{ + HInst = HInstance; + + WNDCLASS wc; + memset(&wc, 0, sizeof(WNDCLASS)); + + wc.style = CS_VREDRAW | CS_HREDRAW | CS_DBLCLKS; + wc.lpfnWndProc = MainWndProc; + wc.hInstance = HInstance; + wc.hCursor = LoadCursor(NULL, IDC_ARROW); + wc.hbrBackground = reinterpret_cast(COLOR_BTNFACE + 1); + wc.lpszClassName = WndClassName; + + if (RegisterClass(&wc)) + { + HWND HWnd = + CreateWindow(WndClassName, TEXT("StretchBlt Zooming Demo"), + WS_OVERLAPPEDWINDOW | WS_CAPTION | + WS_VISIBLE | WS_CLIPSIBLINGS, + 0, 0, 675, 560, + NULL, NULL, HInst, NULL); + + if (HWnd) + { + HListBox = + CreateWindowEx(WS_EX_CLIENTEDGE, "LISTBOX", "", + LBS_NOTIFY | WS_CHILD | WS_VISIBLE, + 530, 5, 130, 150, HWnd, + reinterpret_cast(ID_LISTBOX), + HInst, NULL); + if (HListBox) + { + SNDMSG(HListBox, LB_ADDSTRING, 0, + reinterpret_cast("Zoom 25%")); + SNDMSG(HListBox, LB_ADDSTRING, 0, + reinterpret_cast("Zoom 50%")); + SNDMSG(HListBox, LB_ADDSTRING, 0, + reinterpret_cast("Zoom 75%")); + SNDMSG(HListBox, LB_ADDSTRING, 0, + reinterpret_cast("Zoom 100%")); + SNDMSG(HListBox, LB_ADDSTRING, 0, + reinterpret_cast("Zoom 125%")); + SNDMSG(HListBox, LB_ADDSTRING, 0, + reinterpret_cast("Zoom 150%")); + SNDMSG(HListBox, LB_ADDSTRING, 0, + reinterpret_cast("Zoom 200%")); + SNDMSG(HListBox, LB_ADDSTRING, 0, + reinterpret_cast("Zoom 300%")); + } + + ShowWindow(HWnd, nCmdShow); + UpdateWindow(HWnd); + + MSG msg; + while (GetMessage(&msg, NULL, 0, 0)) + { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + } + } + return 0; +} +//------------------------------------------------------------------ + + +// image related +BITMAP bmp; +const char* filename = "LENA.BMP"; +HDC HMemDC = NULL; +HBITMAP HOldBmp = NULL; + +// zooming related +float zoom_factor = 0.5; +RECT RDest = {5, 5, 0, 0}; +enum {ID_ZOOM25, ID_ZOOM50, ID_ZOOM75, ID_ZOOM100, + ID_ZOOM125, ID_ZOOM150, ID_ZOOM200, ID_ZOOM300}; + +LRESULT CALLBACK MainWndProc(HWND HWnd, UINT Msg, WPARAM WParam, + LPARAM LParam) +{ + switch (Msg) + { + case WM_CREATE: + { + // create a memory DC + HMemDC = CreateCompatibleDC(NULL); + if (HMemDC) + { + // load a bitmap from file + HBITMAP HBmp = + static_cast( + LoadImage(HInst, filename, IMAGE_BITMAP, + 0, 0, LR_LOADFROMFILE) + ); + if (HBmp) + { + // extract dimensions of the bitmap + GetObject(HBmp, sizeof(BITMAP), &bmp); + + // associate the bitmap with the memory DC + HOldBmp = static_cast( + SelectObject(HMemDC, HBmp) + ); + } + } + } + case WM_COMMAND: + { + if (WParam == MAKEWPARAM(ID_LISTBOX, LBN_SELCHANGE)) + { + switch (SNDMSG(HListBox, LB_GETCURSEL, 0, 0)) + { + case ID_ZOOM25: zoom_factor = 0.25; break; + case ID_ZOOM50: zoom_factor = 0.50; break; + case ID_ZOOM75: zoom_factor = 0.75; break; + case ID_ZOOM100: zoom_factor = 1.00; break; + case ID_ZOOM125: zoom_factor = 1.25; break; + case ID_ZOOM150: zoom_factor = 1.50; break; + case ID_ZOOM200: zoom_factor = 2.00; break; + case ID_ZOOM300: zoom_factor = 3.00; break; + } + + // calculate the new width and height + const int new_width = + static_cast(zoom_factor * bmp.bmWidth); + const int new_height = + static_cast(zoom_factor * bmp.bmHeight); + + // is zooming in? + bool zoom_in = (new_width > RDest.right - RDest.left); + + // caculate the area that needs to be updated + RECT RUpdate = { + RDest.left, RDest.top, + RDest.left + max(new_width, RDest.right - RDest.left), + RDest.top + max(new_height, RDest.bottom - RDest.top) + }; + + // adjust the dimenstions of the + // destination rectangle + RDest.right = RDest.left + new_width; + RDest.bottom = RDest.top + new_height; + + // create an update region from the XOR combination + // of the update and destination rectangles + HRGN HUpdateRgn = CreateRectRgnIndirect(&RUpdate); + HRGN HDestRgn = CreateRectRgnIndirect(&RDest); + int result = + CombineRgn(HUpdateRgn, HUpdateRgn, HDestRgn, RGN_XOR); + + // incite a repaint + if (result != NULLREGION && result != ERROR) + { + InvalidateRgn(HWnd, HUpdateRgn, true); + RedrawWindow(HWnd, &RDest, NULL, RDW_NOERASE | RDW_INVALIDATE); + } + else if (result == NULLREGION) + { + InvalidateRect(HWnd, &RUpdate, zoom_in ? false : true); + } + + // clean up + DeleteObject(HUpdateRgn); + DeleteObject(HDestRgn); + } + break; + } + case WM_PAINT: + { + PAINTSTRUCT ps; + const HDC Hdc = BeginPaint(HWnd, &ps); + try + { + // + // TODO: add palette support (see Chapter 9)... + // + + if (RDest.right - RDest.left > 0) + { + // use BitBlt when not zooming + if (zoom_factor == 1.0) + { + BitBlt(Hdc, RDest.left, RDest.top, + RDest.right - RDest.left, + RDest.bottom - RDest.top, + HMemDC, 0, 0, + SRCCOPY); + } + else + { + if (zoom_factor < 1.0) + { + SetStretchBltMode(Hdc, COLORONCOLOR); + } + + // render the zoomed image + StretchBlt(Hdc, RDest.left, RDest.top, + RDest.right - RDest.left, + RDest.bottom - RDest.top, + HMemDC, 0, 0, + bmp.bmWidth, bmp.bmHeight, + SRCCOPY); + } + } + } + catch (...) + { + EndPaint(HWnd, &ps); + } + EndPaint(HWnd, &ps); + break; + } + case WM_DESTROY: + { + // clean up + DeleteObject(SelectObject(HMemDC, HOldBmp)); + DeleteDC(HMemDC); + + PostQuitMessage(0); + return 0; + } + } + return DefWindowProc(HWnd, Msg, WParam, LParam); +} +//------------------------------------------------------------------ + + +