簡體   English   中英

Win32 GUI和回調到C ++函數

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

所以,基本上我正在使用像這樣的代碼。 這是一個簡單的窗口,您只能在編輯框內更改文本,然后按下一個按鈕,該按鈕將對函數進行回調(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()內部的用戶輸入,或者我必須使用多個線程?

抱歉這個令人困惑的問題。

我會去調用QueueUserWorkItem()來處理它。 如果你的DoSomethingCallback()太長,那么當DoSomethingCallback()工作時,沒有辦法使你的窗口響應,因為只有一個線程來運行代碼。 祝好運!

如果可能,您可以在DoSomethingCallback中間隔處理消息隊列,這將使UI保持響應。 只需運行原始的消息循環,即while( GetMessage(...無論何時可以,但確保禁用該按鈕,以便用戶不再單擊...這將導致遞歸。

您可以通過不時調用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;
    }
  }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM