0

Until I touch the richedit window by mouse its contents are live updated, but hovering the mouse over it turns arrow into hourglass cursor. The window then doesn't react to three or four consequent tries to move it by title bar. When it finally does react to mouse dragging it moves fine but stops refreshing its contents and the title bar becomes empty. Similar effect is when I try to click the client area of the window. This time after a few clicks with no reaction window also stops updating and its title bar turns to (not responding).

When the loop eventually stops the program comes back window updates and comes back 'alive'. What to do to be able to manipulate the window (and see it's updating content) while it's client area is updated ?

#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);
  }
}
rsk82
  • 28,217
  • 50
  • 150
  • 240

2 Answers2

2

You are populating the rich edit window in a tight loop, and not servicing your message queue. Unless your process is regularly attending to its message queue, the system thinks that your app has stopped responding. Well, it has stopped responding!

In order to keep your application responsive, you must pump your message queue. I don't really know what your real program is trying to do. If you wanted to put that text into a rich edit, you'd do so with a single EM_REPLACESEL message.

If you really do have a long running task then it belongs on a different thread. Then you have to deal with synchronizing back to the GUI thread. If all you do is call SendMessage then the system takes care of synchronizing that.

The bottom line is that must pump your message queue in a timely fashion.

David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
0

Found answer this is my revised code, look at PeekMessageW and DispatchMessageW.

#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);
  }
}
rsk82
  • 28,217
  • 50
  • 150
  • 240
  • 1
    That code is all wrong. You need to check the return value of PeekMessage. There might be no message there. You really should empty the queue if there is anything there. Otherwise you'll do a key down, then add some more text, then do a key up, and so on. Will that be fine? You should call translate message. But why don't you just add all the text in one go? What's more, messing with messing queues like this is messy and bad form. Run the loop in a different thread. Also, what if the user starts typing. Now their text is mixed up with yours. – David Heffernan Jan 24 '13 at 23:32
  • Yea, I know that the code doesn't look professional, but it works, I'm not that obsessed what's happening under the hood, let the computer feel the pain, computers are for humans not other way around. Anyway this is just an example. – rsk82 Jan 25 '13 at 12:30
  • No amount of polishing fixes this up. I'm struggling to know what's wrong with my answer. – David Heffernan Jan 25 '13 at 12:32
  • I've put PeekMessage into a if statement. Better ? Works the same. – rsk82 Jan 25 '13 at 12:58
  • Not much better. You still miss the TranslateMessage. You still only pull off one message at a time and so interleave queued messages with control modifications. And you still allow the user to type away in your control whilst you are modifying it at the same time. What you should do is prepare your content in a string buffer, say, and then put it in the control with a single `EM_REPLACESEL`. That would happen effectively instantly. – David Heffernan Jan 25 '13 at 14:52
  • @DavidHeffernan: ok added TranslateMessage, for typing away I could just set the cursor to the end every time I'm replacing selection. But in this example I wanted to demonstrate exactly that user is able to play with the control while program is doing its own work. – rsk82 Jan 25 '13 at 15:16
  • 1
    You still need to empty the queue. Pulling off one message at a time is no good. Anyway, I've told you all that. Did you understand my answer? – David Heffernan Jan 25 '13 at 15:18