[vb2008] SetForegroundWindow not always works
[vb2008] SetForegroundWindow not always works
[vb2008] SetForegroundWindow not always works
[vb2008] SetForegroundWindow not always works
[vb2008] SetForegroundWindow not always works
[vb2008] SetForegroundWindow not always works [vb2008] SetForegroundWindow not always works [vb2008] SetForegroundWindow not always works [vb2008] SetForegroundWindow not always works [vb2008] SetForegroundWindow not always works [vb2008] SetForegroundWindow not always works [vb2008] SetForegroundWindow not always works [vb2008] SetForegroundWindow not always works
[vb2008] SetForegroundWindow not always works [vb2008] SetForegroundWindow not always works
[vb2008] SetForegroundWindow not always works
Go Back  Xtreme Visual Basic Talk > > > [vb2008] SetForegroundWindow not always works


Reply
 
Thread Tools Display Modes
  #1  
Old 09-20-2010, 10:30 AM
phil2000 phil2000 is offline
Freshman
 
Join Date: Jan 2006
Posts: 43
Default [vb2008] SetForegroundWindow don't always works


well, I have the Hwnd and the Title of every running Application with own Button on the task bar

I want to swap from them (something like Alt+tab) by the mouse wheel

I hook the mouse wheel and I find the Hwnd of the next Application, in Task bar buttons order, incrementing a Index flag

Now the problem in to put in Foregrond the new window.

I try those two codes:

Code:
Microsoft.VisualBasic.AppActivate(Title(Index))
and that code found on the web (where in effect I can find tons of SetForegroundWindow problems)...
Code:
ForceForegroundWindow(Hwnd(Index))

Private Function ForceForegroundWindow(ByVal hWnd As IntPtr) As Boolean
        Dim ThreadID1 As IntPtr
        Dim ThreadID2 As IntPtr
        Dim nRet As Integer

        ' Nothing to do if already in foreground.
        '
        If hWnd = GetForegroundWindow() Then
            Return True
        Else
            ' First need to get the thread responsible for
            ' the foreground window, then the thread running
            ' the passed window.
            '
            ThreadID1 = GetForegroundWindow()
            ThreadID2 = GetWindowThreadProcessId(hWnd, 0)
            '
            ' By sharing input state, threads share their
            ' concept of the active window.
            '
            If ThreadID1 <> ThreadID2 Then
                AttachThreadInput(ThreadID1, ThreadID2, True)
                nRet = SetForegroundWindow(hWnd)
                AttachThreadInput(ThreadID1, ThreadID2, False)
            Else
                nRet = SetForegroundWindow(hWnd)
            End If
            '
            ' Restore and repaint
            '
            If IsIconic(hWnd) Then
                ShowWindowAsync(hWnd, SW_RESTORE)
            ElseIf IsZoomed(hWnd) Then
                ShowWindowAsync(hWnd, SW_SHOW)
            Else
                ShowWindowAsync(hWnd, SW_SHOWNORMAL)
            End If
            '
            ' SetForegroundWindow return accurately reflects
            ' success.
            ForceForegroundWindow = CBool(nRet)
        End If

    End Function
both those codes work perfectly for hours after I launch my application and I do nothing but swap the windows... I swap the windows and them go in foreground without any problem.

The problem is that if I click in a window, both the codes don't work more: all I obtain is to flash incessantly the buttons on the task bar.

Evidently clicking on a window I change somtehing (Z-order???)

Now the question is: how to restore the initial settings (first run of my program) before to read the code above??

Last edited by phil2000; 09-20-2010 at 11:18 AM.
Reply With Quote
  #2  
Old 09-20-2010, 01:07 PM
AtmaWeapon's Avatar
AtmaWeapon[vb2008] SetForegroundWindow not always works AtmaWeapon is offline
Fabulous Florist

Forum Leader
* Guru *
 
Join Date: Feb 2004
Location: Austin, TX
Posts: 9,500
Default

Look carefully at the rules in the documentation for SetForegroundWindow(). Controlling the foreground window has security implications, so it is restricted to certain applications.

Odds are your application works at first because it starts off as the foreground process and receives input events. You can still change to other windows because I'd assume input focus hasn't moved to the newly focused window yet. Click on that window, and your application has lost its right to set the foreground window.

I'm sure there's a way to write something like a custom Alt+Tab switcher, but I believe it's a little more complicated than just using SetForegroundWindow().

Note this is speculation; I'm just repeating what the documentation says and using it to create a logical explanation for the behavior you are seeing. I'm not sure if there's another way to go about this, but it seems likely to me.
__________________
.NET Resources
My FAQ threads | Tutor's Corner | Code Library
I would bet money 2/3 of .NET questions are already answered in one of these three places.
Reply With Quote
  #3  
Old 09-20-2010, 05:32 PM
phil2000 phil2000 is offline
Freshman
 
Join Date: Jan 2006
Posts: 43
Default

