The correct way to create a custom control

I am a beginner and created a new project using VST3_Project_Generator, then implemented a custom piano keyboard control. I have simplified the code, but I still encounter the error: “WeiYuchen::PianoKeyboard class is an abstract class and cannot be instantiated directly.” I believe the issue lies in my implementation, but I have not found a better solution online so far.



// ---------------------------
// PianoKeyboard.cpp
// ---------------------------

#include "PianoKeyboard.h"
#include <iostream>

namespace WeiYuchen {

    // 1. Constructor: Initialize the piano keyboard control
    PianoKeyboard::PianoKeyboard(const VSTGUI::CRect& size)
        : VSTGUI::CControl(size) {}

    // 2. Draw function: Draw the piano key and the musical note
    void PianoKeyboard::draw(VSTGUI::CDrawContext* context) {
        
        // 2.1 Draw only one white key
        VSTGUI::CRect whiteKeyRect(0, 0, 30, 100);              // Define the rectangle for the white key
        context->setFillColor(VSTGUI::CColor(255, 255, 255));   // Set fill color to white
        context->drawRect(whiteKeyRect);                        // Draw the white key rectangle

        // 2.2 Draw text (C note)
        context->setFont(VSTGUI::kNormalFont);                                          // Set font
        context->setFontColor(VSTGUI::CColor(0, 0, 0));                                 // Set font color to black
        context->drawString("C", whiteKeyRect.getTopLeft() + VSTGUI::CPoint(5, 5));     // Draw the C note on the white key
    }

    // 3. Mouse click event handler
    VSTGUI::CMouseEventResult PianoKeyboard::onMouseDown(VSTGUI::CPoint& where, const VSTGUI::CButtonState& buttons) {
        // 3.1 Output the click position
        std::cout << "Mouse clicked at: " << where.x << ", " << where.y << std::endl;
        return VSTGUI::kMouseEventHandled; // Indicate the event has been handled
    }
}
// ---------------------------
// PianoKeyboard.h
// ---------------------------

#ifndef PianoKeyboard_h
#define PianoKeyboard_h

#include <stdio.h>
#include "vstgui/vstgui.h"

namespace WeiYuchen {

    class PianoKeyboard : public VSTGUI::CControl {
    public:
        PianoKeyboard(const VSTGUI::CRect& size);
        virtual ~PianoKeyboard() {}

        // 1. Implement pure virtual functions from CControl
        virtual void draw(VSTGUI::CDrawContext* context) override;
        virtual VSTGUI::CMouseEventResult onMouseDown(VSTGUI::CPoint& where, const VSTGUI::CButtonState& buttons) override;

        // 2. Simplified, other functionalities are not implemented yet
        virtual VSTGUI::CMouseEventResult onMouseUp(VSTGUI::CPoint& where, const VSTGUI::CButtonState& buttons) override {
            return VSTGUI::kMouseEventHandled; // 2.1 Handle mouse up event (no specific functionality here)
        }
    };
}
#endif /* PianoKeyboard_h */
//------------------------------------------------------------------------
IPlugView* PLUGIN_API PianoController::createView(FIDString name)
{
    if (FIDStringsEqual(name, Vst::ViewType::kEditor))
    {
        // 1. Create VST3Editor
        auto* view = new VSTGUI::VST3Editor(this, "view", "editor.uidesc");

        // 2. Get CFrame (this is a VSTGUI container responsible for control's position and size)
        VSTGUI::CFrame* frame = view->getFrame();
        
        // 3. Create a simple piano keyboard control (only draws one white key)
        WeiYuchen::PianoKeyboard* keyboard = new WeiYuchen::PianoKeyboard(VSTGUI::CRect(0, 0, 30, 100));
        
        // 4. Use CFrame's addView method to add the control
        frame->addView(keyboard);

        return view;
    }
    return nullptr;
}

If you lookup the complete compiler output of the error, then you will see that it is giving you an hint which method is missing. But to shorten it this time and because it’s a strange design decision of VSTGUI, if you subclass a CControl, you need to add the macro: CLASS_METHODS or CLASS_METHODS_NOCOPY to your class definition. Look this up in other classes in VSTGUI like CVuMeter.