Hello Alexandre,
> Yes, if it works under Windows then obviously we need a fix in Wine.
> I think you should investigate exactly how Windows does it, there are
> many places where we could add such checks so we need to find out
> exactly where Windows has them.
OK - wrote a little test program to see, how SetShellWindow() exactly works on
Windows. It creates a few windows and tests, what happens when trying to register them
as shell window. To run it you have to terminate Windows Explorer at first. Then the
output is this the following:
first call to SetShellWindow(hwnd): SUCCESS
second call to SetShellWindow(hwnd): FAILURE
reset shell window by SetShellWindow(0): FAILURE
third call to SetShellWindow(hwnd): FAILURE
SetWindowExStyle(hwnd, WS_EX_TOPMOST): FAILURE
DestroyWindow(hwnd): SUCCESS
SetShellWindow(hwnd2) with WS_EX_TOPMOST: FAILURE
SetShellWindow(hwnd3): SUCCESS
SetWindowPos(hwnd3, HWND_TOPMOST): SUCCESS
SetWindowPos(hwnd3, hwnd4: SUCCESS
SetShellWindow(hwnd4): FAILURE
SetWindowPos(hwnd3, hwnd5): SUCCESS
So we have to taking following rules into account for the SetShellWindow/Ex()
implementation:
- SetShellWindow() only succeedes if there is not yet a registered shell window.
- A successfull call moves the window into the background. It becomes the window with
the lowest Z-order. This can't be changed by a call to SetWindowPos() or similar
functions. The shell window remains at the bottom for ever.
- Shell windows can't be reset by calling SetShellWindow(0). To change the shell
window, the current window has to be destroyed.
- Shell windows must not have the extended style bit WS_EX_TOPMOST set. It it is set,
SetShellWindow() failes. If you try to set this bit after registering a window as
shell window, the bit is ignored and automatically set to zero.
- If you try to move the window into the foreground by calling SetWindowPos() with
HWND_TOPMOST this call succeedes, but it does not change anything. The window remains
in the background.
--
Martin Fuchs
[EMAIL PROTECTED]
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <iostream>
using namespace std;
static BOOL (WINAPI*SetShellWindow)(HWND);
static BOOL (WINAPI*SetShellWindowEx)(HWND, HWND);
int main()
{
HINSTANCE shell32 = GetModuleHandle(TEXT("user32")); // or LoadLibrary()
SetShellWindow = (BOOL(WINAPI*)(HWND)) GetProcAddress(shell32,
"SetShellWindow");
SetShellWindowEx = (BOOL(WINAPI*)(HWND,HWND)) GetProcAddress(shell32,
"SetShellWindowEx");
HMODULE hinst = GetModuleHandle(0);
HWND hwnd = CreateWindowEx(0, TEXT("#32770"), TEXT("TEST1"),
WS_OVERLAPPEDWINDOW|WS_VISIBLE, 100, 100, 300, 200, 0, 0, hinst, 0);
BOOL ret = SetShellWindow(hwnd);
cout << "first call to SetShellWindow(hwnd): " << (ret? "SUCCESS": "FAILURE")
<< "\n";
ret = SetShellWindow(hwnd);
cout << "second call to SetShellWindow(hwnd): " << (ret? "SUCCESS": "FAILURE")
<< "\n";
ret = SetShellWindow(0);
cout << "reset shell window by SetShellWindow(0): " << (ret? "SUCCESS":
"FAILURE") << "\n";
ret = SetShellWindow(hwnd);
cout << "third call to SetShellWindow(hwnd): " << (ret? "SUCCESS": "FAILURE")
<< "\n";
SetWindowLong(hwnd, GWL_EXSTYLE,
GetWindowLong(hwnd,GWL_EXSTYLE)|WS_EX_TOPMOST);
ret = GetWindowLong(hwnd,GWL_EXSTYLE)&WS_EX_TOPMOST? TRUE: FALSE;
cout << "SetWindowExStyle(hwnd, WS_EX_TOPMOST): " << (ret? "SUCCESS":
"FAILURE") << "\n";
ret = DestroyWindow(hwnd);
cout << "DestroyWindow(hwnd): " << (ret? "SUCCESS": "FAILURE") << "\n";
HWND hwnd2 = CreateWindowEx(WS_EX_TOPMOST, TEXT("#32770"), TEXT("TEST2"),
WS_OVERLAPPEDWINDOW|WS_VISIBLE, 150, 250, 300, 200, 0, 0, hinst, 0);
ret = SetShellWindow(hwnd2);
cout << "SetShellWindow(hwnd2) with WS_EX_TOPMOST: " << (ret? "SUCCESS":
"FAILURE") << "\n";
HWND hwnd3 = CreateWindowEx(0, TEXT("#32770"), TEXT("TEST3"),
WS_OVERLAPPEDWINDOW|WS_VISIBLE, 200, 400, 300, 200, 0, 0, hinst, 0);
ret = SetShellWindow(hwnd3);
cout << "SetShellWindow(hwnd3): " << (ret? "SUCCESS": "FAILURE") << "\n";
ret = SetWindowPos(hwnd3, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOSIZE|SWP_NOMOVE);
cout << "SetWindowPos(hwnd3, HWND_TOPMOST): " << (ret? "SUCCESS": "FAILURE")
<< "\n";
HWND hwnd4 = CreateWindowEx(0, TEXT("#32770"), TEXT("TEST4"),
WS_OVERLAPPEDWINDOW|WS_VISIBLE, 250, 500, 300, 200, 0, 0, hinst, 0);
cout << "SetWindowPos(hwnd3, hwnd4: " << (ret? "SUCCESS": "FAILURE") << "\n";
ret = SetShellWindow(hwnd4);
cout << "SetShellWindow(hwnd4): " << (ret? "SUCCESS": "FAILURE") << "\n";
HWND hwnd5 = CreateWindowEx(0, TEXT("#32770"), TEXT("TEST5"),
WS_OVERLAPPEDWINDOW|WS_VISIBLE, 300, 600, 300, 200, 0, 0, hinst, 0);
ret = SetWindowPos(hwnd3, hwnd5, 0, 0, 0, 0, SWP_NOSIZE|SWP_NOMOVE);
UpdateWindow(hwnd3);
UpdateWindow(hwnd4);
GdiFlush();
cout << "SetWindowPos(hwnd3, hwnd5): " << (ret? "SUCCESS": "FAILURE") << "\n";
MSG msg;
while(GetMessage(&msg, 0, 0, 0)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return 0;
}