2000 #include #include #define LINES 27 static char *abc[] = { "anteater", "bear", "cougar", "dingo", "elephant", "frog", "gazelle", "hyena", "iguana", "jackal", "kangaroo", "llama", "moose", "newt", "octopus", "penguin", "quail", "rat", "squid", "tortoise", "urus", "vole", "walrus", "xylophone", "yak", "zebra", "This line contains many words, but no character. Go figure." }; LRESULT CALLBACK MainWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam ) { HDC hdc; PAINTSTRUCT ps; TEXTMETRIC tm; SCROLLINFO si; /* These variables are required to display text. */ static int xClient; /* width of client area */ static int yClient; /* height of client area */ static int xClientMax; /* maximum width of client area */ static int xChar; /* horizontal scrolling unit */ static int yChar; /* vertical scrolling unit */ static int xUpper; /* average width of uppercase letters */ static int xPos; /* current horizontal scrolling position */ static int yPos; /* current vertical scrolling position */ static int xMax; /* maximum horiz. scrolling position */ static int yMax; /* maximum vert. scrolling position */ int xInc; /* horizontal scrolling increment */ int yInc; /* vertical scrolling increment */ int i; /* loop counter */ int x, y; /* horiz. and vert. printing coords */ int FirstLine; /* first line in the invalidated area */ int LastLine; /* last line in the invalidated area */ RECT rect; switch (msg) { case WM_CREATE : /* Get the handle of the client area's device context. */ hdc = GetDC (hwnd); /* Extract font dimensions from the text metrics. */ GetTextMetrics (hdc, &tm); xChar = tm.tmAveCharWidth; xUpper = (tm.tmPitchAndFamily & 1 ? 3 : 2) * xChar/2; yChar = tm.tmHeight + tm.tmExternalLeading; /* Free the device context. */ ReleaseDC (hwnd, hdc); /* * Set an arbitrary maximum width for client area. * (xClientMax is the sum of the widths of 48 average * lowercase letters and 12 uppercase letters.) */ xClientMax = 48 * xChar + 12 * xUpper; return 0; case WM_SIZE: /* Retrieve the dimensions of the client area. */ yClient = HIWORD (lParam); xClient = LOWORD (lParam); /* * Determine the maximum vertical scrolling position. * The two is added for extra space below the lines * of text. */ yMax = max (0, LINES + 2 - yClient/yChar); /* * Make sure the current vertical scrolling position * does not exceed the maximum. */ yPos = min(yPos, yMax); /* * Adjust the vertical scrolling range and scroll box * position to reflect the new yMax and yPos values. */ si.cbSize = sizeof(si); si.fMask = SIF_RANGE | SIF_PAGE | SIF_POS; si.nMin = 0; si.nMax = yMax; si.nPage = yClient / yChar; si.nPos = yPos; SetScrollInfo(hwnd, SB_VERT, &si, TRUE); /* * Determine the maximum horizontal scrolling position. * The two is added for extra space to the right of the * lines of text. */ xMax = max (0, 2 + (xClientMax - xClient)/xChar); /* * Make sure the current horizontal scrolling position * does not exceed the maximum. */ xPos = min (xPos, xMax); /* * Adjust the horizontal scrolling range and scroll box * position to reflect the new xMax and xPos values. */ si.cbSize = sizeof(si); si.fMask = SIF_RANGE | SIF_PAGE | SIF_POS; si.nMin = 0; si.nMax = xMax; si.nPage = xClient / xChar; si.nPos = xPos; SetScrollInfo(hwnd, SB_HORZ, &si, TRUE); return 0; case WM_PAINT: /* Prepare the window for painting. */ hdc = BeginPaint(hwnd, &ps); (void) GetClientRect(hwnd, &rect); FillRect(hdc, &rect, GetStockObject(LTGRAY_BRUSH)); /* * Use the current vertical scrolling position and * coordinates of the invalid rectangle to determine * the range of new lines that should be drawn in the * client area. */ FirstLine = max (0, yPos + ps.rcPaint.top/yChar - 1); LastLine = min (LINES, yPos + ps.rcPaint.bottom/yChar); /* Display these lines. */ for (i = FirstLine;i < LastLine;i++) { x = xChar * (1 - xPos); y = yChar * (1 - yPos + i); TextOut (hdc, x, y, abc[i], lstrlen(abc[i])); } /* Indicate that painting is finished. */ EndPaint(hwnd, &ps); break; case WM_HSCROLL: switch(LOWORD (wParam)) { /* User clicked shaft left of the scroll box. */ case SB_PAGEUP: xInc = -8; break; /* User clicked shaft right of the scroll box. */ case SB_PAGEDOWN: xInc = 8; break; /* User clicked the left arrow. */ case SB_LINEUP: xInc = -1; break; /* User clicked the right arrow. */ case SB_LINEDOWN: xInc = 1; break; /* User dragged the scroll box. */ case SB_THUMBTRACK: xInc = HIWORD(wParam) - xPos; break; default: xInc = 0; } /* * If applying the horizontal scrolling increment does not * take the scrolling position out of the scrolling range, * increment the scrolling position, adjust the position * of the scroll box, and update the window. */ if (xInc = max (-xPos, min (xInc, xMax - xPos))) { xPos += xInc; ScrollWindowEx (hwnd, -xChar * xInc, 0, (CONST RECT *) NULL, (CONST RECT *) NULL, (HRGN) NULL, (LPRECT) NULL, SW_INVALIDATE); si.cbSize = sizeof(si); si.fMask = SIF_POS; si.nPos = xPos; SetScrollInfo(hwnd, SB_HORZ, &si, TRUE); UpdateWindow (hwnd); } return 0; case WM_VSCROLL: switch(LOWORD (wParam)) { /* User clicked the shaft above the scroll box. */ case SB_PAGEUP: yInc = min(-1, -yClient / yChar); break; /* User clicked the shaft below the scroll box. */ case SB_PAGEDOWN: yInc = max(1, yClient / yChar); break; /* User clicked the top arrow. */ case SB_LINEUP: yInc = -1; break; /* User clicked the bottom arrow. */ case SB_LINEDOWN: yInc = 1; break; /* User dragged the scroll box. */ case SB_THUMBTRACK: yInc = HIWORD(wParam) - yPos; break; default: yInc = 0; } /* * If applying the vertical scrolling increment does not * take the scrolling position out of the scrolling range, * increment the scrolling position, adjust the position * of the scroll box, and update the window. UpdateWindow * sends the WM_PAINT message. */ if (yInc = max(-yPos, min(yInc, yMax - yPos))) { yPos += yInc; ScrollWindowEx(hwnd, 0, -yChar * yInc, (CONST RECT *) NULL, (CONST RECT *) NULL, (HRGN) NULL, (LPRECT) NULL, SW_INVALIDATE); si.cbSize = sizeof(si); si.fMask = SIF_POS; si.nPos = yPos; SetScrollInfo(hwnd, SB_VERT, &si, TRUE); UpdateWindow (hwnd); } return 0; case WM_DESTROY: PostQuitMessage( 0 ); break; default: return(DefWindowProc(hwnd, msg, wParam, lParam)); } return 0; } int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { WNDCLASS wc; MSG msg; HWND hwnd; if(! hPrevInstance) { memset(&wc,0,sizeof(WNDCLASS)); wc.lpszC 31d lassName = "MyAppClass"; wc.lpfnWndProc = MainWndProc; wc.style = CS_VREDRAW | CS_HREDRAW; wc.hInstance = hInstance; wc.hIcon = LoadIcon(NULL, IDI_APPLICATION ); wc.hCursor = LoadCursor(NULL, IDC_ARROW ); wc.hbrBackground = (HBRUSH)(COLOR_WINDOW); wc.lpszMenuName = NULL; wc.cbClsExtra = 0; wc.cbWndExtra = 0; RegisterClass(&wc); } hwnd = CreateWindowEx( 0L, "MyAppClass", "Scroll Bar Application", WS_OVERLAPPEDWINDOW | WS_HSCROLL | WS_VSCROLL, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, (HWND)NULL, (HMENU)NULL, hInstance, (LPVOID)NULL ); ShowWindow(hwnd, nCmdShow); while (GetMessage(&msg, NULL, 0, 0 )) { TranslateMessage(&msg); DispatchMessage(&msg); } return msg.wParam; } . 0