/*---------------------------------------
BLOWUP.C -- Video Magnifier Program
(c) Charles Petzold, 1998
---------------------------------------*/
#include <windows.h>
#include <stdlib.h> // for abs definition
#include "resource.h"
LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
PSTR szCmdLine, int iCmdShow)
{
static TCHAR szAppName [] = TEXT ("Blowup") ;
HACCEL hAccel ;
HWND hwnd ;
MSG msg ;
WNDCLASS wndclass ;
wndclass.style = CS_HREDRAW | CS_VREDRAW ;
wndclass.lpfnWndProc = WndProc ;
wndclass.cbClsExtra = 0 ;
wndclass.cbWndExtra = 0 ;
wndclass.hInstance = hInstance ;
wndclass.hIcon = LoadIcon (NULL, IDI_APPLICATION) ;
wndclass.hCursor = LoadCursor (NULL, IDC_ARROW) ;
wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH) ;
wndclass.lpszMenuName = szAppName ;
wndclass.lpszClassName = szAppName ;
if (!RegisterClass (&wndclass))
{
MessageBox (NULL, TEXT ("This program requires Windows NT!"),
szAppName, MB_ICONERROR) ;
return 0 ;
}
hwnd = CreateWindow (szAppName, TEXT ("Blow-Up Mouse Demo"),
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT,
NULL, NULL, hInstance, NULL) ;
ShowWindow (hwnd, iCmdShow) ;
UpdateWindow (hwnd) ;
hAccel = LoadAccelerators (hInstance, szAppName) ;
while (GetMessage (&msg, NULL, 0, 0))
{
if (!TranslateAccelerator (hwnd, hAccel, &msg))
{
TranslateMessage (&msg) ;
DispatchMessage (&msg) ;
}
}
return msg.wParam ;
}
void InvertBlock (HWND hwndScr, HWND hwnd, POINT ptBeg, POINT ptEnd)
{
HDC hdc ;
// 获取桌面窗口的显示设备上下文环境的句柄
// DCX_CACHE 从高速缓存中返回设备上下文环境,从本质上覆盖CS_OWNDC和CS_CLASSDC。
// DCX_LOCKWINDOWUPDATE 指明可以在锁定期间进行绘制
hdc = GetDCEx (hwndScr, NULL, DCX_CACHE | DCX_LOCKWINDOWUPDATE) ;
// 将用户坐标转换成屏幕坐标
ClientToScreen (hwnd, &ptBeg) ;
ClientToScreen (hwnd, &ptEnd) ;
// 绘制给定的矩形区域 DSTINVERT标记将目标矩形颜色反向
PatBlt (hdc, ptBeg.x, ptBeg.y, ptEnd.x - ptBeg.x, ptEnd.y - ptBeg.y,
DSTINVERT) ;
ReleaseDC (hwndScr, hdc) ;
}
HBITMAP CopyBitmap (HBITMAP hBitmapSrc)
{
BITMAP bitmap ;
HBITMAP hBitmapDst ;
HDC hdcSrc, hdcDst ;
// 获取位图信息,并建立新位图
GetObject (hBitmapSrc, sizeof (BITMAP), &bitmap) ;
hBitmapDst = CreateBitmapIndirect (&bitmap) ;
// 建立兼容内存设备环境,并选进位图
hdcSrc = CreateCompatibleDC (NULL) ;
hdcDst = CreateCompatibleDC (NULL) ;
SelectObject (hdcSrc, hBitmapSrc) ;
SelectObject (hdcDst, hBitmapDst) ;
BitBlt (hdcDst, 0, 0, bitmap.bmWidth, bitmap.bmHeight,
hdcSrc, 0, 0, SRCCOPY) ;
DeleteDC (hdcSrc) ;
DeleteDC (hdcDst) ;
return hBitmapDst ;
}
LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
static BOOL bCapturing, bBlocking ;
static HBITMAP hBitmap ;
static HWND hwndScr ;
static POINT ptBeg, ptEnd ;
BITMAP bm ;
HBITMAP hBitmapClip ;
HDC hdc, hdcMem ;
int iEnable ;
PAINTSTRUCT ps ;
RECT rect ;
switch (message)
{
// 处理鼠标左键按键
case WM_LBUTTONDOWN:
if (!bCapturing)
{
// 锁定桌面窗口 // 获取桌面窗口设备句柄
if (LockWindowUpdate (hwndScr = GetDesktopWindow ()))
{
bCapturing = TRUE ;
// 设置鼠标捕获
SetCapture (hwnd) ;
// 设置鼠标光标形状
SetCursor (LoadCursor (NULL, IDC_CROSS)) ;
}
else
MessageBeep (0) ;
}
return 0 ;
// 处理鼠标右键按下
case WM_RBUTTONDOWN:
// 在鼠标左键按下的情况下才执行
if (bCapturing)
{
bBlocking = TRUE ;
// 取得鼠标右键按下时的坐标
ptBeg.x = LOWORD (lParam) ;
ptBeg.y = HIWORD (lParam) ;
ptEnd = ptBeg ;
// 使选择矩形颜色反向
InvertBlock (hwndScr, hwnd, ptBeg, ptEnd) ;
}
return 0 ;
// 处理鼠标移动
case WM_MOUSEMOVE:
// 在鼠标左右键均按下的情况下执行
if (bBlocking)
{
InvertBlock (hwndScr, hwnd, ptBeg, ptEnd) ;
ptEnd.x = LOWORD (lParam) ;
ptEnd.y = HIWORD (lParam) ;
InvertBlock (hwndScr, hwnd, ptBeg, ptEnd) ;
}
return 0 ;
// 处理鼠标左右键释放
case WM_LBUTTONUP:
case WM_RBUTTONUP:
// 如果鼠标右键释放则执行
if (bBlocking)
{
// 反转选择矩形颜色,获取释放时鼠标坐标
InvertBlock (hwndScr, hwnd, ptBeg, ptEnd) ;
ptEnd.x = LOWORD (lParam) ;
ptEnd.y = HIWORD (lParam) ;
if (hBitmap)
{
DeleteObject (hBitmap) ;
hBitmap = NULL ;
}
// abs 求整数的绝对值
hdc = GetDC (hwnd) ;
hdcMem = CreateCompatibleDC (hdc) ;
hBitmap = CreateCompatibleBitmap (hdc,
abs (ptEnd.x - ptBeg.x),
abs (ptEnd.y - ptBeg.y)) ;
SelectObject (hdcMem, hBitmap) ;
// 拉伸显示到内存设备环境中
StretchBlt (hdcMem, 0, 0, abs (ptEnd.x - ptBeg.x),
abs (ptEnd.y - ptBeg.y),
hdc, ptBeg.x, ptBeg.y, ptEnd.x - ptBeg.x,
ptEnd.y - ptBeg.y, SRCCOPY) ;
DeleteDC (hdcMem) ;
ReleaseDC (hwnd, hdc) ;
InvalidateRect (hwnd, NULL, TRUE) ;
}
if (bBlocking || bCapturing)
{
bBlocking = bCapturing = FALSE ;
// 修改鼠标光标,释放鼠标捕获,解锁桌面窗口
SetCursor (LoadCursor (NULL, IDC_ARROW)) ;
ReleaseCapture () ;
LockWindowUpdate (NULL) ;
}
return 0 ;
// 菜单准备弹出时,处理可选项
case WM_INITMENUPOPUP:
// 判断剪贴板中CF_BITMAP数据是否存在,依此修改菜单可选项
iEnable = IsClipboardFormatAvailable (CF_BITMAP) ?
MF_ENABLED : MF_GRAYED ;
EnableMenuItem ((HMENU) wParam, IDM_EDIT_PASTE, iEnable) ;
// 判断位图是否建立,依此修改菜单可选项
iEnable = hBitmap ? MF_ENABLED : MF_GRAYED ;
EnableMenuItem ((HMENU) wParam, IDM_EDIT_CUT, iEnable) ;
EnableMenuItem ((HMENU) wParam, IDM_EDIT_COPY, iEnable) ;
EnableMenuItem ((HMENU) wParam, IDM_EDIT_DELETE, iEnable) ;
return 0 ;
case WM_COMMAND:
switch (LOWORD (wParam))
{
case IDM_EDIT_CUT:
case IDM_EDIT_COPY:
if (hBitmap)
{
hBitmapClip = CopyBitmap (hBitmap) ;
// 打开、清空和更新剪贴板
OpenClipboard (hwnd) ;
EmptyClipboard () ;
SetClipboardData (CF_BITMAP, hBitmapClip) ;
}
if (LOWORD (wParam) == IDM_EDIT_COPY)
return 0 ;
// 如果是 剪切 指令,则继续执行
case IDM_EDIT_DELETE:
if (hBitmap)
{
DeleteObject (hBitmap) ;
hBitmap = NULL ;
}
InvalidateRect (hwnd, NULL, TRUE) ;
return 0 ;
case IDM_EDIT_PASTE:
if (hBitmap)
{
DeleteObject (hBitmap) ;
hBitmap = NULL ;
}
// 获取剪贴板中的位图数据句柄
OpenClipboard (hwnd) ;
hBitmapClip = GetClipboardData (CF_BITMAP) ;
// 拷贝剪贴板中的位图数据到程序内存
if (hBitmapClip)
hBitmap = CopyBitmap (hBitmapClip) ;
CloseClipboard () ;
InvalidateRect (hwnd, NULL, TRUE) ;
return 0 ;
}
break ;
case WM_PAINT:
hdc = BeginPaint (hwnd, &ps) ;
if (hBitmap)
{
// 取得窗口大小
GetClientRect (hwnd, &rect) ;
hdcMem = CreateCompatibleDC (hdc) ;
SelectObject (hdcMem, hBitmap) ;
// 取得位图信息
GetObject (hBitmap, sizeof (BITMAP), (PSTR) &bm) ;
// 设置指定设备环境中的位图拉伸模式
// COLORONCOLOR:该模式删除所有消除的像素行,不保留其信息
SetStretchBltMode (hdc, COLORONCOLOR) ;
StretchBlt (hdc, 0, 0, rect.right, rect.bottom,
hdcMem, 0, 0, bm.bmWidth, bm.bmHeight, SRCCOPY) ;
DeleteDC (hdcMem) ;
}
EndPaint (hwnd, &ps) ;
return 0 ;
case WM_DESTROY:
if (hBitmap)
DeleteObject (hBitmap) ;
PostQuitMessage (0) ;
return 0 ;
}
return DefWindowProc (hwnd, message, wParam, lParam) ;
}