Alok
Alok

Reputation: 10544

How to run official SetWinEventHook example code on Windows platform?

I want to try and run the official SetWinEventHook() example given at https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-setwineventhook:

// Global variable.
HWINEVENTHOOK g_hook;

// Initializes COM and sets up the event hook.
//
void InitializeMSAA()
{
    CoInitialize(NULL);
    g_hook = SetWinEventHook(
        EVENT_SYSTEM_MENUSTART, EVENT_SYSTEM_MENUEND,  // Range of events (4 to 5).
        NULL,                                          // Handle to DLL.
        HandleWinEvent,                                // The callback.
        0, 0,              // Process and thread IDs of interest (0 = all)
        WINEVENT_OUTOFCONTEXT | WINEVENT_SKIPOWNPROCESS); // Flags.
}

// Unhooks the event and shuts down COM.
//
void ShutdownMSAA()
{
    UnhookWinEvent(g_hook);
    CoUninitialize();
}

// Callback function that handles events.
//
void CALLBACK HandleWinEvent(HWINEVENTHOOK hook, DWORD event, HWND hwnd,
                             LONG idObject, LONG idChild,
                             DWORD dwEventThread, DWORD dwmsEventTime)
{
    IAccessible* pAcc = NULL;
    VARIANT varChild;
    HRESULT hr = AccessibleObjectFromEvent(hwnd, idObject, idChild, &pAcc, &varChild);  
    if ((hr == S_OK) && (pAcc != NULL))
    {
        BSTR bstrName;
        pAcc->get_accName(varChild, &bstrName);
        if (event == EVENT_SYSTEM_MENUSTART)
        {
            printf("Begin: ");
        }
        else if (event == EVENT_SYSTEM_MENUEND)
        {
            printf("End:   ");
        }
        printf("%S\n", bstrName);
        SysFreeString(bstrName);
        pAcc->Release();
    }
}

I wanted to compile and run this using Visual Studio, so I created a Windows Console Application Project with content:

#include <windows.h>
#include <iostream>
#include <conio.h>
#include <oleacc.h>

// Global variable.
HWINEVENTHOOK g_hook;

// Initializes COM and sets up the event hook.
//
void HandleWinEvent(HWINEVENTHOOK, DWORD, HWND,
    LONG, LONG,
    DWORD, DWORD);

void InitializeMSAA()
{
    HRESULT hrCoInit = CoInitialize(NULL);
    g_hook = SetWinEventHook(
        EVENT_SYSTEM_MENUSTART, EVENT_SYSTEM_MENUEND,  // Range of events (4 to 5).
        NULL,                                          // Handle to DLL.
        HandleWinEvent,                                // The callback.
        0, 0,              // Process and thread IDs of interest (0 = all)
        WINEVENT_OUTOFCONTEXT | WINEVENT_SKIPOWNPROCESS); // Flags.
}

// Unhooks the event and shuts down COM.
//
void ShutdownMSAA()
{
    UnhookWinEvent(g_hook);
    CoUninitialize();
}

// Callback function that handles events.
//
void CALLBACK HandleWinEvent(HWINEVENTHOOK hook, DWORD event, HWND hwnd,
    LONG idObject, LONG idChild,
    DWORD dwEventThread, DWORD dwmsEventTime)
{
    IAccessible* pAcc = NULL;
    VARIANT varChild;
    HRESULT hr = AccessibleObjectFromEvent(hwnd, idObject, idChild, &pAcc, &varChild);
    if ((hr == S_OK) && (pAcc != NULL))
    {
        BSTR bstrName;
        pAcc->get_accName(varChild, &bstrName);
        if (event == EVENT_SYSTEM_MENUSTART)
        {
            printf("Begin: ");
        }
        else if (event == EVENT_SYSTEM_MENUEND)
        {
            printf("End:   ");
        }
        printf("%S\n", bstrName);
        SysFreeString(bstrName);
        pAcc->Release();
    }
}

int main()
{
    std::cout << "Hello World!\n";
    InitializeMSAA();
    MSG msg;
    
    while (1) {
        //if (_getch() == 'q') {
        //    break;
        //}
        GetMessage(&msg, NULL, 0, 0);
        TranslateMessage(&msg);
        DispatchMessage(&msg);
     }
    ShutdownMSAA();
    return 0;
}

This code is running fine, but is not detecting events. I am trying to generate events by opening and closing the Start Menu.

How can I make this example code work?

Upvotes: 0

Views: 2360

Answers (1)

Junjie Zhu - MSFT
Junjie Zhu - MSFT

Reputation: 2979

According to the explanations for EVENT_SYSTEM_MENUSTART and EVENT_SYSTEM_MENUEND in the official documentation.

The system sends this event for standard menus, which are identified by HMENU, created using menu-template resources or Win32 menu API elements.

As @Remy Lebeau said, 'run a separate GUI app that has a menu'.

After your console program starts, you can run a Win32 desktop application with menu.

I modified your code to run in VS2019. Added CALLBACK in front of HandleWinEvent.

#pragma comment(lib,"Oleacc.lib")
// Global variable.
HWINEVENTHOOK g_hook;

// Initializes COM and sets up the event hook.
//
void CALLBACK HandleWinEvent(HWINEVENTHOOK, DWORD, HWND, LONG, LONG, DWORD, DWORD);

Here are my test results,

enter image description here

Upvotes: 1

Related Questions