鱼C论坛

 找回密码
 立即注册
查看: 2481|回复: 4

[已解决]滚屏时客户区“无效区域”问题!!

[复制链接]
发表于 2018-4-8 22:45:07 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

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

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

同时又请教,最小化变到最大化时,“无效区域”是整个屏幕吗?
窗口由小被大,或者由大变小,“无效区域”又是什么?
最佳答案
2018-4-9 03:19:26
http://tieba.baidu.com/p/2035403150
无标题.png

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

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

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

  4. #include <windows.h>

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

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

  10.         HWND hWnd;
  11.         MSG uMsg;
  12.         WNDCLASS stWndClass;

  13.         stWndClass.style = CS_HREDRAW | CS_VREDRAW;
  14.         stWndClass.lpfnWndProc = WndProc;
  15.         stWndClass.cbClsExtra = 0;
  16.         stWndClass.cbWndExtra = 0;
  17.         stWndClass.hInstance = hInstance;
  18.         stWndClass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
  19.         stWndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
  20.         stWndClass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
  21.         stWndClass.lpszMenuName = NULL;
  22.         stWndClass.lpszClassName = szClassName;
  23.         RegisterClass(&stWndClass);

  24.         hWnd = CreateWindow(szClassName, szAppName, WS_OVERLAPPEDWINDOW,
  25.                 CW_USEDEFAULT, CW_USEDEFAULT, 640, 480,
  26.                 NULL, NULL, hInstance, NULL);

  27.         ShowWindow(hWnd, nShowCmd);
  28.         UpdateWindow(hWnd);

  29.         while(GetMessage(&uMsg, NULL, 0, 0))
  30.         {
  31.                 TranslateMessage(&uMsg);
  32.                 DispatchMessage(&uMsg);
  33.         }

  34.         return uMsg.wParam;
  35. }

  36. LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  37. {
  38.         HDC hDc;
  39.         PAINTSTRUCT stPs;
  40.         RECT stRect;

  41.         switch(uMsg)
  42.         {
  43.         case WM_PAINT:
  44.                 GetUpdateRect(hWnd, &stRect, FALSE);
  45.                
  46.                 hDc = BeginPaint(hWnd, &stPs);
  47.                 EndPaint(hWnd, &stPs);
  48.                 return 0;

  49.         case WM_DESTROY:
  50.                 DestroyWindow(hWnd);
  51.                 PostQuitMessage(0);
  52.                 return 0;
  53.         }

  54.         return DefWindowProc(hWnd, uMsg, wParam, lParam);
  55. }
复制代码


在EndPaint(hWnd, &stPs);下断点,然后运行
程序直接停在了EndPaint(hWnd, &stPs);
无标题2.png
无标题3.png

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


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

点“继续”,程序继续运行
点最大化按钮,程序中断
无标题5.png
现在的无效区域是1920X1017

点“继续”,程序继续运行
点还原按钮,程序中断
无标题6.png

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

继续运行,往小拖
无标题8.png

继续运行,我使劲往右拖
无标题9.png

就到这吧,还少一种情况
少了滚屏时的情况
这个交给你了
^_^
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2018-4-9 03:19:26 | 显示全部楼层    本楼为最佳答案   
http://tieba.baidu.com/p/2035403150
无标题.png

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

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

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

  4. #include <windows.h>

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

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

  10.         HWND hWnd;
  11.         MSG uMsg;
  12.         WNDCLASS stWndClass;

  13.         stWndClass.style = CS_HREDRAW | CS_VREDRAW;
  14.         stWndClass.lpfnWndProc = WndProc;
  15.         stWndClass.cbClsExtra = 0;
  16.         stWndClass.cbWndExtra = 0;
  17.         stWndClass.hInstance = hInstance;
  18.         stWndClass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
  19.         stWndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
  20.         stWndClass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
  21.         stWndClass.lpszMenuName = NULL;
  22.         stWndClass.lpszClassName = szClassName;
  23.         RegisterClass(&stWndClass);

  24.         hWnd = CreateWindow(szClassName, szAppName, WS_OVERLAPPEDWINDOW,
  25.                 CW_USEDEFAULT, CW_USEDEFAULT, 640, 480,
  26.                 NULL, NULL, hInstance, NULL);

  27.         ShowWindow(hWnd, nShowCmd);
  28.         UpdateWindow(hWnd);

  29.         while(GetMessage(&uMsg, NULL, 0, 0))
  30.         {
  31.                 TranslateMessage(&uMsg);
  32.                 DispatchMessage(&uMsg);
  33.         }

  34.         return uMsg.wParam;
  35. }

  36. LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  37. {
  38.         HDC hDc;
  39.         PAINTSTRUCT stPs;
  40.         RECT stRect;

  41.         switch(uMsg)
  42.         {
  43.         case WM_PAINT:
  44.                 GetUpdateRect(hWnd, &stRect, FALSE);
  45.                
  46.                 hDc = BeginPaint(hWnd, &stPs);
  47.                 EndPaint(hWnd, &stPs);
  48.                 return 0;

  49.         case WM_DESTROY:
  50.                 DestroyWindow(hWnd);
  51.                 PostQuitMessage(0);
  52.                 return 0;
  53.         }

  54.         return DefWindowProc(hWnd, uMsg, wParam, lParam);
  55. }
