- 對比“滾動條的實現(1)":SetScrollINfo(...)和GetScrollInfo(...)多了兩項新特性:1.滾動條滑塊大小隨界面改變;2.對比滑塊位置HIWORD(wParam)從16位擴展到nPos的32位。
- 函式解析:
- 程式代碼 參考《windows程式設計 第五版》
- Metrics.h
#ifndef _METRICS_H__
#define _METRICS_H__
#include <windows.h>
#define NUMLINES ((int) (sizeof sysmetrics / sizeof sysmetrics [0]))
typedef struct
{
int Index;
TCHAR * szLabel;
TCHAR * szDesc;
}ST_METRICS, *PST_METRICS;
ST_METRICS sysmetrics[] =
{
SM_CXSCREEN, TEXT("SM_CXSCREEN"), TEXT("Screen width in pixels"),
SM_CYSCREEN, TEXT("SM_CYSCREEN"), TEXT("Screen height in pixels"),
SM_CXVSCROLL, TEXT("SM_CXVSCROLL"), TEXT("Vertical scroll width"),
SM_CYHSCROLL, TEXT("SM_CYHSCROLL"), TEXT("Horizontal scroll height"),
SM_CYCAPTION, TEXT("SM_CYCAPTION"), TEXT("Caption bar height"),
SM_CXBORDER, TEXT("SM_CXBORDER"), TEXT("Window border width"),
SM_CYBORDER, TEXT("SM_CYBORDER"), TEXT("Window border height"),
SM_CXFIXEDFRAME, TEXT("SM_CXFIXEDFRAME"), TEXT("Dialog window frame width"),
SM_CYFIXEDFRAME, TEXT("SM_CYFIXEDFRAME"), TEXT("Dialog window frame height"),
SM_CYVTHUMB, TEXT("SM_CYVTHUMB"), TEXT("Vertical scroll thumb height"),
SM_CXHTHUMB, TEXT("SM_CXHTHUMB"), TEXT("Horizontal scroll thumb width"),
SM_CXICON, TEXT("SM_CXICON"), TEXT("Icon width"),
SM_CYICON, TEXT("SM_CYICON"), TEXT("Icon height"),
SM_CXCURSOR, TEXT("SM_CXCURSOR"), TEXT("Cursor width"),
SM_CYCURSOR, TEXT("SM_CYCURSOR"), TEXT("Cursor height"),
SM_CYMENU, TEXT("SM_CYMENU"), TEXT("Menu bar height"),
SM_CXFULLSCREEN, TEXT("SM_CXFULLSCREEN"), TEXT("Full screen client area width"),
SM_CYFULLSCREEN, TEXT("SM_CYFULLSCREEN"), TEXT("Full screen client area height"),
SM_CYKANJIWINDOW, TEXT("SM_CYKANJIWINDOW"), TEXT("Kanji window height"),
SM_MOUSEPRESENT, TEXT("SM_MOUSEPRESENT"), TEXT("Mouse present flag"),
SM_CYVSCROLL, TEXT("SM_CYVSCROLL"), TEXT("Vertical scroll arrow height"),
SM_CXHSCROLL, TEXT("SM_CXHSCROLL"), TEXT("Horizontal scroll arrow width"),
SM_DEBUG, TEXT("SM_DEBUG"), TEXT("Debug version flag"),
SM_SWAPBUTTON, TEXT("SM_SWAPBUTTON"), TEXT("Mouse buttons swapped flag"),
SM_CXMIN, TEXT("SM_CXMIN"), TEXT("Minimum window width"),
SM_CYMIN, TEXT("SM_CYMIN"), TEXT("Minimum window height"),
SM_CXSIZE, TEXT("SM_CXSIZE"), TEXT("Min/Max/Close button width"),
SM_CYSIZE, TEXT("SM_CYSIZE"), TEXT("Min/Max/Close button height"),
SM_CXSIZEFRAME, TEXT("SM_CXSIZEFRAME"), TEXT("Window sizing frame width"),
SM_CYSIZEFRAME, TEXT("SM_CYSIZEFRAME"), TEXT("Window sizing frame height"),
SM_CXMINTRACK, TEXT("SM_CXMINTRACK"), TEXT("Minimum window tracking width"),
SM_CYMINTRACK, TEXT("SM_CYMINTRACK"), TEXT("Minimum window tracking height"),
SM_CXDOUBLECLK, TEXT("SM_CXDOUBLECLK"), TEXT("Double click x tolerance"),
SM_CYDOUBLECLK, TEXT("SM_CYDOUBLECLK"), TEXT("Double click y tolerance"),
SM_CXICONSPACING, TEXT("SM_CXICONSPACING"), TEXT("Horizontal icon spacing"),
SM_CYICONSPACING, TEXT("SM_CYICONSPACING"), TEXT("Vertical icon spacing"),
SM_MENUDROPALIGNMENT, TEXT("SM_MENUDROPALIGNMENT"), TEXT("Left or right menu drop"),
SM_PENWINDOWS, TEXT("SM_PENWINDOWS"), TEXT("Pen extensions installed"),
SM_DBCSENABLED, TEXT("SM_DBCSENABLED"), TEXT("Double-Byte Char Set enabled"),
SM_CMOUSEBUTTONS, TEXT("SM_CMOUSEBUTTONS"), TEXT("Number of mouse buttons"),
SM_SECURE, TEXT("SM_SECURE"), TEXT("Security present flag"),
SM_CXEDGE, TEXT("SM_CXEDGE"), TEXT("3-D border width"),
SM_CYEDGE, TEXT("SM_CYEDGE"), TEXT("3-D border height"),
SM_CXMINSPACING, TEXT("SM_CXMINSPACING"), TEXT("Minimized window spacing width"),
SM_CYMINSPACING, TEXT("SM_CYMINSPACING"), TEXT("Minimized window spacing height"),
SM_CXSMICON, TEXT("SM_CXSMICON"), TEXT("Small icon width"),
SM_CYSMICON, TEXT("SM_CYSMICON"), TEXT("Small icon height"),
SM_CYSMCAPTION, TEXT("SM_CYSMCAPTION"), TEXT("Small caption height"),
SM_CXSMSIZE, TEXT("SM_CXSMSIZE"), TEXT("Small caption button width"),
SM_CYSMSIZE, TEXT("SM_CYSMSIZE"), TEXT("Small caption button height"),
SM_CXMENUSIZE, TEXT("SM_CXMENUSIZE"), TEXT("Menu bar button width"),
SM_CYMENUSIZE, TEXT("SM_CYMENUSIZE"), TEXT("Menu bar button height"),
SM_ARRANGE, TEXT("SM_ARRANGE"), TEXT("How minimized windows arranged"),
SM_CXMINIMIZED, TEXT("SM_CXMINIMIZED"), TEXT("Minimized window width"),
SM_CYMINIMIZED, TEXT("SM_CYMINIMIZED"), TEXT("Minimized window height"),
SM_CXMAXTRACK, TEXT("SM_CXMAXTRACK"), TEXT("Maximum draggable width"),
SM_CYMAXTRACK, TEXT("SM_CYMAXTRACK"), TEXT("Maximum draggable height"),
SM_CXMAXIMIZED, TEXT("SM_CXMAXIMIZED"), TEXT("Width of maximized window"),
SM_CYMAXIMIZED, TEXT("SM_CYMAXIMIZED"), TEXT("Height of maximized window"),
SM_NETWORK, TEXT("SM_NETWORK"), TEXT("Network present flag"),
SM_CLEANBOOT, TEXT("SM_CLEANBOOT"), TEXT("How system was booted"),
SM_CXDRAG, TEXT("SM_CXDRAG"), TEXT("Avoid drag x tolerance"),
SM_CYDRAG, TEXT("SM_CYDRAG"), TEXT("Avoid drag y tolerance"),
SM_SHOWSOUNDS, TEXT("SM_SHOWSOUNDS"), TEXT("Present sounds visually"),
SM_CXMENUCHECK, TEXT("SM_CXMENUCHECK"), TEXT("Menu check-mark width"),
SM_CYMENUCHECK, TEXT("SM_CYMENUCHECK"), TEXT("Menu check-mark height"),
SM_SLOWMACHINE, TEXT("SM_SLOWMACHINE"), TEXT("Slow processor flag"),
SM_MIDEASTENABLED, TEXT("SM_MIDEASTENABLED"), TEXT("Hebrew and Arabic enabled flag"),
SM_MOUSEWHEELPRESENT, TEXT("SM_MOUSEWHEELPRESENT"), TEXT("Mouse wheel present flag"),
SM_XVIRTUALSCREEN, TEXT("SM_XVIRTUALSCREEN"), TEXT("Virtual screen x origin"),
SM_YVIRTUALSCREEN, TEXT("SM_YVIRTUALSCREEN"), TEXT("Virtual screen y origin"),
SM_CXVIRTUALSCREEN, TEXT("SM_CXVIRTUALSCREEN"), TEXT("Virtual screen width"),
SM_CYVIRTUALSCREEN, TEXT("SM_CYVIRTUALSCREEN"), TEXT("Virtual screen height"),
SM_CMONITORS, TEXT("SM_CMONITORS"), TEXT("Number of monitors"),
SM_SAMEDISPLAYFORMAT, TEXT("SM_SAMEDISPLAYFORMAT"), TEXT("Same color format flag")
};
#endif /*_METICS_H__*/
- ScrollTest.cpp
-
#include "Metrics.h"
LRESULT CALLBACK pfnWndProc(HWND, UINT, WPARAM, LPARAM);
int WINAPI WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
PSTR szCmdLine,
int iCmdShow)
{
MSG stMsg;
memset(&stMsg, 0, sizeof (stMsg));
HWND stHwnd;
memset(&stHwnd, 0, sizeof (stHwnd));
WNDCLASS stWndClass;
memset(&stWndClass, 0, sizeof (stWndClass));
const TCHAR szAppName[] = TEXT("SCROLL TEST");
stWndClass.style = CS_HREDRAW | CS_VREDRAW;
stWndClass.lpfnWndProc = pfnWndProc;
stWndClass.cbClsExtra = 0;
stWndClass.cbWndExtra = 0;
stWndClass.hInstance = hInstance;
stWndClass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
stWndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
stWndClass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
stWndClass.lpszMenuName = NULL;
stWndClass.lpszClassName = szAppName;
if (!RegisterClass(&stWndClass))
{
MessageBox(NULL, TEXT("Regiester failure"), szAppName, MB_ICONERROR);
return 0;
}
stHwnd = CreateWindow(szAppName,
TEXT("SCROLL TEST"),
WS_OVERLAPPEDWINDOW | WS_VSCROLL /*| WS_HSCROLL*/,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
NULL,
NULL,
hInstance,
NULL);
ShowWindow(stHwnd, iCmdShow);
UpdateWindow(stHwnd);
while (GetMessage(&stMsg, NULL, 0, 0))
{
TranslateMessage(&stMsg);
DispatchMessage(&stMsg);
}
return stMsg.wParam;
}
LRESULT CALLBACK pfnWndProc(HWND stHwnd, UINT uiMsg, WPARAM wParam, LPARAM lParam)
{
HDC stHdc;
memset(&stHdc, 0, sizeof (stHdc));
PAINTSTRUCT stPs;
memset(&stPs, 0, sizeof (stPs));
RECT stRect;
memset(&stRect, 0, sizeof (stRect));
TEXTMETRIC stTextMetric;
memset(&stTextMetric, 0, sizeof (stTextMetric));
SCROLLINFO stScrollInfo;
memset(&stScrollInfo, 0, sizeof (stScrollInfo));
int iYpos = 0;
int iSavePos = 0;
static int s_iCharWidth = 0;
static int s_iCharHeight = 0;
static int s_iClientHeight = 0;
static int s_iVScrollPos = 0;
static int s_iCapitalCharWidth = 0;
switch (uiMsg)
{
case WM_CREATE:
stHdc = GetDC(stHwnd);//GDI函式入口
GetTextMetrics(stHdc, &stTextMetric);//獲取系統文字字元結構
s_iCharWidth = stTextMetric.tmAveCharWidth;//字元寬度
s_iCapitalCharWidth = (stTextMetric.tmPitchAndFamily & 1 ? 3 : 2) * s_iCharWidth / 2;//大字字元寬度
s_iCharHeight = stTextMetric.tmHeight + stTextMetric.tmExternalLeading;//字元高度
ReleaseDC(stHwnd, stHdc);
return 0;
case WM_SIZE:
s_iClientHeight = HIWORD(lParam);
stScrollInfo.cbSize = sizeof (stScrollInfo);
stScrollInfo.fMask = SIF_RANGE | SIF_PAGE;
stScrollInfo.nMin = 0;
stScrollInfo.nMax = NUMLINES - 1;
stScrollInfo.nPage = s_iClientHeight / s_iCharHeight;
SetScrollInfo(stHwnd, SB_VERT, &stScrollInfo, TRUE);
return 0;
case WM_VSCROLL:
stScrollInfo.cbSize = sizeof (stScrollInfo);
stScrollInfo.fMask = SIF_ALL;
GetScrollInfo(stHwnd, SB_VERT, &stScrollInfo);//獲取
iSavePos = stScrollInfo.nPos;
switch (LOWORD(wParam))
{
case SB_TOP:
stScrollInfo.nPos = stScrollInfo.nMin;
break;
case SB_BOTTOM:
stScrollInfo.nPos = stScrollInfo.nMax;
break;
case SB_LINEUP:
stScrollInfo.nPos -= 1;
break;
case SB_LINEDOWN:
stScrollInfo.nPos += 1;
break;
case SB_PAGEUP:
stScrollInfo.nPos -= stScrollInfo.nPage;
break;
case SB_PAGEDOWN:
stScrollInfo.nPos += stScrollInfo.nPage;
break;
case SB_THUMBTRACK:
stScrollInfo.nPos = stScrollInfo.nTrackPos;
break;
default:
break;
}
//檢查是否需要更新滑塊位置
if ((iSavePos != stScrollInfo.nPos) && (stScrollInfo.nPos < NUMLINES))
{
stScrollInfo.fMask = SIF_POS;
SetScrollInfo(stHwnd, SB_VERT, &stScrollInfo, TRUE);
InvalidateRect(stHwnd, NULL, TRUE);
UpdateWindow(stHwnd);
}
return 0;
case WM_PAINT:
stHdc = BeginPaint(stHwnd, &stPs);
stScrollInfo.cbSize = sizeof (stScrollInfo);
stScrollInfo.fMask = SIF_POS;
GetScrollInfo(stHwnd, SB_VERT, &stScrollInfo);
iSavePos = stScrollInfo.nPos;
for (int iNum = 0; iNum < NUMLINES; iNum++)
{
iYpos = s_iCharHeight * (iNum - iSavePos);
TextOut(stHdc, 0, iYpos, sysmetrics[iNum].szLabel, lstrlen(sysmetrics[iNum].szLabel));
TextOut(stHdc, 40 * s_iCapitalCharWidth, iYpos, sysmetrics[iNum].szDesc, lstrlen(sysmetrics[iNum].szDesc));
}
EndPaint(stHwnd, &stPs);
return 0;
case WM_DESTROY:
PostQuitMessage(0);
return 0;
default:
return DefWindowProc(stHwnd, uiMsg, wParam, lParam);
}
}