I am reading Mr. Petzold's book, trying to make a note pad. When the caret comes to the last line of the client area and press the Enter key, I need to set the range of the scroll bar(adding 1 to the nMax
), but I found that if I set the range of the scroll bar by SetScrollInfo
, always failed, the range never be changed, unless I use the ShowScrollBar
before SetScrollInfo
.
Here is the minimum codes that can reproduce the failure.
#include <Windows.h>
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
int wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PWSTR cmdLine, int cmdShow)
{
PCWSTR szAppName = L"notepad";
WNDCLASSEXW wndClass;
ZeroMemory(&wndClass, sizeof(WNDCLASSEX));
wndClass.cbSize = sizeof(WNDCLASSEX);
wndClass.style = CS_HREDRAW | CS_VREDRAW;
wndClass.cbClsExtra = 0;
wndClass.cbWndExtra = 0;
wndClass.lpfnWndProc = WndProc;
wndClass.hInstance = hInstance;
wndClass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
wndClass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
wndClass.lpszMenuName = NULL;
wndClass.lpszClassName = szAppName;
wndClass.hIconSm = NULL;
if (!RegisterClassExW(&wndClass))
{
MessageBoxW(NULL, L"Failed to register window class.", L"Message", 0);
return 0;
}
HWND hWnd = CreateWindowExW(
WS_EX_APPWINDOW,
szAppName,
TEXT("Note Pad"),
WS_OVERLAPPEDWINDOW | WS_VSCROLL,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
NULL,
NULL,
hInstance,
NULL);
if (hWnd == NULL)
{
MessageBoxW(NULL, L"Failed to create this window.", L"Message", 0);
return 0;
}
ShowWindow(hWnd, cmdShow);
UpdateWindow(hWnd);
MSG msg;
while (GetMessageW(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessageW(&msg);
}
return 0;
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
static DWORD charset = DEFAULT_CHARSET;
static int charWidth, lineHeight;
static int clientWidth, clientHeight;
switch (message)
{
case WM_CREATE:
{
HDC hdc = GetDC(hWnd);
SelectObject(
hdc,
CreateFontW(0, 0, 0, 0, 0, 0, 0, 0, charset, 0, 0, 0, FIXED_PITCH, 0));
TEXTMETRICW tm;
GetTextMetricsW(hdc, &tm);
charWidth = tm.tmAveCharWidth;
lineHeight = tm.tmHeight + tm.tmExternalLeading;
DeleteObject(SelectObject(hdc, GetStockObject(SYSTEM_FONT)));
ReleaseDC(hWnd, hdc);
return 0;
}
case WM_SIZE:
{
clientWidth = LOWORD(lParam);
clientHeight = HIWORD(lParam);
SCROLLINFO si;
si.cbSize = sizeof(si);
si.fMask = SIF_RANGE | SIF_PAGE;
si.nMin = 0;
si.nMax = clientHeight / lineHeight - 1;
si.nPage = clientHeight / lineHeight;
SetScrollInfo(hWnd, SB_VERT, &si, TRUE);
return 0;
}
case WM_CHAR:
{
switch (wParam)
{
case L'\r':
{
SCROLLINFO si;
si.cbSize = sizeof(si);
si.fMask = SIF_RANGE;
GetScrollInfo(hWnd, SB_VERT, &si);
si.nMax++;
// ShowScrollBar(hWnd, SB_VERT, TRUE);
SetScrollInfo(hWnd, SB_VERT, &si, TRUE);
break;
}
}
return 0;
}
case WM_DESTROY:
PostQuitMessage(0);
return 0;
}
return DefWindowProcW(hWnd, message, wParam, lParam);
}
In the code, when the window pops up, the scroll bar doesn't show because of PageSize == nMax - nMin + 1
, page size can include the range. But when setting the nMax
to nMax++
, the page size cannot include the range, the scrollbar should show at the right side of the window. But it didn't, I cannot change the range!
By the section of Scroll Bar Visibility of About Scroll Bar, to change the range of a scrollbar, I shouldn't have called ShowScrollBar
before SetScrollInfo
.