Как следует обновить / вернуть значение из функции обратного вызова?

0

Я зарегистрировал обратный вызов через: SetWindowLongW(hWindow, GWL_WNDPROC, (LONG)WindowCallback);

Я получаю сообщения там без проблем. У меня есть() код стиля внутри обратного вызова, который выглядит так:

if (MSG == 1)
{

   *boolptr = true;
   ...
} else if(MSG == 2) {
  if (*boolptr == true)
    return;

   // do stuff
}

Переменные определяются так (globaly, под #includes right..)

volatile bool         boolVar = false;
volatile bool*        volatile boolptr = &boolVar;

Если я ожидаю, что * boolptr будет TRUE в main(), все будет в порядке, но если я буду ждать его внутри того же callback, где он должен измениться, он не работает. Очевидно, я не понимаю некоторые понятия здесь, поэтому я прошу помощи или объяснения, почему она не работает.

MSG со значением 2 всегда начинается первым, а затем после некоторой обработки MSG со значением 1. Через какое-то время происходит то же самое, но я не хочу делать такую же обработку и отходы процессорных циклов, поэтому мне нужно знать, MSG [1] следует за ним и просто возвращается. Я надеюсь ты понимаешь меня.

Благодарю!

  • 0
    Ваш вопрос немного сбивает с толку - что вы подразумеваете под "ожиданием"? Код, который вы перечислили, не ждет на флаге. Тем не менее, если ваше ожидание что-то вроде while (* boolptr) Sleep (1000); тогда ваш WndProc не будет просматривать MSG (1), если вы не делаете DoEvents в цикле. Другая причина может быть MSG (2) никогда не запускается.
  • 0
    Рассмотрите возможность исключения переменных bool и bool *. Вместо этого используйте переменную PreviousMSG. Это должно позволить вам проверить состояние интереса только одним оператором if.
Показать ещё 4 комментария
Теги:
callback
multithreading

1 ответ

0
Лучший ответ

Ваше описание оставляет много деталей, но я думаю, что понимаю, чего вы хотите. Последний параметр функции API CreateWindow() может использоваться для передачи указателя на ваш обратный вызов на некоторую внешнюю переменную:

// MAKE SURE this variable stays in scope throughout the lifetime of your window !
// Make it global or static
bool myVar;  

// let create an overlapped window of some class with size 400 x 300 
HWND hWnd = CreateWindow("My class name", "My Title", 
    WS_VISIBLE | WS_BORDER| WS_OVERLAPPED | WS_CAPTION |
    WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX,
    0,0, 400, 300, NULL, NULL, GetModuleHandle(NULL), &myVar);

Затем в обратном вызове вы получаете доступ к нему в сообщении WM_CREATE:

// ... start of your callback

// get a pointer to your variable here and use it in all messages
// *except* WM_CREATE that sets it during window instance creation
bool *pMyVar = (bool *)GetWindowLongPtr(hWnd, GWLP_USERDATA);

switch(uMsg)
{
    case WM_CREATE:
    {
        // get your pointer from the CREATESTRUCT passed in
        // and store it in the user data area of your window class
        // note: your WNDCLASS should have its cbWndExtra = sizeof(void *);
        CREATESTRUCT *pC = (CREATESTRUCT *)lParam;
        SetWindowLongPtr(hWnd, GWLP_USERDATA, (LONG)pC->lpCreateParams);
        // .... 
    }
    break;

    case 1 :  // VERY bad choice for a message, use WM_USER+1 instead
        *pMyVar = true;
    break;
// ... rest of your callback

это то, что вы хотели?

EDIT: Хорошо, вот класс, который вы хотели увидеть:

class MyClass
{
public:
    MyClass() : _hasRun(false) { }

    void DoStuff(HWND hW, UINT uMsg)
    {
        if (!_hasRun)
        {
            _hasRun = true;
            // ... do your work here, you have the window handle and the message
        }
    }

private:
    bool _hasRun;
};

теперь в вашем основном создайте экземпляр этого класса и сохраните его в статической или глобальной переменной:

MyClass *pC = new MyClass;

затем передайте это обратному вызову, как я показываю в начале, и затем вызываем его всегда. Функция участника DoStuff проверяет сообщение и делает то, что вы хотите, на основе того, что это сообщение, один раз. Даже если вы держите его в глобальном режиме и всегда вызываете это глобальное от обратного вызова, функциональность будет одинаковой.

// ... callback code before you handle any message
pC->DoStuff(hWnd, uMsg);
// ... rest of callback code
  • 0
    Я не создаю окно так, как вы, поэтому я не обрабатываю сообщение WM_CREATE. Я попал в тупик из-за этого, я думаю. Должен ли я изменить вызов CreateWindow или нет? Все остальное имеет смысл.
  • 0
    Этот метод создает немодальное окно, а остальная часть кода продолжается, чтобы вы могли затем войти в цикл обработки сообщений. Если вы создаете модальное окно (например, MessageBox), то вызов не будет возвращаться, поскольку он создает свой собственный цикл сообщений, пока окно не будет уничтожено. Какой метод вы используете, и почему вы попали в тупик? Кроме того, каждое сообщение в обратном вызове должно выполняться и возвращаться в цикл обработки сообщений, чтобы можно было обрабатывать другие сообщения. Если вы введете цикл ожидания в обратном вызове, ваш текущий поток будет зависать, пока вы не вернетесь из обратного вызова.
Показать ещё 5 комментариев

Ещё вопросы

Сообщество Overcoder
Наверх
Меню