Click to See Complete Forum and Search --> : SetActiveWindow() failing


shadowx360
April 4th, 2009, 04:17 PM
Here is the complete source code for my, uh, C++ desktop organizer program for windows.


#include <windows.h>
#include <iostream>

using namespace std;

void SetActiveWND(HWND WND)
{
AttachThreadInput(GetCurrentThreadId(),GetWindowThreadProcessId(WND,NULL),true);
SetActiveWindow(WND);
AttachThreadInput(GetCurrentThreadId(),GetWindowThreadProcessId(WND,NULL),false);
}

int main()

{ RegisterHotKey(NULL,1,MOD_ALT ,VK_F3);
RegisterHotKey(NULL,2,MOD_ALT ,VK_F2);
MSG msg = {0};
HWND * hwnd,*temp,next;
char i=-1,size,TEMP;
size=10;
hwnd=new HWND[size];

while (GetMessage(&msg, NULL, 0, 0) != 0)
{ if(msg.lParam==7471105)
{
if(i>=(size-1))
{
temp=new HWND[size];
for(TEMP=0;TEMP<size;TEMP++)
{temp[TEMP]=hwnd[TEMP];}
delete [] hwnd;
size+=5;
hwnd=new HWND[size];
TEMP=size-5;
for(TEMP=0;TEMP<size;TEMP++)
{hwnd[TEMP]=temp[TEMP];}
delete [] temp;}

i++;
hwnd[i]=GetForegroundWindow();
next=GetWindow(hwnd[i],GW_HWNDNEXT);
ShowWindow(hwnd[i],SW_HIDE);
SetActiveWND(next); }
if((msg.lParam==7405569)&&(i>=0))
{ShowWindow(hwnd[i],SW_SHOWDEFAULT);
SetActiveWND(hwnd[i]);
i--;}

}
UnregisterHotKey(NULL,1);
UnregisterHotKey(NULL,2);
return 0;
}

The part I want to focus on is the function SetActiveWND() at the top of my code. According to http://msdn.microsoft.com/en-us/library/ms646311(VS.85).aspx,The SetActiveWindow function activates a window. The window must be attached to the calling thread's message queue.