Quote:
Originally Posted by AtmaWeapon View Post
Odds are your application works at first because it starts off as the foreground process and receives input events. You can still change to other windows because I'd assume input focus hasn't moved to the newly focused window yet. Click on that window, and your application has lost its right to set the foreground window.
The hook code obviously works even if my application is not active: in fact if I click in another application I obtain something: the buttons OF EVERY APPLICATION flash instead of display the window: the code is read but don' works.

There are tons of web pages about the SetForegroundWindow not working problems and flashing windows problems, explecially with Vista uac.

May be the easiest way to do the job should be to simulate the toolbar buttons click... but I can't find working code...

Last edited by phil2000; 09-20-2010 at 05:45 PM.
Reply With Quote
  #4  
Old 09-21-2010, 11:05 AM
AtmaWeapon's Avatar
AtmaWeapon[vb2008] SetForegroundWindow not always works AtmaWeapon is offline
Fabulous Florist

Forum Leader
* Guru *
 
Join Date: Feb 2004
Location: Austin, TX
Posts: 9,500
Default

The most polite way I can describe the behavior of focus and foreground windows is "It sucks."

In a perfect system, we wouldn't need rules regarding when you are allowed to set the foreground window: people would only use SetForegroundWindow() when there's a legitimate need. They'd also check to make sure their window is already the foreground window first, and possibly make an application option the user can enable. The only people that would skip those processes would be people writing Alt-Tab replacements or other application switchers.

Instead, we live in a world where evil and stupid people break rules. During its startup process, Lotus Notes brings itself to the foreground 3 times. Sometimes when I'm building a project, VS brings itself to the foreground every few seconds. This is very annoying because during those two long processes, I like to go read forums or something else but I can't because the stupid other application thinks it's *so* important that I have to watch it do nothing useful. Other applications are even more mean; they set timers and frequently check if they are on top and if not try to make themselves active. Guess what happens if you run two of these at once? If you're lucky, the timers are slow enough you can close one; if not you have to restart and remember not to start them at the same time.

That's not even considering the *really* evil applications. These might have a list of applications they don't like and, when you try to focus one of those, cover it up with some overlay window. This is really bad if, say, it detects when you visit your bank website in your browser and it overlays a window that looks similar. Or perhaps it could put up a fake virus scanner UI, fake filesystem view, etc. On the annoying end, it could just cover your whole screen and make sure nothing appears on top of itself. This is bad stuff.

So we have rules dictating who can bring windows to the front. Somewhere around XP or Vista, the rules got a little bump: sometimes if the window can't be brought to the front its icon in the taskbar flashes to tell you there's something important going on but the window doesn't want to/can't interrupt what you're doing. Vista UAC introduced the notion of "levels" of process, where less secure processes are not able to manipulate more secure processes.

In my experience, manipulating focus and active windows in a predictable fashion is impossible. Some of the behaviors I've seen when attempting to do so are downright schizophrenic. GDI has its own focus mechanisms, WPF has its own, other toolkits that build on it might have theirs, and functions like LockSetForegroundWindow() can make SetForegroundWindow() just not work. Except even if you call it, sometimes Windows will automatically unlock it for security reasons.

The documentation has a comment in it that notes that SetForegroundWindow() only works if your process owns the window you're trying to bring to the foreground. That's bizarre to me because clearly SetForegroundWindow() works sometimes even if you don't own that window. Why? Who knows!

My opinion is the stew of security and usability rules around controlling the foreground window create a situation in which you can only reliably view calls to SetForegroundWindow() as suggestions, not mandates. Are you checking the return value to verify that it is saying that the window was actually set to the foreground? That'd be more odd than having it not work.

I really hope someone can solve your problem, but in my experience managing focus and foreground windows is an unreliable pain in the butt.
__________________
.NET Resources
My FAQ threads | Tutor's Corner | Code Library
I would bet money 2/3 of .NET questions are already answered in one of these three places.
Reply With Quote
  #5  
Old 09-22-2010, 11:21 AM
phil2000 phil2000 is offline
Freshman
 
Join Date: Jan 2006
Posts: 43
Default

I am in accord with you, in fact I wrote:

"May be the easiest way to do the job should be to simulate the toolbar buttons click... but I can't find working code".

I have the Hwnd of the window, the button ID (if the button ID is it index.. 1 or 3 or 5 etc etc) and I have tried tons of SendMessage code found on the web to simulate the button click... no one works...

