简体   繁体   English

Win32 GUI和回调到C ++函数

[英]Win32 GUI and callback to C++ function

So, basically I'm using a code like this one. 所以,基本上我正在使用像这样的代码。 It's a little simple window where you can only change text inside of an edit box and press a button that will make a callback to a function (DoSomethingCallback(text)). 这是一个简单的窗口,您只能在编辑框内更改文本,然后按下一个按钮,该按钮将对函数进行回调(DoSomethingCallback(text))。

#include <windows.h>

#define ID_EDIT 1
#define ID_BUTTON 2

LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{

  static HWND hwndEdit;
  static HWND hwndButton;
  static int len;
  static TCHAR text[30];


  switch(msg)
  {
    case WM_CREATE:
    hwndEdit = CreateWindow(TEXT("Edit"), NULL, WS_CHILD | WS_VISIBLE | WS_BORDER,
                50, 50, 150, 20, hwnd, (HMENU) ID_EDIT,
                NULL, NULL);

    hwndButton = CreateWindow(
        TEXT("button"), TEXT("Set Title"),       
        WS_VISIBLE | WS_CHILD,  
        50, 100, 80, 25,        
        hwnd, (HMENU) ID_BUTTON, NULL, NULL);      

    break;

    case WM_COMMAND:    
           if (HIWORD(wParam) == BN_CLICKED) {
               SetWindowText(hwnd, "Working...");
               GetWindowText(hwndEdit, text, len);
               DoSomethingCallback(text);
               SetWindowText(hwnd, "Finished");
           }
    break;

    case WM_DESTROY:
        PostQuitMessage(0);
    break;
  }
  return DefWindowProc(hwnd, msg, wParam, lParam);
}

int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,
            LPSTR lpCmdLine, int nCmdShow )
{
  MSG  msg ;    
  WNDCLASS wc = {0};
  wc.lpszClassName = TEXT( "Edit Control" );
  wc.hInstance     = hInstance ;
  wc.hbrBackground = GetSysColorBrush(COLOR_3DFACE);
  wc.lpfnWndProc   = WndProc ;
  wc.hCursor       = LoadCursor(0,IDC_ARROW);


  RegisterClass(&wc);
  CreateWindow( wc.lpszClassName, TEXT("Edit control"),
                WS_OVERLAPPEDWINDOW | WS_VISIBLE,
                220, 220, 280, 200, 0, 0, hInstance, 0);  

  while( GetMessage(&msg, NULL, 0, 0)) {
    TranslateMessage(&msg);
    DispatchMessage(&msg);
  }
  return (int) msg.wParam;
}

The problem is that when running that Callback the window will appear as "Not responsive" and even laggy if you try to close or press the button. 问题是,当运行该回调时,如果您尝试关闭或按下按钮,则窗口将显示为“无响应”,甚至会出现滞后现象。 I understand the reason why this might be happening, the callback takes time and the receiving loop isn't there to check the input of the user. 我理解为什么会发生这种情况,回调需要时间,接收循环不在那里检查用户的输入。 I've searched a way to 'fix' this and I couldn't find any. 我已经搜索了一种'修复'的方法,我找不到任何东西。 I'm pretty sure it's something dumb, but I have to try and ask. 我很确定这是愚蠢的,但我必须试着问。

An obvious way would be making a faster callback. 一个显而易见的方法是进行更快速的回调。 But is there another one like checking the user input inside of a DoSomethingCallback() while, or I have to use multiple threads? 但还有另外一个像检查DoSomethingCallback()内部的用户输入,或者我必须使用多个线程?

Sorry for the confusing question. 抱歉这个令人困惑的问题。

I would go for calling QueueUserWorkItem() to handle it. 我会去调用QueueUserWorkItem()来处理它。 If your DoSomethingCallback() is too long, there is no way to make your window responsive while DoSomethingCallback() is working since there is only one thread to run the code. 如果你的DoSomethingCallback()太长,那么当DoSomethingCallback()工作时,没有办法使你的窗口响应,因为只有一个线程来运行代码。 Good Luck! 祝好运!

If possible, you can process the message queue at intervals within DoSomethingCallback which will keep the UI responsive. 如果可能,您可以在DoSomethingCallback中间隔处理消息队列,这将使UI保持响应。 Just run the original message loop ie while( GetMessage(... whenever you can but make sure you disable the button so the user does not click a second time... this will lead to recursion. 只需运行原始的消息循环,即while( GetMessage(...无论何时可以,但确保禁用该按钮,以便用户不再单击...这将导致递归。

You can peek at the message queue to convince windows that you are still alive and kicking, by calling PeekMessage() from time to time. 您可以通过不时调用PeekMessage()来查看消息队列以说服窗口您仍然活着并且正在踢。 This assumes that you can do this in your DoSomethingCallback(), ie that the main thread doesn't hang completely. 这假设您可以在DoSomethingCallback()中执行此操作,即主线程不会完全挂起。 Regard the loop below as pseudo code and use your imagination to transform it to your needs. 将下面的循环视为伪代码,并使用您的想象力将其转换为您的需求。

void DoSomethingCallback()
{
  // Loop that takes a long time
  while (true) {
    DoSomeStuff();
    MSG msg;
    PeekMessage(&msg, nil, 0, 0, PM_NOREMOVE);
    if (ShouldBreak()) {
      break;
    }
  }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM