0

Here's what I'm trying to do with this WinAPI function:

EnumWindows(
    _In_ WNDENUMPROC lpEnumFunc,
    _In_ LPARAM      lParam
);

It is called from the FeedWindowsHandlesList function of this class WinFinder (simplified here).

class WinFinder
{
    WinFinder();
    ~WinFinder();

    std::vector<HWND> winHandles;
    void FeedWindowsHandlesList();
};

This FeedWinDowsHandlesList function calls EnumWindows, which in turn triggers a callback for every handle found. There, the HWND is added to the winHandles member of the calling WinFinder instance. The challenge for me is to access members of the calling WinFinder instance. I tried two methods, they both fail the same way.


Method1:(Inspired from this SO post)

Calling function:

void WinFinder::FeedWindowsHandlesList() {
    LPARAM param = reinterpret_cast<LPARAM>(this);
    EnumWindows(EnumWindowsProc, param);
}

Callback(simplified):

BOOL CALLBACK EnumWindowsProc(HWND hWnd, LPARAM lParam)
{
    WinFinder thisWF = *(reinterpret_cast<WinFinder*>(lParam));
    thisWF.winHandles.push_back(hWnd);
    return TRUE;
}

A breakpoint at the push_back level lets me see that adding occurs, and the size of the vector gets to 1. But the next time I get in the callback, the vector is empty. When EnumWindows has finished, the vector is totally empty.


I also tried like this

Method2:

Calling function:

void WinFinder::FeedWindowsHandlesList() {
    WinFinder * wf =this;
    EnumWindows(EnumWindowsProc,(LPARAM)wf);    
}

Callback:

BOOL CALLBACK EnumWindowsProc(HWND hWnd, LPARAM lParam)
{
    WinFinder thisWF= *((WinFinder*)lParam);
    thisWF.winHandles.push_back(hWnd);  
 return TRUE;
}

So, How do you think I could do to access the vector member of the WinFinder class that calls EnumWindows, without losing anything?

Student
  • 805
  • 1
  • 8
  • 11
Eric P.
  • 97
  • 1
  • 7

1 Answers1

2
BOOL CALLBACK EnumWindowsProc(HWND hWnd, LPARAM lParam)
{
    // WinFinder thisWF = *(reinterpret_cast<WinFinder*>(lParam));
    // in the above line you're creating a copy of the object pointed to by lParam
    // what you want instead is just a pointer of type WinFinder to simplify access:
    WinFinder *thisWF = reinterpret_cast<WinFinder*>(lParam);
    // thisWF.winHandles.push_back(hWnd);
    // since thisWF is a pointer you have to use -> to access the members:
    thisWF->winHandles.push_back(hWnd);
    return TRUE;
}

Plan-B: Use a reference (as suggested by @SoronelHaetir):

BOOL CALLBACK EnumWindowsProc(HWND hWnd, LPARAM lParam)
{
    WinFinder &thisWF = *reinterpret_cast<WinFinder*>(lParam);
    thisWF.winHandles.push_back(hWnd);
    return TRUE;
}

Minimal Example:

#include <iostream>
#include <vector>
#include <Windows.h>

struct WinFinder
{
    std::vector<HWND> winHandles;
    void FeedWindowsHandlesList();
};

BOOL CALLBACK EnumWindowsProc(HWND hWnd, LPARAM lParam)
{
    WinFinder *thisWF = reinterpret_cast<WinFinder*>(lParam);
    thisWF->winHandles.push_back(hWnd);
    return TRUE;
}

void WinFinder::FeedWindowsHandlesList()
{
    LPARAM param = reinterpret_cast<LPARAM>(this);
    EnumWindows(EnumWindowsProc, param);
}

int main()
{
    WinFinder wf;
    wf.FeedWindowsHandlesList();

    for (auto const & w : wf.winHandles)
        std::cout << w << '\n';
}
Swordfish
  • 12,971
  • 3
  • 21
  • 43
  • Using a reference (to the dereferenced pointer) would allow for changing less of the existing code. – SoronelHaetir Jul 28 '18 at 15:29
  • Thank you for taking the time to help and teach a few things. Unfortunately with both of these solutions, I have the same problem as I had when i tried something else ((reinterpret_cast(lParam)->winHandles).push_back(hWnd);) : In DEBUG mode, when doing push_back, i get Exception thrown: read access violation. _Pnext was 0xFFFFFFFFFFFFFFFF. While In Release mode, it does work and I have my vector filled. Debugging in Release mode is not an option for me, since many variables are optimized away. Would you know how to overcome this issue? Again, many thanks – Eric P. Jul 28 '18 at 16:00
  • @Eric P. I edited my answer to include a complete example. – Swordfish Jul 28 '18 at 16:17
  • @EricP.: If that's the error you, you are probably accessing an object after it has been destroyed. Set a breakpoint on your destructor to learn, what's going on. You can also use the [/Zo](https://learn.microsoft.com/en-us/cpp/build/reference/zo-enhance-optimized-debugging) compiler switch to enhance optimized debugging. That's not required, though. – IInspectable Jul 28 '18 at 16:19
  • Thank you @Swordfish. Your project indeed works, and mine not. I realize the problem lies elsewhere, and created another question to adress it. Feel free to chime in, of course;). Anyway, thanks a lot for your time! – Eric P. Jul 30 '18 at 15:50
  • Here is the [question](https://stackoverflow.com/questions/51597764/a-vector-member-is-reset-and-unaccessible) – Eric P. Jul 30 '18 at 15:56