C “第四个参数”之谜;“滚动窗口”;Windows编程中的API函数

C “第四个参数”之谜;“滚动窗口”;Windows编程中的API函数,c,windows,winapi,C,Windows,Winapi,我的代码如下所示。当程序运行时,我先单击鼠标右键,然后单击鼠标左键。结果如第一张图所示。根据ScrollWindow函数的帮助文档,如果第四个参数为NULL,则应滚动整个客户端区域。为什么x=30个设备单元时有10个像素的间隙 我想知道为什么结果不像第二张图那样显示 #包括 LRESULT回调WndProc(HWND、UINT、WPARAM、LPARAM); int WINAPI WinMain(HINSTANCE HINSTANCE、HINSTANCE HPPreInstance、, PS

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

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

#包括
LRESULT回调WndProc(HWND、UINT、WPARAM、LPARAM);
int WINAPI WinMain(HINSTANCE HINSTANCE、HINSTANCE HPPreInstance、,
PSTR szCmdLine,int iCmdShow)
{
静态TCHAR szAppName[]=文本(“HelloWin”);
HWND-HWND;
味精;
WNDCLASS WNDCLASS;
wndclass.style=CS_HREDRAW | CS_VREDRAW;
wndclass.lpfnWndProc=WndProc;
wndclass.cbClsExtra=0;
wndclass.cbWndExtra=0;
wndclass.hInstance=hInstance;
wndclass.hIcon=LoadIcon(空,IDI_应用程序);
wndclass.hCursor=LoadCursor(空,IDC_箭头);
wndclass.hbrBackground=(HBRUSH)GetStockObject(白色画笔);
wndclass.lpszMenuName=NULL;
wndclass.lpszClassName=szAppName;
if(!RegisterClass(&wndclass))
{
MessageBox(空,文本(“此程序需要Windows NT!”),
szAppName,MB_i错误);
返回0;
}
hwnd=CreateWindow(szAppName,//窗口类名称
文本(“Hello程序”),//窗口标题
WS\u重叠窗口,//窗口样式
CW_USEDEFAULT,//初始x位置
CW\U USEFAULT,//初始y位置
CW\u usefault,//初始x大小
CW\u usefault,//初始y大小
NULL,//父窗口句柄
NULL,//窗口菜单句柄
hInstance,//程序实例句柄
NULL);//创建参数
显示窗口(hwnd、iCmdShow);
更新窗口(hwnd);
while(GetMessage(&msg,NULL,0,0))
{
翻译信息(&msg);
发送消息(&msg);
}
返回msg.wParam;
}
LRESULT回调WndProc(HWND HWND,UINT消息,WPARAM WPARAM,LPARAM LPARAM)
{
HDC-HDC;
PAINTSTRUCT-ps;
RECT-RECT;
开关(信息)
{          
案例WM_油漆:
hdc=开始喷漆(hwnd和ps);
端漆(hwnd和ps);
返回0;
案例WM_LBUTTONDOWN:
hdc=GetDC(hwnd);
SetRect(&rect,30,0,70,100);
滚动窗口(hwnd、10、0、NULL和rect);
更新窗口(hwnd);
释放DC(hwnd、hdc);
返回0;
案例WM_RBUTTONDOWN:
hdc=GetDC(hwnd);
椭圆(hdc,0,0,100,100);
释放DC(hwnd、hdc);
返回0;
案例WM_销毁:
PostQuitMessage(0);
返回0;
}
返回DefWindowProc(hwnd、message、wParam、lParam);
}
如果第四个参数为NULL,则应滚动整个客户端区域

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

为什么x=30个设备单元时有10个像素的间隙

因为当Windows告诉您这样做时,您不会绘制该间隙

发件人:

ScrollWindow未覆盖的区域不会重新绘制,但会合并到窗口的更新区域中。应用程序最终会收到一条WM_PAINT消息,通知它必须重新绘制该区域

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

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


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

请提供有关您输入的更多详细信息。你点击一个按钮,即你按下它,在按下时不移动它,然后释放它?然后另一个按钮也一样?你不是在
WM_PAINT
中画画,所以你在屏幕上看到垃圾是正常的。你得到的特定类型的垃圾不是特别有趣。这是常见的绘画代码损坏的情况。右击只会将像素飞溅到窗口上,它们不会存活很长时间。通过将窗口部分拖离屏幕或最小化并恢复窗口,最容易看到。在屏幕截图中可见,ScrollWindow无法将像素移到剪辑矩形之外,并且它生成的后续绘制也不会绘制像素。根据您的回答,我还有两个问题。@user7028什么问题?根据您的回答,我还有两个问题。1.因为第四个参数不起作用。第四个参数存在的必要性是什么?2.您说“来自MSDN:ScrollWindow未覆盖的区域不会重新绘制,但会合并到窗口的更新区域中。应用程序最终会收到WM_PAINT消息,通知它必须重新绘制该区域。”我想知道是否“ScrollWindow未覆盖的区域”
#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) ;
}