c - Windows编程中关于 "ScrollWindow"API函数第四个参数的困惑

标签 c windows winapi

我的代码如下所示。当程序运行时,我先单击鼠标右键,然后单击鼠标左键。结果如第一张图所示。根据ScrollWindow函数的帮助文档,如果第四个参数为NULL,则整个客户区都应该滚动。为什么 x = 30 设备单位处有 10 像素间隙?

Actual result

我想知道为什么结果不像第二张图那样显示。

Expected result

#include <windows.h>

LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;

int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
                    PSTR szCmdLine, int iCmdShow)
{

    static TCHAR szAppName[] = TEXT ("HelloWin") ;
    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  = NULL ;
    wndclass.lpszClassName = szAppName ;

    if (!RegisterClass (&wndclass))
    {
        MessageBox (NULL, TEXT ("This program requires Windows NT!"), 
                    szAppName, MB_ICONERROR) ;
        return 0 ;
    }

    hwnd = CreateWindow (szAppName,                  // window class name
                         TEXT ("The Hello Program"), // window caption
                         WS_OVERLAPPEDWINDOW,        // window style
                         CW_USEDEFAULT,              // initial x position
                         CW_USEDEFAULT,              // initial y position
                         CW_USEDEFAULT,              // initial x size
                         CW_USEDEFAULT,              // initial y size
                         NULL,                       // parent window handle
                         NULL,                       // window menu handle
                         hInstance,                  // program instance handle
                         NULL) ;                     // creation parameters

    ShowWindow (hwnd, iCmdShow) ;
    UpdateWindow (hwnd) ;

    while (GetMessage (&msg, NULL, 0, 0))
    {
        TranslateMessage (&msg) ;
        DispatchMessage (&msg) ;
    }
    return msg.wParam ;
}

LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    HDC         hdc ;
    PAINTSTRUCT ps ;
    RECT rect;

    switch (message)
    {          
        case WM_PAINT:
            hdc = BeginPaint (hwnd, &ps) ;
            EndPaint (hwnd, &ps) ;
            return 0 ;

        case WM_LBUTTONDOWN:
            hdc = GetDC(hwnd);
            SetRect(&rect, 30, 0, 70, 100);
            ScrollWindow(hwnd, 10, 0, NULL, &rect);
            UpdateWindow(hwnd);
            ReleaseDC(hwnd, hdc);
            return 0;

        case WM_RBUTTONDOWN:
            hdc = GetDC(hwnd);
            Ellipse(hdc, 0, 0, 100, 100);
            ReleaseDC(hwnd, hdc);
            return 0;

        case WM_DESTROY:
            PostQuitMessage (0) ;
            return 0 ;
    }
    return DefWindowProc (hwnd, message, wParam, lParam) ;
}

最佳答案

if the fourth parameter is NULL, the entire client area should be scrolled.

您还指定了一个剪切矩形(第5个参数),因此当然不会滚动整个客户区域。但实际上这与问题无关。

Why is there a 10 pixels gap at x = 30 device units?

因为当 Windows 要求您这样做时,您没有绘制该间隙。

来自MSDN :

The area uncovered by ScrollWindow is not repainted, but it is combined into the window's update region. The application eventually receives a WM_PAINT message notifying it that the region must be repainted.

您的 WM_PAINT 处理程序除了通过验证更新区域向 Windows 撒谎之外什么也不做。

通过仅在 WM_PAINT 中进行所有绘制来修复您的代码。当您在 WM_LBUTTONDOWN 中滚动时,您还必须增加一个存储滚动位置的变量。将滚动位置添加到您传递给 WM_PAINT 中的 Ellipse() 的坐标。现在你应该得到像第二张图这样的结果。

我建议找到一个关于 Win32 绘画的好教程,因为这里似乎缺少一些基本知识。了解什么是“更新区域”以及它如何与绘制周期交互。

关于c - Windows编程中关于 "ScrollWindow"API函数第四个参数的困惑,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46020902/

相关文章:

windows - 交互式命令提示符字符转义%

windows - 将 PowerShell 转换为 Bash

windows - FindWindow 收到的句柄是否需要释放?

c - 线程未按预期工作

c - 将 char 附加到没有值的字符串

c - 当我将二维数组读取为一维数组时,显示的是什么?

c - Lex:如何防止它与子字符串匹配?

c# - 窗口最小化后不恢复

c++ - 使用 IOCP 时 OVERLAPPED 结构的用途是什么?

CreateProcess() 因访问冲突而失败