Я пытаюсь реализовать VST с помощью VSTGUI 4.0. Мой DAW использует сообщения WM_KEYDOWN и WM_KEYUP для отправки миди-нот на основе нажатий на клавиатуре, чтобы вы могли играть на VST с клавиатуры. Проблема в том, что VSTGUI делает это, когда получает сообщение WM_LBUTTONDOWN:
win32Frame->prevFocus = SetFocus (win32Frame->getPlatformWindow ());
CPoint where ((CCoord)((int)(short)LOWORD(lParam)), (CCoord)((int)(short)HIWORD(lParam)));
if (pFrame->platformOnMouseDown (where, buttons) == kMouseEventHandled)
SetCapture (win32Frame->getPlatformWindow ());
return 0;
Это отнимает фокус у DAW и не позволяет ему обрабатывать нажатия клавиш. VSTGUI нужен фокус окна для обработки событий WM_MOUSEWHEEL и WM_KEYUP / WM_KEYDOWN для настройки элементов управления. Но когда вы настраиваете элементы управления в VST, вы, очевидно, хотите иметь возможность играть ноты с помощью клавиатуры, чтобы увидеть, как они звучат, поэтому важны обе функции.
Единственный способ решить эту проблему — установить SetFocus () в родительское окно, отправить туда сообщения WM_KEYUP / WM_KEYDOWN обратно с помощью SendMessage (), а затем SetFocus () обратно в окно VST:
case WM_KEYDOWN:
...code to handle modifiers like shift, ctrl, etc...
else
{
SetFocus(win32Frame->prevFocus);
SendMessage(win32Frame->prevFocus, message, wParam, lParam);
SetFocus(win32Frame->getPlatformWindow ());
}
Это работает отлично, пока вы не нажмете VST и не нажмете клавишу одновременно, и в этот момент происходит неопределенный процесс (замораживание DAW, сбой DAW, переполнение стека и т. Д.).
Поэтому, очевидно, я принимаю неправильный подход с этим. Я чувствую, что мне нужно PostMessage () и ждать обратного вызова, прежде чем я верну фокус на VST или что-то в этом роде. Даже это звучит как-то не так, как надо, так каков правильный способ решения такой проблемы?
Имейте в виду, что у меня нет доступа к коду окна DAW, которое передает сообщения, поэтому я не могу реализовать пользовательское сообщение или что-то подобное.
Большое спасибо Hans Passant за решение этой проблемы!
Проблема с аварией была из-за ненадежности моего дескриптора окна. Я перестал хранить дескриптор окна в переменной, и вместо этого я получил его на месте с помощью GetParent ().
Мне также не нужно было фокусироваться на текущем окне, все, что мне нужно было сделать, это заменить свое SendMessage на PostMessage. Итак, новый код:
case WM_KEYDOWN:
...code to handle modifiers like shift, ctrl, etc...
else
{
PostMessage(GetParent(win32Frame->getPlatformWindow ()), message, wParam, lParam);
}
Других решений пока нет …