I want to make a window created with
CreateWindowEx(WS_EX_TOOLWINDOW | WS_EX_LAYERED, wc.lpszClassName, 0, WS_POPUP | WS_VISIBLE | WS_SYSMENU, ...);
a part of the desktop. (I know this may be impossible, but I want to get as close as possible to this feeling).
Thus, I need that when WIN+D is hit (or when bottom-right of the screen Show desktop button is clicked), the window should not be hidden.
How to prevent the window to be hidden when showing desktop with WIN+D?
Note: I initially thought it was possible by preventing the window to be minimized
(https://stackoverflow.com/questions/27781352/prevent-window-to-be-minimized?noredirect=1#comment43975051_27781352) but as pointed by some users, it seems
that it is another problem.
It is possible to make the window part of the desktop by doing:
HWND hwndOwner = GetWindow(GetWindow(GetTopWindow(0), GW_HWNDLAST), GW_CHILD);
SetWindowLong(hwndMain, GWL_HWNDPARENT, (LONG) hwndOwner);
Also try another test: http://files.rsdn.ru/42164/quasi_owner.zip (exe + sources, tested on Win7-x86).
1st version (not really working):
It is enough remove WS_MINIMIZEBOX & add WS_EX_TOPMOST
Related
I have a CPropertySheet.
When I use
ModifyStyle(DS_MODALFRAME, WS_POPUP | WS_THICKFRAME | WS_MAXIMIZEBOX);
inside an OnCreate handler everything is fine. The created window behaves as expected and is resizable.
When I use the same code, just a tick later in CPropertySheet::OnInitDialog than this code has only the effect that the correct frame is shown, also the cursor changes when I drag over the window border. But there is no resize feature.
Same happens for a CDialog when uses in OnInitDialog. Seams that some flags can't be changed after a window is created.
Is there more information about this problem?
You need to set the nFlags parameter to SWP_FRAMECHANGED and maybe also SWP_DRAWFRAME in your call to ModifyStyle. This way it will call SetWindowPos internally, which will apply the new style. You also need to remove WS_SYSMENU instead of DS_MODALFRAME.
Example:
ModifyStyle(WS_SYSMENU, WS_POPUP | WS_THICKFRAME | WS_MAXIMIZEBOX, SWP_FRAMECHANGED);
I know this sounds evil but my intention is not this at all.
A user has clicked "delay shot" and a countdown starts, during that time they go focus another application, then after countdown user expects my app to take back focus.
SetForegroundWindow fails when it runs from appliction with PID X while application with PID Y is focused.
This worked to bring my window forward, but it doesn't get focus:
SetWindowPos(hwnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE);
It sets the window to be always on top. However focus is not put into my window. And then setting it back to HWND_NOTOPMOST leaves it there, even though its not top most, but it still doesnt have focus. Running SetForegroundWindow won't do the trick after these calls to SetWindowPos Is there anyway to steal focus?
I have tried a combination of:
SwitchToThisWindow
SetWindowPos
ShowWindow
SetForegroundWindow
But can't seem to figure it out.
Another reason I think this has to be possible is because Mac OSX allows it with NSApplication activateIgnoringOtherApps: and Linux's allow it too. I'd like to get this cross platform.
As a last resort I was going to use the HWND_TOPMOST method, then GetWindowRect then SetCursorPos and send single click to my window at pos 0,0, I really don't want to though as there might be something at 0,0 and it shouldn't be auto clicked on.
This always works, no matter what app is in foreground (like Task Manager, etc.):
AllocConsole();
auto hWndConsole = GetConsoleWindow();
SetWindowPos(hWndConsole, 0, 0, 0, 0, 0, SWP_NOZORDER);
FreeConsole();
SetForegroundWindow(hWnd);
As the comment says, SetForegroundWindow is sometimes useless intentionally. Basically, two ways are used to bypass restrictions:
Simulate keyboards / mouses
Get privileges
There is some smarter magic to achieve the goal without directly clicking the window you are going to activate. Since I'm not familiar with GUI, I would suggest inject code directly into current foreground window and hand over the foreground right.
Besides there're some examples on simulating.
http://www.codeproject.com/Tips/76427/How-to-bring-window-to-top-with-SetForegroundWindo.aspx
Is it possible create MFC form that cold stay on the top of all applications on PC not allowing to do anything else without entering required information.
Win32 doesn't support system-modal dialogs any more, as far as I'm aware. This is a relic from 16 bit Windows versions.
You can try yourself with a MB_SYSTEMMODAL type MessageBox.
Closest thing would be to utilize a screen-sized window to display a dimmed desktop background while your dialog is shown. This simulates the behaviour of the user account control -- except that you still can switch tasks.
You can obtain something similar setting your window on "TopMost". You can do it on property sheet in design mode, or programmatically with this line:
SetWindowPos( pWnd->m_hWnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE );
Hope this will fit your needs.
I am having trouble with SetWindowPos failing to bring windows of external processes to the top of the z-order reliably. I am able to bring windows to the front like:
NativeMethods.SetWindowPos(hwnd, new IntPtr(-1), Left, Top, Width, Height, 0x10);
NativeMethods.SetWindowPos(hwnd, new IntPtr(-2), Left, Top, Width, Height, 0x10);
It doesn't work 100% of the time though. After some reading, I found a few things.
SetWindowPos documentation states:
To use SetWindowPos to bring a window to the top, the process that owns the window must have SetForegroundWindow permission.
An article on MSDN then states
A process that is started with UIAccess rights has the following abilities:
* Set the foreground window.
AllowSetForeground mentions
The calling process must already be able to set the foreground window
I have signed my .exe and enabled UIAccess so that I can set the foreground window like so in my manifest:
<requestedExecutionLevel level="highestAvailable" uiAccess="true" />
My program starts and I get the UAC prompt asking for permission. I then test for UIAccess, admin rights, and TokenElevationType. The first 2 return true, and the 3rd returns TokenElevationTypeFull. I still run into the same problems though with my new code though.
My code is:
uint processid=0;
NativeMethods.GetWindowThreadProcessId(hwnd, out processid);
NativeMethods.AllowSetForegroundWindow((int)processid);
NativeMethods.SetWindowPos(hwnd, IntPtr.Zero, Left, Top, Width, Height, 0x10);
NativeMethods.RedrawWindow(hwnd, IntPtr.Zero, IntPtr.Zero, NativeMethods.RedrawWindowFlags.Erase | NativeMethods.RedrawWindowFlags.Invalidate | NativeMethods.RedrawWindowFlags.NoChildren);
NativeMethods.RedrawWindow(hwnd, IntPtr.Zero, IntPtr.Zero, NativeMethods.RedrawWindowFlags.Erase | NativeMethods.RedrawWindowFlags.Invalidate | NativeMethods.RedrawWindowFlags.UpdateNow | NativeMethods.RedrawWindowFlags.AllChildren);
What you want to do is contrary to the (complicated) rules Windows has in place to prevent badly-behaved programs from wresting control away from the user. (Control doesn't just mean input focus, but also control of what's visible and what's not.) Although your intentions may be aligned with the user's, what you're asking for is indistinguishable from what disruptive programs often try to do.
There are alternative ways to signal the user that non-foreground windows need attention. Check out FlashWindowEx, for example. You might also consider a tray icon that pops notification balloons. These seem like they'd be appropriate and effective solutions.
I have an application that compiles ok (mingw) and runs ok, however the edit control that is created has scroll bars but the vertical scroll bar doesn't do anything. The same executable works fine on WinXP. Also, the edit control has both vertical and horizontal scroll bars, the horizontal works just fine, but vertical does not. The vertical scroll bar is visible and clickable, but nothing happens...
Following code is used when creating the edit control:
HWND hwndEdit = CreateWindow(TEXT("EDIT"), TEXT("Edit control"),
WS_OVERLAPPED | WS_VISIBLE | WS_HSCROLL | WS_VSCROLL | ES_LEFT | ES_MULTILINE |
ES_AUTOHSCROLL | ES_AUTOVSCROLL | ES_READONLY | WS_SIZEBOX,
1000, 480, 400, 500, NULL, 0, GetModuleHandle(NULL), NULL);
SendMessage(hwndEdit, WM_SETTEXT, 0, (LPARAM) TEXT(""));
SendMessage(hwndEdit, EM_LIMITTEXT, 0, 0);
Following code is used repeatedly to add text to edit control:
char test[] = "test";
SendMessage(hWndDbg, EM_SETSEL, 0x7FFFFFFF, 0x7FFFFFFF); // Undo any selection and move to end.
SendMessage(hWndDbg, EM_REPLACESEL, 0, (LPARAM) temp);
Finally found the fix. It seems in WinXP the edit control does not have to have a parent window defined, in Win7 it is required for the vertical scroll bar to work, horizontal scroll bar works in Win7 even without parent window defined.
Note that vertical scroll bars even make sense on single-line edit controls. In this case, WM_VSCROLL must be set, and ES_AUTOVSCROLL not. (EM_AUTOVSCROLL means EM_AutoHIDEVScroll.) The alternative UpDown control makes more programming efford than capturing VM_VSROLL messages, and then changing the (typically numerical) value inside the edit control.
Unluckily, the MS Visual Studio built-in Resource Editor won't let you add WM_VSROLL to single-line edits! You must do this by adding this bit by editing the .RC file in text mode.
Similar to the fact that this Resource Editor won't let you add a default text to the control, which is still supported by the resource loader.
Use GetDesktopWindow() as hWndParent parameter. It works on Win7.