【问题标题】:C++ WINAPI window does not refreshC++ WINAPI 窗口不刷新
【发布时间】:2016-04-22 13:23:55
【问题描述】:

我在由注入的DLL 创建的线程内有一个简单的窗口。这就是我的线程的样子:

int Thread()
{
  HWND hwnd;
  MSG messages;
  WNDCLASSEX wincl;
  /* The Window structure */
  wincl.hInstance = hThisInstance;
  wincl.lpszClassName = szClassName;
  wincl.lpfnWndProc = WindowProcedure;
  wincl.style = CS_CLASSDC;
  wincl.cbSize = sizeof(WNDCLASSEX);
  wincl.hIcon = LoadIcon(NULL, IDI_APPLICATION);
  wincl.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
  wincl.hCursor = LoadCursor(NULL, IDC_ARROW);
  wincl.lpszMenuName = NULL;
  wincl.cbClsExtra = 0;
  wincl.cbWndExtra = 0;

  wincl.hbrBackground = (HBRUSH)COLOR_BACKGROUND;
  if (!RegisterClassEx(&wincl))
    ;

  hwnd = CreateWindowEx(
    0,
    szClassName,
    "Windows App",
    WS_OVERLAPPEDWINDOW,
    CW_USEDEFAULT,
    CW_USEDEFAULT,
    544,
    375,
    NULL,
    NULL,
    hThisInstance,
    NULL
    );
  ShowWindow(hwnd, SW_SHOW);

  while (true) {
    if (GetMessage(&messages, NULL, 0, 0)) {
      TranslateMessage(&messages);
      DispatchMessage(&messages);
    }
    SetWindowText(hwnd, b);
    ShowWindow(hwnd, SW_SHOW);

    UpdateWindow(hwnd);
    RedrawWindow(hwnd, NULL, NULL, RDW_UPDATENOW);

    //do the stuff that computes values to show
  }
  return 0;
}

这是我的窗口过程:

LRESULT CALLBACK WindowProcedure(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
  switch (message)
  {
  case WM_PAINT:
  {

    PAINTSTRUCT ps;
    HDC hdc = BeginPaint(hwnd, &ps);
    TextOut(hdc,
      10,
      10,
      b,
      50);
    EndPaint(hwnd, &ps);
    return 0L;
  }
  break;
  case WM_DESTROY:
    PostQuitMessage(0);
    break;
  default:
    return DefWindowProc(hwnd, message, wParam, lParam);
  }
  return 0;
}

窗口可以工作,但有一个大问题。我希望实时更新和显示这些值,无论是在标题栏中还是在窗口内。尽管在循环中使用了这 3 个函数:ShowWindowUpdateWindowRedrawWindow,但重绘并不能如我所愿。当我使用正在注入的应用程序并生成我希望在我创建的窗口中显示的值时,我的窗口的标题栏或主区域都不会更新。但是,当所需的值发生变化并且我将鼠标移到我的窗口上时,标题栏会更新。至于主要区域,它仅在我将窗口拖动到屏幕边缘时更新,以便我覆盖要显示文本的位置然后揭开它(它甚至可以部分重绘),或者只是最小化并恢复窗户。

【问题讨论】:

    标签: c++ winapi


    【解决方案1】:
     if (GetMessage(&messages, NULL, 0, 0)) {
       TranslateMessage(&messages);
       DispatchMessage(&messages);
     }
     SetWindowText(hwnd, b);
     ShowWindow(hwnd, SW_SHOW);
    
     UpdateWindow(hwnd);
     RedrawWindow(hwnd, NULL, NULL, RDW_UPDATENOW);
    

    GetMessage blocks 如果没有消息要处理。 您应该确保它有消息要处理,可能通过使用 SetTimer 来生成计时器消息,或者考虑使用 PeekMessage 而不是 GetMessage(使用 PM_REMOVE 标志)

    【讨论】:

    • 谢谢,PeekMessage 正是我想要的!
    【解决方案2】:

    UpdateWindow之前调用InvalidateRect

    【讨论】:

    • 谢谢,现在我在主区域中的值与标题栏完全一样——它会在鼠标移动时刷新,即使窗口处于非活动状态。但我希望它在没有任何交互的情况下刷新。
    • 参见SetTimer API。它将在指定时间发送WM_TIMER 消息-您将在那里调用InvalidateRectUpdateWindow 不是必需的)。
    • 我看不出它对我有什么帮助,因为我一直在调用 InvalidateRect 并且这不会打扰我。我刚刚找到了一种解决方法——在更新函数的同时调用 SetForegroundWindow。但它不是很优雅和方便。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-10-26
    • 1970-01-01
    • 2013-10-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-10-01
    相关资源
    最近更新 更多