| |
| Author |
Message |
Mark
Joined: 05 May 2005
Posts: 13
Location: Novato, CA
|
Posted:
Thu Dec 29, 2005 5:18 PM |
  |
Once upon a time Microsoft decided these functions would no longer bring things to the foreground on Windows (about the time of Windows ME). Instead, these functions would make the taskbar button of the program or window flash incessantly.
This is all well and good, and I'm sure there were good intentions behind it, but quite frankly, it's annoying when your app is supposed to come to the foreground and it doesn't.
I found this problem while developing in .NET, so most of my code will be heavy on that side, but should easily be convertable to non-.NET (in fact, I'll be showing you the exact DLL's the functions are in, so you can just write language specific binding as an exercise ).
The Managed C++ Code that doesn't work:
| Code: |
| ((System.Windows.Forms.Form *) myForm)->Focus() |
The C# Code that doesn't work:
This just flashes myForm's taskbar button (although this behavior can be changed by editing the registry, this is the default behavior). What we want to do is force our form to the foreground. Initially, one would suspect that a lower level call to SetForegroundWindow() would do this, but it does not. It's result is the same. Instead, we have to temporarily modify the system's parameter that defines the behavior we don't like.
In Managed C++, we can do this:
| Code: |
::SystemParametersInfo(SPI_SETFOREGROUNDLOCKTIMEOUT, 0, (LPVOID)0, SPIF_SENDWININICHANGE | SPIF_UPDATEINIFILE);
::ShowWindowAsync((HWND) window->Handle.ToPointer(), WS_SHOWNORMAL);
::SetForegroundWindow((HWND) window->Handle.ToPointer());
::SystemParametersInfo(SPI_SETFOREGROUNDLOCKTIMEOUT, 200000, (LPVOID)0, SPIF_SENDWININICHANGE | SPIF_UPDATEINIFILE); |
In C# we need to define:
| Code: |
[DllImport("user32.dll", EntryPoint="SystemParametersInfo")]
public static extern bool SystemParametersInfo(uint uiAction, uint uiParam, uint pvParam, uint fWinIni);
[DllImport("user32.dll", EntryPoint="SetForegroundWindow")]
public static extern bool SetForegroundWindow(IntPtr hWnd);
[DllImport("User32.dll", EntryPoint="ShowWindowAsync")]
private static extern bool ShowWindowAsync(IntPtr hWnd, int cmdShow);
private const int WS_SHOWNORMAL = 1; |
and later use:
| Code: |
SystemParametersInfo( (uint) 0x2001, 0, 0, 0x0002 | 0x0001);
ShowWindowAsync(window.Handle, WS_SHOWNORMAL);
SetForegroundWindow(window.Handle);
SystemParametersInfo( (uint) 0x2001, 200000, 200000, 0x0002 | 0x0001); |
This all seems like a bunch of arcanum, but it's fairly simply explained.
The first call to SystemParametersInfo tells Windows that we don't want to flash the taskbar button, we want to bring our window to the foreground instead.
The call to ShowWindowAsync brings the window out of minimized state, if necessary.
The call to SetForegroundWindow will now actually bring our window to the foreground.
The second call to SystemParametersInfo tells Windows that we want to go back to the default, which is flashing the taskbar button.
If you notice, in the C# code, we have to tell C# how to find these functions. All three of these functions are contained in the User32.DLL file. The SystemParametersInfo() function expects all unsigned integers, so the marshalling here is no problem. The ShowWindowAsync() and the SetForegroundWindow() functions both want an HWND as their first argument, which, when it comes down to it, is a pointer -- which we can just marshall as an IntPtr (which happens to be the type for the Form.Handle property). ShowWindowAsync() expects an integer value representing a particular command to perform on the form we gave it. We simply define the only one we care about WS_SHOWNORMAL (value of 1); this value instructs ShowWindowAsync() to show our form, well, 'normally'.
A way to improve the above code would be to store the current value of the system parameter and write it back in. This is left as an exercise. |
_________________ Please note, though I still support the Mapwing Project, I am no longer part of the Mapwing Team at this time. |
|
   |
 |
pappe82
Joined: 30 Jan 2009
Posts: 1
|
Posted:
Fri Jan 30, 2009 6:34 AM |
  |
Unfortunately, this hint did not help solving my "flashing" problem.
my final solution was then to use two more exports out of user32.dll called "bool IsIconic(HWND handle)" and "bool IsZoomed(HWND handle)" so i can determine the actual state of the window (if not zoomed and not iconic, well, you need simple logic to determine the window state as normal )
then I set the state to minimized first and directly back to the original, this works for me an i don't need the call to SystemParametersInfo and works even without flicker.
Maybe this is helpful for anybody else!?! |
|
|
  |
 |
|
|
|
View next topic
View previous topic
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
All times are GMT - 5 Hours
|
|