【问题标题】:why adding text to RichEdit window freezes it?为什么将文本添加到 RichEdit 窗口会冻结它?
【发布时间】:2023-03-06 15:15:01
【问题描述】:

在我用鼠标触摸richedit 窗口之前,它的内容是实时更新的,但是将鼠标悬停在它上面会将箭头变成沙漏光标。然后,该窗口不会对随后通过标题栏移动它的三到四次尝试做出反应。当它最终对鼠标拖动做出反应时,它移动正常但停止刷新其内容并且标题栏变为空。类似的效果是当我尝试单击窗口的客户区时。这一次点击几下后没有反应窗口也停止更新并且它的标题栏变成(没有响应)

当循环最终停止时,程序返回窗口更新并“活着”返回。在更新客户区时如何操作窗口(并看到它正在更新内容)?

#include <windows.h>
#include <sstream>

int main() {
  using namespace std;
  LoadLibrary("Msftedit.dll");
  HWND richeditWindow = CreateWindowExW (
    WS_EX_TOPMOST,
    L"RICHEDIT50W", 
    L"window text",
    WS_SYSMENU | WS_VSCROLL | ES_MULTILINE | ES_NOHIDESEL | WS_VISIBLE,
    50, 50, 500, 500,
    NULL, NULL, NULL, NULL
  );

  for (int i = 0 ; i<100000; i++) {
    wstringstream wss;
    wss << i << L", ";
    SendMessageW(richeditWindow, EM_REPLACESEL, FALSE, (LPARAM) wss.str().c_str());
  }

  MSG msg;
  while( GetMessageW( &msg, richeditWindow, 0, 0 ) ) {
    TranslateMessage(&msg);
    DispatchMessageW(&msg);
  }
}

【问题讨论】:

    标签: c++ winapi richedit


    【解决方案1】:

    您正在一个紧密的循环中填充丰富的编辑窗口,而不是为您的消息队列提供服务。除非您的进程定期处理其消息队列,否则系统会认为您的应用程序已停止响应。好吧,它已经停止响应了!

    为了让您的应用程序保持响应,您必须抽取消息队列。我真的不知道您的实际程序正在尝试做什么。如果您想将该文本放入丰富的编辑中,您可以使用单个 EM_REPLACESEL 消息来实现。

    如果您确实有一个长时间运行的任务,那么它属于不同的线程。然后你必须处理同步回 GUI 线程。如果您所做的只是调用 SendMessage,那么系统会负责同步。

    底线是必须及时抽出您的消息队列。

    【讨论】:

      【解决方案2】:

      找到答案这是我修改后的代码,看看PeekMessageWDispatchMessageW

      #include <windows.h>
      #include <iostream>
      #include <sstream>
      
      int main() {
        using namespace std;
        LoadLibrary("Msftedit.dll");
        HWND richeditWindow = CreateWindowExW (
          WS_EX_TOPMOST,
          L"RICHEDIT50W", 
          L"window text",
          WS_SYSMENU | WS_VSCROLL | ES_MULTILINE | ES_NOHIDESEL | WS_VISIBLE,
          50, 50, 500, 500,
          NULL, NULL, NULL, NULL
        );
      
        MSG msg;
        for (int i = 0 ; i<100000; i++) {
          wstringstream wss;
          wss << i << L", ";
          SendMessageW(richeditWindow, EM_REPLACESEL, FALSE, (LPARAM) wss.str().c_str());
          if (PeekMessageW(&msg, richeditWindow, 0, 0, PM_REMOVE)) {
            TranslateMessage(&msg);
            DispatchMessageW(&msg);
          }
        }
      
        while( GetMessageW( &msg, richeditWindow, 0, 0 ) ) {
          TranslateMessage(&msg);
          DispatchMessageW(&msg);
        }
      }
      

      【讨论】:

      • 那个代码全错了。您需要检查 PeekMessage 的返回值。那里可能没有消息。如果那里有任何东西,你真的应该清空队列。否则,您将按下键,然后添加更多文本,然后按下键,依此类推。那会好吗?您应该调用翻译消息。但是,您为什么不一口气添加所有文本呢?更重要的是,像这样乱七八糟的队列是混乱和糟糕的形式。在不同的线程中运行循环。另外,如果用户开始打字怎么办。现在他们的文字和你的混在一起了。
      • 是的,我知道代码看起来不专业,但它确实有效,我并不那么着迷于幕后发生的事情,让计算机感受到痛苦,计算机是为人类而不是其他绕路。无论如何,这只是一个例子。
      • 没有任何改进可以解决这个问题。我很难知道我的答案有什么问题。
      • 我已将 PeekMessage 放入 if 语句中。更好的 ?效果一样。
      • 您仍然需要清空队列。一次发送一条消息是不好的。不管怎样,我已经告诉你了。你明白我的回答了吗?
      猜你喜欢
      • 2013-06-11
      • 2017-08-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-04-29
      • 1970-01-01
      • 2011-04-02
      • 1970-01-01
      相关资源
      最近更新 更多