I'm writing a program which needs to retrieve the window title for the
foreground/ current/ active window in any given process. I've managed
to get the process list and using EnumWindows retrieve information
about all the top level windows. The first problem I have is some
processes have more then one top level window so I receive multiple
callbacks for the same process.
I thought I could use GetGUIThreadInfo and look at the hwndActive
member to get the current foreground window and hence the title of the
last active window. However while GetGUIThreadInfo succeeds all the
members of the structure are null. I've attached the code below in
case I'm doing something daft!
Does anyone know a way to get the title for the last active window
given either the PID or the thread ID? I presume it must be possible
as Dev Studio produces the a list of processes and window titles when
you attach the debugger to a running process.
Thanks in advance.
Philip Sharpe.
BOOL CALLBACK EnumWindowsCallback(HWND hWnd, LPARAM lParam)
{
GUITHREADINFO threadInfo;
DWORD processID;
DWORD threadID;
processID = 0;
threadID = GetWindowThreadProcessId(hWnd, &processID);
threadInfo.cbSize = sizeof(GUITHREADINFO);
if (GetGUIThreadInfo(threadID, &threadInfo))
{
// Even through the function succeeds all the members
are blank
// TO DO Get the window title
}
return TRUE;
}
You need to set the flags member of the GUITHREADINFO structure to tell
the function what to return. With no flags set, you get nothing returned.
--
-GJC [MS Windows SDK MVP]
-Software Consultant (Embedded systems and Real Time Controls)
-gcha...@mvps.org
-Abolish public schools
My apology for a wrong answer. The flags member is an output not an
input.
I think your code will return the proper information for a thread which
has the foreground. It will return NULLs for the window handles (at least
the active and focus handles) when the thread is not in the foreground.
An interesting addition to the documentation which I found in the header
file is that you can pass NULL as the thread ID to get the current
foreground and active window handles regardless of what thread is in the
foreground.
HWND GetProcessForegroundWindow(DWORD dwPid)
{
HANDLE hProcess, hThread;
HWND hwndFG;
hProcess = OpenProcess(PROCESS_CREATE_THREAD, FALSE, dwPid);
if(hProcess == 0) return 0;
hThread = CreateRemoteThread(hProcess, 0, 0, GetForegroundWindow, 0, 0,
0);
WaitForSingleObject(hThread, INFINITE);
GetExitCodeThread(hThread, (DWORD *)&hwndFG);
CloseHandle(hThread);
CloseHandle(hProcess);
return hwndFG;
}
needs error checking, havn't tested etc....just a different way to do what
you
want thats all.
-James
--
www.catch22.org.uk
Free Win32 Software, Source Code and Tutorials
"Philip Sharpe" <xko...@hotmail.com> wrote in message
news:ogvn00dlflubmpv7l...@4ax.com...
>How about:
>
>HWND GetProcessForegroundWindow(DWORD dwPid)
>{
> HANDLE hProcess, hThread;
> HWND hwndFG;
>
> hProcess = OpenProcess(PROCESS_CREATE_THREAD, FALSE, dwPid);
> if(hProcess == 0) return 0;
>
> hThread = CreateRemoteThread(hProcess, 0, 0, GetForegroundWindow, 0, 0,
>0);
>
> WaitForSingleObject(hThread, INFINITE);
> GetExitCodeThread(hThread, (DWORD *)&hwndFG);
>
> CloseHandle(hThread);
> CloseHandle(hProcess);
>
> return hwndFG;
>}
>
>needs error checking, havn't tested etc....just a different way to do what
>you
>want thats all.
Sadly GetForegroundWindow returns the current foreground window not
the topmost window for the application. What I'm after is getting the
title of the last window the user visited for all applications not
just the current active window.
James
"Philip Sharpe" <xko...@hotmail.com> wrote in message
news:vafq00dcggit8vjk8...@4ax.com...
>Hi all,
>
>I'm writing a program which needs to retrieve the window title for the
>foreground/ current/ active window in any given process. I've managed
>to get the process list and using EnumWindows retrieve information
>about all the top level windows. The first problem I have is some
>processes have more then one top level window so I receive multiple
>callbacks for the same process.
>
>I thought I could use GetGUIThreadInfo and look at the hwndActive
>member to get the current foreground window and hence the title of the
>last active window. However while GetGUIThreadInfo succeeds all the
>members of the structure are null. I've attached the code below in
>case I'm doing something daft!
>
>Does anyone know a way to get the title for the last active window
>given either the PID or the thread ID? I presume it must be possible
>as Dev Studio produces the a list of processes and window titles when
>you attach the debugger to a running process.
>
>Thanks in advance.
>
>Philip Sharpe.
Hi all,
I've managed to work out how to do this although it's a bit
convoluted.
Basically in your EnumWindows callback remember the window handles for
all the processes you're interested in. Then after that you can whip
through the saved window handles for each process and work out which
is the topmost window using GetNextWindow.
It's probably easier to understand from the code - although this is
still a little rough around the edges!
Philip Sharpe.
BOOL CALLBACK EnumWindowsCallback(HWND hWnd, LPARAM lParam)
{
CLIENTPROCESSINFOARRAY *pClientListArr =
(CLIENTPROCESSINFOARRAY *) lParam;
DWORD processID;
struct ClientProcessInfo *processInfo;
DWORD threadID;
processID = 0;
threadID = GetWindowThreadProcessId(hWnd, &processID);
// Can we find a match for the process ID?
for (int i = 0; i < pClientListArr->GetSize(); i++)
{
processInfo = pClientListArr->GetAt(i);
if (processID == processInfo->pid)
{
if (processInfo->pTopLevelWindowsArr == NULL)
processInfo->pTopLevelWindowsArr = new
CArray<HWND, HWND>;
processInfo->pTopLevelWindowsArr->Add(hWnd);
}
}
return TRUE;
}
// Generate a list of all windows opened by the clients
EnumWindows(EnumWindowsCallback, (LPARAM) &clientList);
// For every client
for (int i = 0; i < clientList.GetSize(); i++)
{
processInfo = clientList.GetAt(i);
// For every window see if it's the top of the Z order for
that process
for (int j = 0; j <
processInfo->pTopLevelWindowsArr->GetSize(); j++)
{
found = FALSE;
currentWnd =
processInfo->pTopLevelWindowsArr->GetAt(j);
// If the window is visible
if (::IsWindowVisible(currentWnd))
{
// See if it's at the top of the Z order
nextWnd = ::GetNextWindow(currentWnd,
GW_HWNDPREV);
found = (nextWnd == NULL);
// While we're not at the top of the Z order
or we haven't encountered another window owned by this process
while (nextWnd != NULL && !found)
{
// Get the next (higher) window in the
Z order
nextWnd = ::GetNextWindow(currentWnd,
GW_HWNDPREV);
if (nextWnd == NULL)
{
found = TRUE;
break;
}
// If we haven't reached the top. Is
the next window owned by the process?
for (int k = 0; k <
processInfo->pTopLevelWindowsArr->GetSize(); k++)
{
if (nextWnd ==
processInfo->pTopLevelWindowsArr->GetAt(k) &&
::IsWindowVisible(nextWnd))
break;
}
currentWnd = nextWnd;
}
// If we've found the topmost window owned by
this process get the title
if (found)
{
CWnd *tmpWnd =
CWnd::FromHandle(processInfo->pTopLevelWindowsArr->GetAt(j));
tmpWnd->GetWindowText(processInfo->mainWindowTitle);
break;
}
}
}
}
This give the top window for each family of windows but that may not be
the active window.
<snip>
> This give the top window for each family of windows but that may not be
>the active window.
Very true but it's likely to be the last one the user had seen so
they've probably got a better chance of linking the title to that
program rather than the active window.
Basically I'm writing a debugger for a piece of network software and
would like to be able to attach it to the running clients, just like
you can attach the Visual Studio debugger to a running process.
Getting the exact title isn't 100% necessary but the title of the last
window the user remembers interacting with should be enough for them
to distinguish one client from another. Which should be easier than
trying to work out which client is which PID!
Philip Sharpe
Why would that be? I can think of numerous examples which violate this.
For instance, a dialog will have its controls stacked in the order that TAB
will sequence through them regardless of which one is active.