Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Passing a pointer as LPARAM to EnumWindowsProc ..... How?

Tags:

c++

I have a question using the EnumWindows function.

What I am trying to do:

I want to call EnumWindows and subsequently my EnumVisiWindowTitles function. The EnumVisiWindowTitles shall get every handle and caption of all visible windows AND STORE THESE in the "lumpi" struct.

Later on in the main I want to access "lumpi" and search for a particular caption string.

My problem is that I don't manage to pass a pointer pointing to lumpi[0] to EnumVisiWindowTitles as LPARAM.

Maybe my genaral plan is not so bright, so if annyone of you could help me, or show me a solution that performs the same task I would be very glad for your help!

I have a main looking like this:

int _tmain(int argc, _TCHAR* argv[])

{
 MYHANDLES lumpi[10];
 EnumWindows(EnumVisiWindowTitles, (LPARAM) &lumpi[0]);

blabla
}

Myhandles is defined as:

#ifndef handlestruct_H
#define handlestruct_H
struct MYHANDLES
 { public:
  MYHANDLES();  //MYHANDLEconstructor.cpp
  HWND haendchen;
  int count;
  char title[200];
 };

#endif

And my EnumWindowsProc looks like this:

using namespace std;
 BOOL CALLBACK EnumVisiWindowTitles(HWND hWnd, LPARAM lumpi) 
{  

 TCHAR String[200]; 

 if (!hWnd)
  return TRUE;// Not a window, return TRUE to Enumwindows in order to get the next handle
 if (!::IsWindowVisible(hWnd))
  return TRUE;// Not visible, return TRUE to Enumwindows in order to get the next handle 
 if (!SendMessageW(hWnd, WM_GETTEXT, sizeof(String), (LPARAM)String))
  return TRUE;// No window title, return TRUE to Enumwindows in order to get the next handle

 lumpi[lumpi[0].count].haendchen = hWnd;

   for (int n=0; n<201; n++)//copy the caption to lumpi struct
    {
     lumpi[lumpi[0].count].title[n] = String[n];
    }

   lumpi[0].count++;  //Increase counter

   wcout<<String<<'\n';
   return true;   //return true to get next handle   
}

I get an "Expression must have pointer to object type" indicated at each [0]

Arne

like image 204
Lumpi Avatar asked Dec 16 '10 12:12

Lumpi


2 Answers

First off, change your call to EnumWindows() to this:

int _tmain(int argc, _TCHAR* argv[])
{
    MYHANDLES lumpi[10];
    EnumWindows(&EnumVisiWindowTitles, reinterpret_cast<LPARAM>(lumpi));
    // ...
}

Standard C++ requires that you use the & symbol to pass a pointer to a function. The reinterpret_cast<>() tells the compiler to pass the pointer to your MYHANDLES array as-is to the LPARAM parameter of EnumWindows().

Then, in your callback:

BOOL CALLBACK EnumVisiWindowTitles(HWND hWnd, LPARAM ptr)
{
    MYHANDLES* lumpi = reinterpret_cast<MYHANDLES*>(ptr);
    // ...
}

We then retrieve the original pointer back using reinterpret_cast<>() again. Then, you can act upon lumpi as though it was an array because it actually is an array.

That issue asside, I see other problems. You apparently use the first element to store the count, which is weird. Just put that in another struct.

struct MyHandles
{
public:
    MyHandles();
    HWND haendchen;
    char title[200];
};

struct ListOfMyHandles
{
public:
    int count;
    MyHandles handles[10];
};

int _tmain(int argc, _TCHAR* argv[])
{
    ListOfMyHandles lumpi;
    ::EnumWindows(&EnumVisiWindowTitles, reinterpret_cast<LPARAM>(&lumpi));
    // ...
}

BOOL CALLBACK EnumVisiWindowTitles(HWND hWnd, LPARAM ptr)
{
    ListOfMyHandles* lumpi = reinterpret_cast<ListOfMyHandles*>(ptr);
    if(lumpi != 0 && lumpi->count < 10) // Avoid going past the array
    {
        lumpi->handles[lumpi.count] = //...
        // ...
        ++lumpi->count;
        return TRUE;
    }
    return FALSE;
}

Note that this will only hold up to 10 windows. Why not use std::vector instead, which will grow dynamically as you add elements to it?

like image 112
In silico Avatar answered Sep 25 '22 22:09

In silico


You need to cast the pointer. A LPARAM is defined as a long in 32bit and __int64 in 64bit, so it's perfectly OK to cast your pointer to a LPARAM and back again.

More than that, you really need to use a little object orientation here. There's absolutely no need to maintain your own counters or limited memory management, etc.

typedef std::basic_string<TCHAR> tstring;
class Handles {
public:
    struct window_data {
        tstring caption;
        HWND handle;
    };
private:
    std::vector<window_data> stuff;
    BOOL add_window(HWND hwnd) {
        TCHAR String[200] = {0};
        if (!hwnd)
            return TRUE;// Not a window, return TRUE to Enumwindows in order to get the next handle
        if (!::IsWindowVisible(hwnd))
            return TRUE;// Not visible, return TRUE to Enumwindows in order to get the next handle 
        LRESULT result = SendMessageW(hwnd, WM_GETTEXT, sizeof(String), (LPARAM)String);
        if (!result)
            return TRUE;// No window title, return TRUE to Enumwindows in order to get the next handle
        window_data data;
        data.handle = hwnd;
        for(int i = 0; i < result; i++)
            data.caption.push_back(String[i]);
        stuff.push_back(data);
        return TRUE;
    }
    static BOOL CALLBACK EnumWindowsProcCallback(HWND hwnd, LPARAM lparam) {
        Handles* ptr = reinterpret_cast<Handles*>(lparam);
        return ptr->add_window(hwnd);
    }
public:
    Handles& enum_windows() {
        stuff.clear();
        if(!EnumWindows(EnumWindowsProcCallback, reinterpret_cast<LPARAM>(this))) {
            // Error! Call GetLastError();
        }
        return *this;
    }
    std::vector<window_data>& get_results() {
        return stuff;
    }
};

int _tmain(int argc, TCHAR* argv[]) {
    std::vector<Handles::window_data> results = Handles().enum_windows().get_results();
}

Nice, easy interface, automated memory management - epic win.

like image 25
Puppy Avatar answered Sep 26 '22 22:09

Puppy