May be the most safe way should be something like ALT+TAB sendkeys (even if I have read the Vista e Seven don't like sendkey messages), but without to see the alt+tab OS window (even if for a fraction of second) and the possibility of programmatically choose the window to open (something like ALT+(TAB & TAB & TAB)).....

Last edited by phil2000; 09-22-2010 at 12:50 PM.
Reply With Quote
  #6  
Old 09-23-2010, 11:31 AM
AtmaWeapon's Avatar
AtmaWeapon[vb2008] SetForegroundWindow not always works AtmaWeapon is offline
Fabulous Florist

Forum Leader
* Guru *
 
Join Date: Feb 2004
Location: Austin, TX
Posts: 9,500
Default

I'm not going to reiterate the security implications. I've already been through them twice. Instead I'm going to restate the important part.

I am certain the problem is not XP, not Vista, and not Windows 7. I've been through all of the documentation several times to the extent that I think the ForceSetForegroundWindow() from the guy in the MSDN comments is just a bunch of extra effort based on nothing but superstition. Why am I so sure?

I've attached the reason. What I've attached sounds almost exactly like what you have specified your application does, albeit a little less elegant and not using the taskbar interface to get window titles. I wrote it in C# because it felt more comfortable and it's meant to be a "run it and see if it fails the same way" example rather than a "copy this code" example. Click the "Refresh" button and you get a list of every main process's main window title (if it has a main window). Double-click an item in the list or select an item and click the "Focus" button, and that window will be brought to the foreground. If you select an item in the list and click the "Timer" button, the application waits 5 seconds before switching the foreground window.

Now this is where it gets interesting. If Mr. Shelly is correct and this is only valid for windows that the process owns, I ought not to be able to switch from my application to Notepad without doing some footwork to make it look like the call happens from Notepad's thread. Instead, Notepad comes to the front. Hmm. What about if my application isn't the foreground? I selected my email client, clicked the "Timer" button, then minimized the switcher and started typing in this text editor. Within seconds, my email client was in focus. Hmm. What about applications protected by UAC? I started an elevated command prompt, set the timer to switch to the text editor, then started working in the command prompt. The text editor came to the front. Maybe you can't bring forth elevated apps? Nope, that worked to. I could find *no* circumstances in which I was unable to bring a window to the foreground (though I admit I didn't fool with LockSetForegroundWindow().)

Note I did this both in the Debug build with the debugger attached and in the Release build with no debugger. It had no effect.

So based on the documentation *and* my personal experience, I am going to say with certainty that something is wrong in your code or on your machine that causes you to lose the ability to set the foreground window. There's practically no way for anyone to determine what's going on from this side; the only way I can see making any progress is if you post the code and instructions for how to make it stop switching windows. Alternatively, find a forum that specializes in Windows API; maybe someone there can think of a scenario where SetForegroundWindow() will stop working.

I am almost certain that attempting to simulate clicks on the taskbar buttons would be *more* suspicious to the system than calls to SetForegroundWindow() and thus more likely to fail, but already I'm not seeing the documented rules being enforced strictly so I have no idea; it might work. But I think it's better to figure out why your straightforward approach has issues.
Attached Files
File Type: zip Switcher.zip (11.1 KB, 28 views)
__________________
.NET Resources
My FAQ threads | Tutor's Corner | Code Library
I would bet money 2/3 of .NET questions are already answered in one of these three places.
Reply With Quote
  #7  
Old 09-24-2010, 12:07 PM
phil2000 phil2000 is offline
Freshman
 
Join Date: Jan 2006
Posts: 43
Default

DONE!

ty to this web page

http://www.tek-tips.com/faqs.cfm?fid=4262

I have changed my code in

Code:
            ThreadID1 = GetWindowThreadProcessId(GetForegroundWindow(), 0)
            ThreadID2 = GetCurrentThreadId()
            '
            ' By sharing input state, threads share their
            ' concept of the active window.
            '
            If ThreadID1 <> ThreadID2 Then
                AttachThreadInput(ThreadID1, ThreadID2, True)
                nRet = BringWindowToTop(hWnd)
                ShowWindow(hWnd, SW_SHOWNORMAL)
                AttachThreadInput(ThreadID1, ThreadID2, False)
            Else
                nRet = BringWindowToTop(hWnd)
                ShowWindow(hWnd, SW_SHOWNORMAL)
            End If
and seems to work well

Last edited by phil2000; 09-24-2010 at 12:46 PM.
Reply With Quote
Reply


Currently Active Users Viewing This Thread: 1 (0 members and 1 guests)
 
Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off

Forum Jump

Advertisement:





Free Publications
The ASP.NET 2.0 Anthology
101 Essential Tips, Tricks & Hacks - Free 156 Page Preview. Learn the most practical features and best approaches for ASP.NET.
subscribe
Programmers Heaven C# School Book -Free 338 Page eBook
The Programmers Heaven C# School book covers the .NET framework and the C# language.
subscribe
Build Your Own ASP.NET 3.5 Web Site Using C# & VB, 3rd Edition - Free 219 Page Preview!
This comprehensive step-by-step guide will help get your database-driven ASP.NET web site up and running in no time..
subscribe
[vb2008] SetForegroundWindow not always works
[vb2008] SetForegroundWindow not always works
[vb2008] SetForegroundWindow not always works [vb2008] SetForegroundWindow not always works
[vb2008] SetForegroundWindow not always works
[vb2008] SetForegroundWindow not always works
[vb2008] SetForegroundWindow not always works [vb2008] SetForegroundWindow not always works [vb2008] SetForegroundWindow not always works [vb2008] SetForegroundWindow not always works [vb2008] SetForegroundWindow not always works [vb2008] SetForegroundWindow not always works [vb2008] SetForegroundWindow not always works
[vb2008] SetForegroundWindow not always works
[vb2008] SetForegroundWindow not always works
 
[vb2008] SetForegroundWindow not always works
[vb2008] SetForegroundWindow not always works
 
-->