I have done that with the function AttachThreadInput(http://msdn.microsoft.com/en-us/library/cc429027.aspx) that is mentioned by the MSDN documentation. However, if you compile the source, the SetActiveWND() always fails, and the window that gets unhidden is never set as the active window, just the foreground window. Any advice?

Marc G
April 5th, 2009, 03:49 AM
Try something like:
void SwitchTo(HWND hWnd)
{
HWND hPopup = GetWindow(hWnd, GW_ENABLEDPOPUP);
if (hPopup)
hWnd = hPopup;

if (!IsWindow(hWnd) || IsHungAppWindow(hWnd))
return;

if (IsIconic(hWnd))
{
PostMessage(hWnd, WM_SYSCOMMAND, SC_RESTORE, 0);
return;
}

HWND hForeground = GetForegroundWindow();
if (hWnd != hForeground)
{
BringWindowToTop(hWnd);
SetWindowPos(hWnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
// Try SetForegroundWindow
if (!SetForegroundWindow(hWnd))
{
// SetForegroundWindow failed, try with attaching input threads
if (!hForeground)
hForeground = FindWindow(_T("Shell_TrayWnd"), NULL);

DWORD idForeground = GetWindowThreadProcessId(hForeground, NULL);
DWORD idTarget = GetWindowThreadProcessId(hWnd, NULL);

AttachThreadInput(idForeground, idTarget, TRUE);

// Try SetForegroundWindow again
if (!SetForegroundWindow(hWnd))
{
// Still not working...
// Simulate two single ALT keystrokes, See LockSetForegroundWindow
INPUT inp[4];
ZeroMemory(&inp, sizeof(inp));
inp[0].type = inp[1].type = inp[2].type = inp[3].type = INPUT_KEYBOARD;
inp[0].ki.wVk = inp[1].ki.wVk = inp[2].ki.wVk = inp[3].ki.wVk = VK_MENU;
inp[0].ki.dwFlags = inp[2].ki.dwFlags = KEYEVENTF_EXTENDEDKEY;
inp[1].ki.dwFlags = inp[3].ki.dwFlags = KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP;
SendInput(4, inp, sizeof(INPUT));

SetForegroundWindow(hWnd);
}

AttachThreadInput(idForeground, idTarget, FALSE);
}
}
Sleep(50);
}

shadowx360
April 5th, 2009, 05:12 PM
Thank you for your reply. I integrated your code into mine:


#include "stdafx.h"
#include "hwnd.no.console.h"

HWND hForeground;

void SetActiveWND(HWND hWnd)
{
HWND hPopup = GetWindow(hWnd, GW_ENABLEDPOPUP);
if (hPopup)
hWnd = hPopup;

if (!IsWindow(hWnd) || IsHungAppWindow(hWnd))
return;

if (IsIconic(hWnd))
{
PostMessage(hWnd, WM_SYSCOMMAND, SC_RESTORE, 0);
return;
}

hForeground = GetForegroundWindow();
if (hWnd != hForeground)
{
BringWindowToTop(hWnd);
SetWindowPos(hWnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
// Try SetForegroundWindow
if (!SetForegroundWindow(hWnd))
{
// SetForegroundWindow failed, try with attaching input threads
if (!hForeground)
hForeground = FindWindow(_T("Shell_TrayWnd"), NULL);

DWORD idForeground = GetWindowThreadProcessId(hForeground, NULL);
DWORD idTarget = GetWindowThreadProcessId(hWnd, NULL);

AttachThreadInput(idForeground, idTarget, TRUE);

// Try SetForegroundWindow again
if (!SetForegroundWindow(hWnd))
{
// Still not working...
// Simulate two single ALT keystrokes, See LockSetForegroundWindow
INPUT inp[4];
ZeroMemory(&inp, sizeof(inp));
inp[0].type = inp[1].type = inp[2].type = inp[3].type = INPUT_KEYBOARD;
inp[0].ki.wVk = inp[1].ki.wVk = inp[2].ki.wVk = inp[3].ki.wVk = VK_MENU;
inp[0].ki.dwFlags = inp[2].ki.dwFlags = KEYEVENTF_EXTENDEDKEY;
inp[1].ki.dwFlags = inp[3].ki.dwFlags = KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP;
SendInput(4, inp, sizeof(INPUT));

SetForegroundWindow(hWnd);
}

AttachThreadInput(idForeground, idTarget, FALSE);
}
}
Sleep(50);
}
int APIENTRY _tWinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPTSTR lpCmdLine,int nCmdShow)
{RegisterHotKey(NULL,1,MOD_ALT ,VK_F3);
RegisterHotKey(NULL,2,MOD_ALT ,VK_F2);
MSG msg = {0};
HWND * hwnd,*temp,next;
char i=-1,size,TEMP;
size=10;
hwnd=new HWND[size];

while (GetMessage(&msg, NULL, 0, 0) != 0)
{ if(msg.lParam==7471105)
{
if(i>=(size-1))
{
temp=new HWND[size];
for(TEMP=0;TEMP<size;TEMP++)
{temp[TEMP]=hwnd[TEMP];}
delete [] hwnd;
size+=5;
hwnd=new HWND[size];
TEMP=size-5;
for(TEMP=0;TEMP<size;TEMP++)
{hwnd[TEMP]=temp[TEMP];}
delete [] temp;}

i++;
hwnd[i]=GetForegroundWindow();
next=GetWindow(hwnd[i],GW_HWNDNEXT);
ShowWindow(hwnd[i],SW_HIDE);
SetActiveWND(next);

}


if((msg.lParam==7405569)&&(i>=0))
{ShowWindow(hwnd[i],SW_SHOWDEFAULT);
SetActiveWND(hwnd[i]);
i--;}

}
UnregisterHotKey(NULL,1);
UnregisterHotKey(NULL,2);
}


However, your function only works for unhiding the windows, right here:

if((msg.lParam==7405569)&&(i>=0))
{ShowWindow(hwnd[i],SW_SHOWDEFAULT);
SetActiveWND(hwnd[i]);
i--;}


It doesn't work here:

hwnd[i]=GetForegroundWindow();
next=GetWindow(hwnd[i],GW_HWNDNEXT);
ShowWindow(hwnd[i],SW_HIDE);
SetActiveWND(next);


I have no idea why, the variable "next" isn't null, but if I try to do anything with it, it doesn't work. I tried using ShowWindow(next,SW_HIDE); just to see if it would work, and it didn't. But when I inserted an If statement under next=GetWindow(hwnd[i],GW_HWNDNEXT); to check if "next" is null, it said it wasn't.

Any other ideas?

Marc G
April 6th, 2009, 02:05 AM
I would suggest to use Spy++. Put a breakpoint or a message after the GetWindow statement. Check the value of next and use Spy++ to find out which window that exactly is and whether it's the correct window that you actually really want.

shadowx360
April 9th, 2009, 05:43 PM
I just tried using Spy++, and the handles GetWindow() returns cannot be found with their finder tool, but by searching I see the handles belong to the same process as the next window, so I believe those are child windows. The window caption of the hwnd returned by GetWindow is "M", and is owned by "Default IME", according to Spy++. What is this window? I see many instances of this window called "M," and is used in many different classes and applications, and includes classes like scroll bar. How can I find the whole entire next window, not just the scroll bar?