added tests for StretchBlt, PatBlt and BitBlt by Damon Chandler

svn path=/trunk/; revision=3652
This commit is contained in:
Steven Edwards 2002-10-24 07:46:43 +00:00
parent 95bb94d117
commit a42476b9fb
9 changed files with 864 additions and 0 deletions

View file

@ -0,0 +1,138 @@
// ------------------------------------------------------------------
// Windows 2000 Graphics API Black Book
// Chapter 1 - Listing 1.3 (BitBlt Bitmap Rendering Demo)
//
// Created by Damon Chandler <dmc27@ee.cornell.edu>
// Updates can be downloaded at: <www.coriolis.com>
//
// Please do not hesistate to e-mail me at dmc27@ee.cornell.edu
// if you have any questions about this code.
// ------------------------------------------------------------------
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
#include <windows.h>
//<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
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<HBRUSH>(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<HBITMAP>(
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<HBITMAP>(
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);
}
//------------------------------------------------------------------

Binary file not shown.

After

Width:  |  Height:  |  Size: 87 KiB

View file

@ -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

Binary file not shown.

After

Width:  |  Height:  |  Size: 104 KiB

View file

@ -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

View file

@ -0,0 +1,270 @@
// ------------------------------------------------------------------
// Windows 2000 Graphics API Black Book
// Chapter 2 - Listing 2.1 (PatBlt Tracking Rect Demo)
//
// Created by Damon Chandler <dmc27@ee.cornell.edu>
// Updates can be downloaded at: <www.coriolis.com>
//
// Please do not hesistate to e-mail me at dmc27@ee.cornell.edu
// if you have any questions about this code.
// ------------------------------------------------------------------
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
#include <windows.h>
//<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
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<HBRUSH>(
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<LPPOINT>(&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<HBITMAP>(
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<HBITMAP>(
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);
}
//------------------------------------------------------------------

Binary file not shown.

After

Width:  |  Height:  |  Size: 87 KiB

View file

@ -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

View file

@ -0,0 +1,258 @@
// ------------------------------------------------------------------
// Windows 2000 Graphics API Black Book
// Chapter 1 - Listing 1.5 (StretchBlt Zooming Demo)
//
// Created by Damon Chandler <dmc27@ee.cornell.edu>
// Updates can be downloaded at: <www.coriolis.com>
//
// Please do not hesistate to e-mail me at dmc27@ee.cornell.edu
// if you have any questions about this code.
// ------------------------------------------------------------------
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
#include <windows.h>
//<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
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<HBRUSH>(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<HMENU>(ID_LISTBOX),
HInst, NULL);
if (HListBox)
{
SNDMSG(HListBox, LB_ADDSTRING, 0,
reinterpret_cast<LPARAM>("Zoom 25%"));
SNDMSG(HListBox, LB_ADDSTRING, 0,
reinterpret_cast<LPARAM>("Zoom 50%"));
SNDMSG(HListBox, LB_ADDSTRING, 0,
reinterpret_cast<LPARAM>("Zoom 75%"));
SNDMSG(HListBox, LB_ADDSTRING, 0,
reinterpret_cast<LPARAM>("Zoom 100%"));
SNDMSG(HListBox, LB_ADDSTRING, 0,
reinterpret_cast<LPARAM>("Zoom 125%"));
SNDMSG(HListBox, LB_ADDSTRING, 0,
reinterpret_cast<LPARAM>("Zoom 150%"));
SNDMSG(HListBox, LB_ADDSTRING, 0,
reinterpret_cast<LPARAM>("Zoom 200%"));
SNDMSG(HListBox, LB_ADDSTRING, 0,
reinterpret_cast<LPARAM>("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<HBITMAP>(
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<HBITMAP>(
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<int>(zoom_factor * bmp.bmWidth);
const int new_height =
static_cast<int>(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);
}
//------------------------------------------------------------------