Win32 GUI и обратный вызов функции C ++ - PullRequest
1 голос
/ 21 марта 2011

Итак, в основном я использую такой код.Это небольшое простое окно, в котором вы можете изменить только текст внутри поля редактирования и нажать кнопку, которая будет вызывать функцию (DoSomethingCallback (текст)).

#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 ]

2 голосов
/ 21 марта 2011

Я бы пошел для вызова QueueUserWorkItem () для его обработки. Если ваш DoSomethingCallback () слишком длинный, невозможно сделать ваше окно отзывчивым, пока DoSomethingCallback () работает, поскольку для выполнения кода существует только один поток. Удачи!

1 голос
/ 21 марта 2011

Вы можете заглянуть в очередь сообщений, чтобы убедить Windows, что вы все еще живы, и время от времени вызываете 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;
    }
  }
}
1 голос
/ 21 марта 2011

Если возможно, вы можете обрабатывать очередь сообщений с интервалами в пределах DoSomethingCallback, что будет поддерживать отзывчивость интерфейса пользователя.Просто запустите исходный цикл обработки сообщений, т. Е. while( GetMessage(..., когда только сможете, но обязательно отключите кнопку, чтобы пользователь не нажимал второй раз ... это приведет к рекурсии.

...