Win32 GUI和回调到C ++函数

时间:2011-03-21 05:09:54

标签: c++ winapi user-interface codeblocks

所以,基本上我正在使用像这样的代码。这是一个简单的窗口,您只能在编辑框内更改文本,然后按下一个按钮,该按钮将对函数进行回调(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;
}

问题在于,当运行该回调时,如果您尝试关闭或按下按钮,则窗口将显示为“无响应”,甚至会出现滞后现象。我理解为什么会发生这种情况,回调需要时间,接收循环不在那里检查用户的输入。我已经搜索了一种'修复'的方法,我找不到任何东西。我很确定这是愚蠢的,但我必须试着问。

一种显而易见的方法是进行更快速的回调。但还有另外一个像检查DoSomethingCallback()内部的用户输入,或者我必须使用多个线程?

抱歉这个令人困惑的问题。

3 个答案:

答案 0 :(得分:2)

我会去打电话QueueUserWorkItem()来处理它。如果你的DoSomethingCallback()太长,那么当DoSomethingCallback()工作时,没有办法使你的窗口响应,因为只有一个线程来运行代码。祝你好运!

答案 1 :(得分:1)

如果可能,您可以在DoSomethingCallback内定期处理消息队列,这将使UI保持响应。只要你可以运行原始的消息循环,即while( GetMessage(...,但请确保禁用该按钮,这样用户不会再次点击...这将导致递归。

答案 2 :(得分:1)

您可以通过不时调用PeekMessage()来查看消息队列以说服窗口您仍然活着并且正在踢。这假设您可以在DoSomethingCallback()中执行此操作,即主线程不会完全挂起。将下面的循环视为伪代码,并利用您的想象力将其转换为您的需求。

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