Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

How to use EnumWindows with a lambda?

How to call the winapi EnumWindows in a lambda?
My attempt:

        DWORD parentId;
        // ...
        HWND parent_hwnd;
        EnumWindows([parent_hwnd](HWND hwnd, LPARAM lParam)
        {
            DWORD lpdwProcessId;
            GetWindowThreadProcessId(hwnd,&lpdwProcessId);
            if(lpdwProcessId == lParam)
            {
                parent_hwnd = hwnd;
                return FALSE;
            }
            return TRUE;
        }, (LPARAM)&parentId);

>Solution :

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

EnumWindows() expects a plain function pointer for its callback, however a capturing lambda is not convertible to a function pointer. Only a non-capturing lambda is convertible to a function pointer. As such, you need to use a non-capturing lambda, and use the callback’s LPARAM parameter to pass around all of your lambda’s state information.

Note that you have two bugs in your original lambda, which would have caused your code to fail even if you could have used a capturing lambda as the callback:

  • You are capturing the caller’s parent_hwnd variable by-value, which means the lambda makes a copy and won’t modify the value of the caller’s original variable. You would need to capture the variable by-reference instead. Not that it matters in this case, since you can’t use a capturing lambda anyway.

  • (this one affects a non-capturing lambda, too) You are passing the caller’s parentId variable by DWORD* pointer to the callback’s LPARAM, but then you are treating the LPARAM‘s value as-is, which means your comparison to each window’s process ID will never find a match. You would need to cast the LPARAM to a DWORD* pointer and then dereference that pointer in order to get the correct DWORD value for the comparisons, eg if (lpdwProcessId == *(DWORD*)lParam). Otherwise, just pass in the caller’s parentId variable by-value instead of by-pointer, then you don’t have to worry about this casting. Not that it matters in this case, since you need to pass in more than just a single DWORD to the callback in order for your logic to work.

With all of that said, try something more like this instead:

struct enumInfo {
    DWORD procId;
    HWND hwnd;
};

enumInfo info;
info.procId = ...;
info.hwnd = NULL;

EnumWindows(
    [](HWND hwnd, LPARAM lParam)
    {
        enumInfo *info = reinterpret_cast<enumInfo*>(lParam);

        DWORD dwProcessId;
        GetWindowThreadProcessId(hwnd, &dwProcessId);

        if (dwProcessId == info->procId)
        {
            info->hwnd = hwnd;
            return FALSE;
        }
        return TRUE;
    },
    reinterpret_cast<LPARAM>(&info)
);

HWND parent_hwnd = info.hwnd;
// use parent_hwnd as needed...
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading