以下示例使用户能够将屏幕内容捕获到位图中,并滚动客户端区域中的位图。
HDC hdc;
PAINTSTRUCT ps;
SCROLLINFO si;
/ * BitBlt需要这些变量。*/
static HDC hdcWin; /* window DC */
static HDC hdcScreen; /* DC for entire screen */
static HDC hdcScreenCompat; /* memory DC for screen */
static HBITMAP hbmpCompat; /* bitmap handle for old DC */
static BITMAP bmp; /* bitmap data structure */
static BOOL fBlt; /* TRUE if BitBlt occurred */
static BOOL fScroll; /* TRUE if scrolling occurred */
static BOOL fSize; / * TRUE if fBlt & WM_SIZE * /
/ *这些变量是水平滚动所必需的。*/
static int xMinScroll; /* minimum horizontal scroll value */
static int xCurrentScroll; /* current horizontal scroll value */
static int xMaxScroll; /* maximum horizontal scroll value */
/ *垂直滚动需要这些变量。*/
static int yMinScroll; /* minimum vertical scroll value */
static int yCurrentScroll; /* current vertical scroll value */
static int yMaxScroll; /* maximum vertical scroll value */
开关(uMsg){
case WM_CREATE:
/*
*为整体创建一个正常的DC和一个内存DC
*屏幕。正常的DC提供了一个快照
*屏幕内容。内存DC保留这个的副本
*相关位图中的快照。
*/
hdcScreen = CreateDC("DISPLAY", (LPCSTR) NULL,
(LPCSTR) NULL, (CONST DEVMODE *) NULL);
hdcScreenCompat = CreateCompatibleDC(hdcScreen);
/*
*检索与该关联的位图的度量
*常规设备上下文。
*/
bmp.bmBitsPixel =
(BYTE) GetDeviceCaps(hdcScreen, BITSPIXEL);
bmp.bmPlanes = (BYTE) GetDeviceCaps(hdcScreen, PLANES);
bmp.bmWidth = GetDeviceCaps(hdcScreen, HORZRES);
bmp.bmHeight = GetDeviceCaps(hdcScreen, VERTRES);
/ *宽度必须是字节对齐。*/
bmp.bmWidthBytes = ((bmp.bmWidth + 15) &~15)/8;
/ *为兼容DC创建位图。*/
hbmpCompat = CreateBitmap(bmp.bmWidth, bmp.bmHeight,
bmp.bmPlanes, bmp.bmBitsPixel, (CONST VOID *) NULL);
/ *选择兼容的DC的位图。*/
SelectObject(hdcScreenCompat, hbmpCompat);
/ *初始化标志。*/
fBlt = FALSE;
fScroll = FALSE;
fSize = FALSE;
/ *初始化水平滚动变量。*/
xMinScroll = 0;
xCurrentScroll = 0;
xMaxScroll = 0;
/ *初始化垂直滚动变量。*/
yMinScroll = 0;
yCurrentScroll = 0;
yMaxScroll = 0;
break;
case WM_SIZE: {
int xNewSize;
int yNewSize;
xNewSize = LOWORD(lParam);
yNewSize = HIWORD(lParam);
if(fBlt)
fSize = TRUE;
/*
*水平滚动范围由...定义
*(bitmap_width) - (client_width)。当前水平
*滚动值保持在水平滚动范围内。
*/
xMaxScroll = max(bmp.bmWidth-xNewSize, 0);
xCurrentScroll = min(xCurrentScroll, xMaxScroll);
si.cbSize = sizeof(si);
si.fMask = SIF_RANGE | SIF_PAGE | SIF_POS;
si.nMin = xMinScroll;
si.nMax = xMaxScroll;
si.nPage = xNewSize;
si.nPos = xCurrentScroll;
SetScrollInfo(hwnd, SB_HORZ, &si, TRUE);
/*
*垂直滚动范围由...定义
*(bitmap_height) - (client_height)。当前垂直
*滚动值保持在垂直滚动范围内。
*/
yMaxScroll = max(bmp.bmHeight - yNewSize, 0);
yCurrentScroll = min(yCurrentScroll, yMaxScroll);
si.cbSize = sizeof(si);
si.fMask = SIF_RANGE | SIF_PAGE | SIF_POS;
si.nMin = yMinScroll;
si.nMax = yMaxScroll;
si.nPage = yNewSize;
si.nPos = yCurrentScroll;
SetScrollInfo(hwnd, SB_VERT, &si, TRUE);
}
break;
case WM_PAINT: {
PRECT prect;
hdc = BeginPaint(hwnd, &ps);
/*
*如果窗口已经被调整大小,并且用户有
*捕获屏幕,使用以下调用
* BitBlt绘制窗口的客户区。
*/
if(fSize){
BitBlt(ps.hdc,
0, 0,
bmp.bmWidth,bmp.bmHeight,
hdcScreenCompat,
xCurrentScroll,yCurrentScroll,
SRCCOPY);
fSize = FALSE;
}
/*
*如果滚动发生,请使用以下调用
* BitBlt绘制无效矩形。
*
*这个矩形的坐标是在
* RECT结构,其中prect点。
*
*请注意,有必要增加第七
*参数(prect- >左)由xCurrentScroll和
*第八个参数(prect- > top)由yCurrentScroll在
*从源位图映射正确的像素。
*/
if(fScroll){
prect = &ps.rcPaint;
BitBlt(ps.hdc,
prect- > left,prect- > top,
(prect- > right - prect- >左),
(prect- > bottom-prect- > top),
hdcScreenCompat,
prect- > left + xCurrentScroll,
prect- > top + yCurrentScroll,
SRCCOPY);
fScroll = FALSE;
}
EndPaint(hwnd, &ps);
}
break;
case WM_HSCROLL: {
int xDelta; /* xDelta = new_pos - current_pos */
int xNewPos; /* new position */
int yDelta = 0;
开关(LOWORD(wParam)){
/ *用户点击滚动框左侧的轴。*/
case SB_PAGEUP:
xNewPos = xCurrentScroll - 50;
break;
/ *用户点击滚动框右侧的轴。*/
case SB_PAGEDOWN:
xNewPos = xCurrentScroll + 50;
break;
/ *用户点击左箭头。*/
case SB_LINEUP:
xNewPos = xCurrentScroll - 5;
break;
/ *用户点击右箭头。*/
case SB_LINEDOWN:
xNewPos = xCurrentScroll + 5;
break;
/ *用户拖动滚动框。*/
case SB_THUMBPOSITION:
xNewPos = HIWORD(wParam);
break;
默认:
xNewPos = xCurrentScroll;
}
/ *新位置必须介于0和屏幕宽度之间。*/
xNewPos = max(0, xNewPos);
xNewPos = min(xMaxScroll, xNewPos);
/ *如果当前位置不变,请不要滚动。* /
if (xNewPos == xCurrentScroll)
break;
/ *将滚动标志设置为TRUE。*/
fScroll = TRUE;
/ *确定滚动量(以像素为单位)。*/
xDelta = xNewPos - xCurrentScroll;
/ *重置当前滚动位置。*/
xCurrentScroll = xNewPos;
/*
*滚动窗口。(系统重绘大部分
* client area when ScrollWindowEx is called; however, it is
*必须调用UpdateWindow才能重新绘制
*无效的像素矩形。)
*/
ScrollWindowEx(hwnd,-xDelta,-yDelta,(CONST RECT *)NULL,
(CONST RECT *) NULL, (HRGN) NULL, (LPRECT) NULL,
SW_INVALIDATE);
UpdateWindow(hwnd);
/ *重置滚动条。*/
si.cbSize = sizeof(si);
si.fMask = SIF_POS;
si.nPos = xCurrentScroll;
SetScrollInfo(hwnd, SB_HORZ, &si, TRUE);
}
break;
case WM_VSCROLL: {
int xDelta = 0;
int yDelta; /* yDelta = new_pos - current_pos */
int yNewPos; /* new position */
开关(LOWORD(wParam)){
/ *用户点击滚动框上方的轴。*/
case SB_PAGEUP:
yNewPos = yCurrentScroll - 50;
break;
/ *用户点击滚动条下方的轴。*/
case SB_PAGEDOWN:
yNewPos = yCurrentScroll + 50;
break;
/ *用户点击顶部箭头。*/
case SB_LINEUP:
yNewPos = yCurrentScroll - 5;
break;
/ *用户点击底部箭头。*/
case SB_LINEDOWN:
yNewPos = yCurrentScroll + 5;
break;
/ *用户拖动滚动框。*/
case SB_THUMBPOSITION:
yNewPos = HIWORD(wParam);
break;
默认:
yNewPos = yCurrentScroll;
}
/ *新位置必须在0和屏幕高度之间。*/
yNewPos = max(0, yNewPos);
yNewPos = min(yMaxScroll, yNewPos);
/ *如果当前位置不变,请不要滚动。* /
if (yNewPos == yCurrentScroll)
break;
/ *将滚动标志设置为TRUE。*/
fScroll = TRUE;
/ *确定滚动量(以像素为单位)。*/
yDelta = yNewPos - yCurrentScroll;
/ *重置当前滚动位置。*/
yCurrentScroll = yNewPos;
/*
*滚动窗口。(系统重绘大部分
* client area when ScrollWindowEx is called; however, it is
*必须调用UpdateWindow才能重新绘制
*无效的像素矩形。)
*/
ScrollWindowEx(hwnd,-xDelta,-yDelta,(CONST RECT *)NULL,
(CONST RECT *) NULL, (HRGN) NULL, (LPRECT) NULL,
SW_INVALIDATE);
UpdateWindow(hwnd);
/ *重置滚动条。*/
si.cbSize = sizeof(si);
si.fMask = SIF_POS;
si.nPos = yCurrentScroll;
SetScrollInfo(hwnd, SB_VERT, &si, TRUE);
}
break;
case WM_COMMAND: /* uMsg: command from app. menu */
开关(wParam){
case IDM_STC:
/*
*复制当前屏幕的内容
*进入兼容DC。
*/
BitBlt(hdcScreenCompat,0,0,bmp.bmWidth,
bmp.bmHeight, hdcScreen, 0, 0, SRCCOPY);
/*
*将兼容DC复制到客户端区域。
*/
hdcWin = GetDC(hwnd);
BitBlt(hdcWin,0,0,bmp.bmWidth,bmp.bmHeight,
hdcScreenCompat, 0, 0, SRCCOPY);
ReleaseDC(hwnd, hdcWin);
fBlt = TRUE;
break;
默认:
return(DefWindowProc(hwnd,uMsg,
wParam, lParam));
}
break;