Feb 092009
 

Developing a slick and polished gui for your VST plugin is less about graphics and more about creating a smooth customer experience. The default behavior of IPlug is to block mouse input when an ICaptionControl has edit focus (that’s the object you use to allow someone to type values into your parameters). If I have clicked on a value to type in it and decide to tweak a knob instead, then I don’t want to have to click back in the edit field and hit enter before being able to turn that other knob. I want to directly click on that other knob and have the edit field just go away. Here is an IPlug mod that will allow your VST plugin interface to work this way.

This behavior is all controlled from within the IGraphicsWin::WndProc method. Near the beginning of that method look for this code:

    if (pGraphics->mParamEditWnd && pGraphics->mParamEditMsg == kEditing) {
        if ((msg == WM_RBUTTONDOWN) {
            pGraphics->mParamEditMsg = kCancel;
            return 0;
        }
        return DefWindowProc(hWnd, msg, wParam, lParam);
    }

The most basic outcome of this block of code is to say if our parameter edit window is in editing mode then don’t process anything beyond this block until we are out of editing mode. There is a special handler contained within this block that says right mouse button events are ok to process while in editing mode, and they cause editing mode to be cancelled. We want to add a custom handler here for the left mouse button as well so it can also cancel editing mode. That is easy enough to accomplish by altering the inner if statement’s condition to look like this:

if ((msg == WM_RBUTTONDOWN) || (msg == WM_LBUTTONDOWN)) {

Now our left mouse button can get us past this portion of code but the parameter edit window does not close right away, if at all. Look further down in the same method to where you’ll see the following two case statements.

        case WM_RBUTTONDOWN:
            if (pGraphics->mParamEditWnd) {
                pGraphics->mParamEditMsg = kCancel;
                return 0;
            }
            // Else fall through.

        case WM_LBUTTONDOWN:
            SetCapture(hWnd);
            pGraphics->OnMouseDown(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam), &GetMouseMod(wParam));
            return 0;

Processing the right mouse button verifies that parameter editing has been cancelled and takes no further action, but processing the left button ignores the parameter edit window completely. So our first task is to make the left mouse button mParamEditWnd aware. Our first instinct is to add the same if statement to the WM_LBUTTONDOWN case. Close scrutinization of the code shows us that the if statement is the only thing in the WM_RBUTTONDOWN case which has a deliberate fallthrough to the left button case. Instead of copying the if statement we should be moving it.

The final implementation:

        case WM_RBUTTONDOWN:
            // fall through.
        case WM_LBUTTONDOWN:
            if (pGraphics->mParamEditWnd)
            {
                pGraphics->mParamEditMsg = kCancel;
            }
            SetCapture(hWnd);
            pGraphics->OnMouseDown(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam), &GetMouseMod(wParam));
            return 0;

It is a good habit to always leave a comment on any case statement that does not have a break in it. This lets any future developers (or yourself in a few weeks) that the break is missing on purpose and not some undiscovered bug.

With this development trick, your VST plugin gui should seamlessly transition in and out of edit mode with intuitive behavior.

NOTE: This mod works very well with the additional capability for allowing the left mouse button to enter parameter edit mode (technique outlined in this article).

Sorry, the comment form is closed at this time.