兰陵月 发表于 2018-4-8 22:45:07

滚屏时客户区“无效区域”问题!!

滚屏时,Windows肯定是要发送WM_PAINT消息的,因为整个客户区都要刷新嘛!再根据《琢石成器》书中第196页倒数第一段的内容:
。。。Windows仅仅根据是否存在“无效区域”来决定是否发送WM_PAINT消息,。。。

我想请问,滚屏时,“无效区域”是否就是整个客户区?

同时又请教,最小化变到最大化时,“无效区域”是整个屏幕吗?
窗口由小被大,或者由大变小,“无效区域”又是什么?

人造人 发表于 2018-4-9 03:19:26

http://tieba.baidu.com/p/2035403150


我百度了无效区域
找到了GetUpdateRect,这个函数
https://baike.so.com/doc/4371911-4577831.html


也就是说BeginPaint和GetUpdateRect都能得到无效区域
之后的实验也证明了的确是这样

代码
/* -------------------------------------------------------------------
MyWindows.c -- 基本窗口模型
--------------------------------------------------------------------*/

#include <windows.h>

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

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
{
        static TCHAR szClassName[] = TEXT("MyClass");
        static TCHAR szAppName[] = TEXT("MyWindows");

        HWND hWnd;
        MSG uMsg;
        WNDCLASS stWndClass;

        stWndClass.style = CS_HREDRAW | CS_VREDRAW;
        stWndClass.lpfnWndProc = WndProc;
        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 = szClassName;
        RegisterClass(&stWndClass);

        hWnd = CreateWindow(szClassName, szAppName, WS_OVERLAPPEDWINDOW,
                CW_USEDEFAULT, CW_USEDEFAULT, 640, 480,
                NULL, NULL, hInstance, NULL);

        ShowWindow(hWnd, nShowCmd);
        UpdateWindow(hWnd);

        while(GetMessage(&uMsg, NULL, 0, 0))
        {
                TranslateMessage(&uMsg);
                DispatchMessage(&uMsg);
        }

        return uMsg.wParam;
}

LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
        HDC hDc;
        PAINTSTRUCT stPs;
        RECT stRect;

        switch(uMsg)
        {
        case WM_PAINT:
                GetUpdateRect(hWnd, &stRect, FALSE);
               
                hDc = BeginPaint(hWnd, &stPs);
                EndPaint(hWnd, &stPs);
                return 0;

        case WM_DESTROY:
                DestroyWindow(hWnd);
                PostQuitMessage(0);
                return 0;
        }

        return DefWindowProc(hWnd, uMsg, wParam, lParam);
}


在EndPaint(hWnd, &stPs);下断点,然后运行
程序直接停在了EndPaint(hWnd, &stPs);



我创建窗口时
hWnd = CreateWindow(szClassName, szAppName, WS_OVERLAPPEDWINDOW,
                CW_USEDEFAULT, CW_USEDEFAULT, 640, 480,
                NULL, NULL, hInstance, NULL);
窗口大小是640X480,这里的无效区域是624X441,这里得到的是客户区域的无效区域,非客户区域不在这里


我点“继续”,程序就跑起来了,不管是移动这个窗口也好,还是拿其他窗口遮住这个窗口再移开也好,程序一直跑着,没有中断
我点这个窗口的最小化按钮,程序依然跑着,没有中断
当我从任务栏点了一下这个程序,把他还原时,程序中断了,下面是截图


点“继续”,程序继续运行
点最大化按钮,程序中断

现在的无效区域是1920X1017

点“继续”,程序继续运行
点还原按钮,程序中断


点“继续”,程序继续运行
往大拖窗口,程序立刻中断,我无法控制大小,只要一拖,程序立刻中断


继续运行,往小拖


继续运行,我使劲往右拖


就到这吧,还少一种情况
少了滚屏时的情况
这个交给你了
^_^

人造人 发表于 2018-4-9 03:32:18

当我把窗口移出屏幕外时,没有中断,继续往外移,仍然没有中断,当我把窗口拉回来时中断了


2X441


继续运行,继续往回拉,又中断


一直运行,一直往回拉,一直中断
我要如何才能把窗口拉回来?(在不禁用断点的情况下)
算了,不拉了,直接停止调试,窗口直接关闭了

人造人 发表于 2018-4-9 03:49:51

换一个方法

/* -------------------------------------------------------------------
MyWindows.c -- 基本窗口模型
--------------------------------------------------------------------*/

#include <windows.h>

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

HANDLE hStdin;
HANDLE hStdout;

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
{
        static TCHAR szClassName[] = TEXT("MyClass");
        static TCHAR szAppName[] = TEXT("MyWindows");

        HWND hWnd;
        MSG uMsg;
        WNDCLASS stWndClass;



        AllocConsole();
        hStdin = GetStdHandle(STD_INPUT_HANDLE);
        hStdout = GetStdHandle(STD_OUTPUT_HANDLE);




        stWndClass.style = CS_HREDRAW | CS_VREDRAW;
        stWndClass.lpfnWndProc = WndProc;
        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 = szClassName;
        RegisterClass(&stWndClass);

        hWnd = CreateWindow(szClassName, szAppName, WS_OVERLAPPEDWINDOW,
                CW_USEDEFAULT, CW_USEDEFAULT, 640, 480,
                NULL, NULL, hInstance, NULL);

        ShowWindow(hWnd, nShowCmd);
        UpdateWindow(hWnd);

        while(GetMessage(&uMsg, NULL, 0, 0))
        {
                TranslateMessage(&uMsg);
                DispatchMessage(&uMsg);
        }

        return uMsg.wParam;
}

LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
        HDC hDc;
        PAINTSTRUCT stPs;
        RECT stRect;
        char buf;
        DWORD length;

        switch(uMsg)
        {
        case WM_PAINT:
                GetUpdateRect(hWnd, &stRect, FALSE);
               
                hDc = BeginPaint(hWnd, &stPs);

               
                wsprintf(buf, "GetUpdateRect:\t(left:%d)(top:%d)(right:%d)(bottom:%d)\n", stRect.left, stRect.top, stRect.right, stRect.bottom);
                length = strlen(buf);
                WriteFile(hStdout, buf, length, &length, 0);


                wsprintf(buf, "BeginPaint:\t(left:%d)(top:%d)(right:%d)(bottom:%d)\n", stPs.rcPaint.left, stPs.rcPaint.top, stPs.rcPaint.right, stPs.rcPaint.bottom);
                length = strlen(buf);
                WriteFile(hStdout, buf, length, &length, 0);

               
                EndPaint(hWnd, &stPs);
                return 0;

        case WM_DESTROY:
                DestroyWindow(hWnd);
                PostQuitMessage(0);
                return 0;
        }

        return DefWindowProc(hWnd, uMsg, wParam, lParam);
}

兰陵月 发表于 2018-4-9 08:23:33

C的知识还是20年前大学学的,现在不熟悉了。

不过基本还是看懂了。看来滚屏时无效区域就是整个客户区了。
页: [1]
查看完整版本: 滚屏时客户区“无效区域”问题!!