Passing a pointer as LPARAM to EnumWindowsProc ..... How?
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(开发者_JS百科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
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?
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.
An LPARAM is not a pointer - you need to cast it:
BOOL CALLBACK EnumVisiWindowTitles(HWND hWnd, LPARAM lumpi) {
MYHANDLES * mh = (MYHANDLES *) lumpi;
....
mh[mh[0].count].title[n] = String[n]
}
I can't speak for the semantic correctness of this, however.
精彩评论