what is the right approach to fire an event in a C++ DLL and handle it in a client(C++ or C# application that consumes the DLL)?

Viewed 263

I am trying to build a DLL that reads Raw input, processes the data, and streams it to a client application that consumes this DLL. Both my DLL, and client application will be running in the background, or in the system tray. To achieve this behavior, I plan to use events. While I was trying to learn about the right approach to do this, I found conflicting guidance online and had trouble differentiating between these, and picking the right approach.

This article on event handling in native C++ suggests to setup an event source and event receiver using the event_source and event_receiver attributes. Though this approach might work in my situation, This documentation on event handling informs that event handling, though supported for native C++, is deprecated and will not be supported in future releases. This implies that I should not be using this approach. At the same time, This documentation on handling COM events looks like one potentially correct approach. I however am not able to fully understand the code here. Are there better examples or documentation that I could learn from?

Finally, This article on using C++ events in CLI discusses what I understand is a slightly different approach. The code below shows my approach for registering for input from a Precision Touchpad. I want to then override the WindowProc callback function to read input in the background. Finally, I want my DLL to raise my own events when a touch begins, is in progress, and ends. An application (running in the background) consuming this DLL should then be able to listen for the events I raise, and perform actions. What is the right, and non-deprecated approach to fire events in a C++ DLL, and handle it in the client?

My Code

// skipping headers and error handeling for brevity.
static std::vector<RAWINPUTDEVICELIST> getRawInputDevices()
{
    std::vector<RAWINPUTDEVICELIST> devices(64);
    while (true) {
        UINT numDevices = devices.size();
        UINT ret = GetRawInputDeviceList(&devices[0], &numDevices, sizeof(RAWINPUTDEVICELIST));
        if (ret != (UINT)-1) {
            devices.resize(ret);
            return devices;
        }
        else if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
            devices.resize(numDevices);
        }
        else {
            throw win32_error();
        }
    }
}

static RID_DEVICE_INFO getDeviceInfo(HANDLE HDevice)
{
    RID_DEVICE_INFO info;
    info.cbSize = sizeof(RID_DEVICE_INFO);
    UINT deviceSize;
    deviceSize = sizeof(RID_DEVICE_INFO);
    if (GetRawInputDeviceInfo(HDevice, RIDI_DEVICEINFO, &info, &deviceSize) == -1)
    {
        throw win32_error();
    }
    return info;
}

bool isPrecisionTouchAvailable()
{
    bool isDigitizerAvailable = false;
    std::vector<RAWINPUTDEVICELIST> devices = getRawInputDevices();
    for (std::size_t i = 0; i < devices.size(); ++i)
    {
        RID_DEVICE_INFO info = getDeviceInfo(devices[i].hDevice);
        if (info.dwType == RIM_INPUT && info.hid.usUsagePage == HID_USAGE_PAGE_DIGITIZER && info.hid.usUsage == HID_USAGE_DIGITIZER_TOUCH_PAD)
        {
            isDigitizerAvailable = true;
            break;
        }
        else {
            isDigitizerAvailable = false;
        }

    }
    return isDigitizerAvailable;
}

bool registerTouchpadForInput()
{
    bool registrationStatus = false;
    bool precisionTouchStatus = isPrecisionTouchAvailable();
    if (isPrecisionTouchAvailable != 0)
    {
        return registrationStatus;
    }
    else {
        RAWINPUTDEVICE rid[1]; //one for precision touch when application is in background. Array because I plan to register for more devices like keyboard once I get things working.
        rid[0].usUsagePage = HID_USAGE_PAGE_DIGITIZER; // for touchpad
        rid[0].usUsage = HID_USAGE_DIGITIZER_TOUCH_PAD; // usage ID for touchpad
        rid[0].dwFlags = RIDEV_INPUTSINK; //to receive events even in the background.
        if (RegisterRawInputDevices(rid, 1, sizeof(rid[0])) == false)
        {
            GetLastError();
            //throw "error registering touchpad to get data.";
        }
        else { registrationStatus = true; }

    }
    return registrationStatus;
}

When my application launches, I want to call registerTouchpadForInput and let the user know that they will not be able to use my application if they do not have a Precision Touchpad on their device.

0 Answers
Related