【问题标题】:Win32 GUI and callback to C++ functionWin32 GUI 和 C++ 函数回调
【发布时间】:2011-03-21 05:09:53
【问题描述】:

所以,基本上我使用的是这样的代码。这是一个简单的窗口,您只能在其中更改编辑框中的文本并按下一个按钮,该按钮将对函数进行回调 (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() 中检查用户输入,或者我必须使用多个线程?

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

【问题讨论】:

    标签: c++ winapi user-interface codeblocks


    【解决方案1】:

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

    【讨论】:

    • 我愿意尝试这个解决方案,因为这看起来对我最有帮助。但是,当尝试使用该函数时,我遇到了一个未声明的函数问题(“'QueueUserWorkItem' 未在此范围内声明”)。我已经包含 windows.h(这是文档要求的)并链接到 libkernel32.a。我错过了什么吗?
    • 来自 MSDN,“要编译使用此函数的应用程序,请将 _WIN32_WINNT 定义为 0x0500 或更高版本。”希望能帮助到你。 :)
    • 非常感谢。我之前确实尝试过,但它试图定义一个已经定义的值,我认为没有必要。我更好地阅读了windef.h 中的定义,因为这似乎需要这个值才能工作,所以我在包含windows.h 之前定义了它,现在一切都很完美。再次感谢。
    【解决方案2】:

    如果可能,您可以在DoSomethingCallback 内每隔一段时间处理消息队列,这将使 UI 保持响应。尽可能运行原始消息循环,即while( GetMessage(...,但请确保禁用该按钮,以便用户不会再次单击...这将导致递归。

    【讨论】:

      【解决方案3】:

      您可以通过不时调用 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;
          }
        }
      }
      

      【讨论】:

      • 也许这让 Windows 信服了,但它并没有让用户信服。用户仍然会认为应用程序崩溃了,因为无法重绘/移动窗口。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多