复制代码


在EndPaint(hWnd, &stPs);下断点,然后运行
程序直接停在了EndPaint(hWnd, &stPs);
无标题2.png
无标题3.png

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


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

点“继续”,程序继续运行
点最大化按钮,程序中断
无标题5.png
现在的无效区域是1920X1017

点“继续”,程序继续运行
点还原按钮,程序中断
无标题6.png

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

继续运行,往小拖
无标题8.png

继续运行,我使劲往右拖
无标题9.png

就到这吧,还少一种情况
少了滚屏时的情况
这个交给你了
^_^
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2018-4-9 03:32:18 | 显示全部楼层
当我把窗口移出屏幕外时,没有中断,继续往外移,仍然没有中断,当我把窗口拉回来时中断了
无标题10.png

2X441


继续运行,继续往回拉,又中断
无标题11.png

一直运行,一直往回拉,一直中断
我要如何才能把窗口拉回来?(在不禁用断点的情况下)
算了,不拉了,直接停止调试,窗口直接关闭了
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2018-4-9 03:49:51 | 显示全部楼层
换一个方法

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

  4. #include <windows.h>

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

  6. HANDLE hStdin;
  7. HANDLE hStdout;

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

  12.         HWND hWnd;
  13.         MSG uMsg;
  14.         WNDCLASS stWndClass;



  15.         AllocConsole();
  16.         hStdin = GetStdHandle(STD_INPUT_HANDLE);
  17.         hStdout = GetStdHandle(STD_OUTPUT_HANDLE);




  18.         stWndClass.style = CS_HREDRAW | CS_VREDRAW;
  19.         stWndClass.lpfnWndProc = WndProc;
  20.         stWndClass.cbClsExtra = 0;
  21.         stWndClass.cbWndExtra = 0;
  22.         stWndClass.hInstance = hInstance;
  23.         stWndClass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
  24.         stWndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
  25.         stWndClass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
  26.         stWndClass.lpszMenuName = NULL;
  27.         stWndClass.lpszClassName = szClassName;
  28.         RegisterClass(&stWndClass);

  29.         hWnd = CreateWindow(szClassName, szAppName, WS_OVERLAPPEDWINDOW,
  30.                 CW_USEDEFAULT, CW_USEDEFAULT, 640, 480,
  31.                 NULL, NULL, hInstance, NULL);

  32.         ShowWindow(hWnd, nShowCmd);
  33.         UpdateWindow(hWnd);

  34.         while(GetMessage(&uMsg, NULL, 0, 0))
  35.         {
  36.                 TranslateMessage(&uMsg);
  37.                 DispatchMessage(&uMsg);
  38.         }

  39.         return uMsg.wParam;
  40. }

  41. LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  42. {
  43.         HDC hDc;
  44.         PAINTSTRUCT stPs;
  45.         RECT stRect;
  46.         char buf[1024];
  47.         DWORD length;

  48.         switch(uMsg)
  49.         {
  50.         case WM_PAINT:
  51.                 GetUpdateRect(hWnd, &stRect, FALSE);
  52.                
  53.                 hDc = BeginPaint(hWnd, &stPs);

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


  58.                 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);
  59.                 length = strlen(buf);
  60.                 WriteFile(hStdout, buf, length, &length, 0);

  61.                
  62.                 EndPaint(hWnd, &stPs);
  63.                 return 0;

  64.         case WM_DESTROY:
  65.                 DestroyWindow(hWnd);
  66.                 PostQuitMessage(0);
  67.                 return 0;
  68.         }

  69.         return DefWindowProc(hWnd, uMsg, wParam, lParam);
  70. }
复制代码
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2018-4-9 08:23:33 | 显示全部楼层
C的知识还是20年前大学学的,现在不熟悉了。

不过基本还是看懂了。看来滚屏时无效区域就是整个客户区了。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-4-20 14:29

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表