WPF-Window Topmost for own application only? - c#

The Splashscreen/Loading-Window in my WPF application is set to Topmost="True". Now this windows in on top of all other windows even when you switch to another application (because loading will take some time). I don't want this kind of behavior.
If I set Topmost="False" the window in not topmost at all. But If you switch back to my application after working with with another application my customers sometimes don't realize the Loading-Windows is still working. The application appears to be unresponsive because the Loading-Window in the background is still the active window and it is modal.
I want to have the Loading-Window topmost but only if my application is in foreground. If you switch to another program the window should disappear and reappear topmost when you switch back.

You can try to use the "Owner" property of the window, with that the splash screen will always overlap the other windows.

I think maybe a change in the loading pattern of your MainWindow might help. If you can put to time consuming part of loading the window on a background thread then you can take this path:
Show MainWindow empty or bare bones (empty fields/grid etc)
Launch async load method to get data and populate main window
Create splash screen, set owner to self and show
make sure to close splash screen when load is complete.
that should keep the splash on top while load is being processed.

To clarify I will reanswer this question:
Martin Moser's answer is the correct one.
Set the owner property like:
secondarywindow.Owner = parent;
AND set TopMost to false.

Related

Show icon in taskbar for hidden windows

When I set the main window's visibility to hidden, No icon is shown in taskbar, so I have no control over the window to show it again. I want for the application's icon to be visible even when I hide the window, and to show the window when I click it's button in the taskbar. (something like minimize behavior)
How can I achieve that using WPF and .Net 4.0 in C#?
Edit: I mean the icon in taskbar (usually in the left and middle of the horizontal taskbar) not the notifyicon in system tray.
So, based on "comments" section, what you are looking to do is minimize or hide a window but still show some windows or dialogues that the window opens. First if you want to keep your window in the task bar, you should minimize with:
this.WindowState = WindowState.Minimized
That can be called from anywhere within the form. As you mentioned, though, this will close hide any dialogues that have this window set as the parent. The key, then is to not use this window as the parent. Lets say your dialogues inherit from form. You want to use:
newWindow.Show();
I am guessing that you are calling "ShowDialog", which ties the window state to the parent window state. Try this out and hopefully it will help!
Edit
One more note: the same is actually true of MessageBoxes, but the way to control the parent form is with the first parameter of the MessageBox.Show() call. If you pass in a form as the first parameter, that will be the parent, otherwise the parent will not be set.

Window Flicker on loss of focus?

I have been working on a windows form application based in c# and I am in need of some assistance. I am trying to recreate the window flicker that most windows applications have when a form loses focus to a parent form. Best way I can explain this is open up calculator open the help window and try to click the calculator, the help window then without falling behind the calculator flickers losing and gaining the shadowing around the edges.
I have managed to regain the focus on the child window when the parent is clicked but this creates a odd flickering effect as the parent window is momentarily brought in front of the child window. I am only guessing but that effect I am looking for appears to be that the calculator is never brought in front of the help window and then the help window is simply activated and deactivated a few times.
I tried doing some searches and I have seen a few topics relating to this but none of the solutions quite match. I am fairly new to making windows form applications so there are still a things I don't understand so be patient with me if I don't understand something at first.
Thank you in advance
An elaboration on the calculator example:
1) open up calculator from windows accessories
2) in the toolbar go to the help tab and open the about calculator option
3) click on the calculator window
4) the about calculator window will then flicker while never falling behind the calculator
The only progress I have made towards this is
private void MainForm_Activated(object sender, EventArgs e)
{
if (Open == true)
{
//blink active window
_addForm.Activate(); //makes window active
}
}
The open variable is something I use to keep track of if open forms and is made true when I show another form.
In your example the About window is called a modal window. A modal window prevents the user from interacting with the parent window until it is closed. Use Form.ShowDialog instead of Form.Show to present a Form to the user as a modal window.
Make the child form modal. This means that the child must be closed properly before focus can be transferred back to the parent.

"Tint" an entire window, or alternative method of making window look inactive

I have a winforms C# application that opens multiple dialog boxes. To suit the style of the application, I have removed the default title bars for each window and created my own (with control buttons and drag-to-move function).
The problem that now faces me is that without a titlebar, the user has no way of telling which window is the 'active' window when they are manually moved apart (so they are not overlapping).
In any windows application (that uses titlebars), when you try to navigate away from a dialog box back to the main program (without closing the dialog box) - it wont let you. The border of the dialog box flashes and you hear a windows error sound. Some kind of equivalent visual feedback would be great without needing to have the default titlebars - and tinting an entire window darker seems like it would do the trick nicely.
Something like this in pseudo-code, which would nicely tint the parent window whilst a dialog is open:
// tint window now
window.ShowDialog();
// un-tint window
I have tried to place a panel covering everything with colour set to 'transparent' (with the intention of later controlling the opacity of the panel) but the transparency does not seem to work. Any other ideas of accomplishing this? Or does anyone have a better suggestion to achieve the same level of visual feedback?
Summary:
Is there any way to tint an entire window, or overlay it with a colour? If not, could anyone suggest an alternate method of making the window appear 'inactive'?
I would suggest you to create a method in forms you want to disable:
void DisableForm()
{
//some fancy color
this.BackColor = System.Drawing.Color.Khaki;
//and disable all controls owned by form, just to be sure
foreach (var s in this.Controls)
{
((Control)s).Enabled = false;
}
}
and functions which enables back those forms of course.
edit.
also you can set visibility property of controls to false

Updating the background of a hidden Windows Forms control

I have a Windows Forms control (a subclass of Panel) that serves as a panel that displays an image. The background of the control serves as the image that is displayed to the user.
The image itself is generally a screenshot of whatever is behind the application. The method of obtaining this screenshot is to hide the application and have the user press a button.
When that button is pressed, the screenshot is saved as the background of the Windows Forms control, and then the application is shown again. The background doesn't appear to update
until the control is visible again, and this causes a noticeable flicker of sorts as the old background switches to the new background. Is there a way to cause the background to
change while the control is hidden and remove this flicker?
Code:
public void updateBackground()
{
Image bg = null;
do
{
// this just gets the background using gdi32 and user32 calls
bg = Utilities.getDesktopImage();
}
while (bg == null);
// this function invokes the GUI thread to change the BackgroundImage of the
// drawPanel
drawPanel.setBackground(bg)
// drawPanel is a child control to the main Form
mainForm.show();
}
I have also tried using various forms of Refresh() and Invalidate() to get the control to update before it is shown. Application.DoEvents() seems to improve the speed, but there is still a noticible change from the old background to the new one.
Is there something that I'm missing? I can't seem to find what I'm looking for on Google, or elsewhere on StackOverflow.
Thanks.
Try moving your logic to another thread (Task, Backgroundworker or ThreadPool). This shall remove the lag you see.
The flicker occurs because (I assume) you do some relatively lengthy work in the UI thread, which blocks graphic message loop and everything "freeze" for a fraction of a second.
Are you using Win7 or Vista and is the Desktop Window Manager Service running?
Does the problem go away when the DWM is disabled (Control Panel --> Administrative Tools --> Services --> Desktop Window Manager Session Manager)?
It sounds like an issue with Aero - the way the DWM works is that the form's graphics buffer is not updated while it is hidden. The DWM stores the data from the last visible paint and doesn't refresh until the form is visible again. This causes the previous form canvas to be visible briefly until Windows gets around to repainting the changes since it was last visible (ie: the flicker).
This article discusses some of the topics :
http://blogs.msdn.com/b/greg_schechter/archive/2006/05/02/588934.aspx
There is probably a way to override some of this behaviour but I'm not familiar with it off the top of my head. Tagging this with GDI+ may help get better answers.

Get window handle underneath mouse pointer, while ignoring a semi-transparent window

I've created a semi-transparent form (60% opacity with black background color) that my app launches, maximized, over the entire screen. Basically, it casts a gray color on the entire desktop.
When the user mouses-over a window on the desktop, I want to get that window's handle (hWnd).
The easy way to do this, which is working for me, is:
Temporarily hide my form (OR, temporarily set my form's opacity to 0.0)
Call [GetCursorPos][1]
Call [WindowFromPoint][2]
Show my form again
The problem with this approach is that my form / the screen blinks, which I don't like.
I've tried to fix this in two ways:
I figure there should be a way to get the hWnd of the window directly underneath my form by calling ChildWindowFromPointEx (passing-in the hWnd of the desktop and CWP_SKIPTRANSPARENT), but it doesn't seem to work. I also played with [ChildWindowFromPoint][4] and [RealChildWindowFromPoint][5] with no success. (P.S. Raymond Chen discusses the differences between these calls, here and it seems to me that ChildWindowFromPointEx is designed to do exactly what I need)
I tried preventing the entire desktop from refreshing (kind of "freezing" the screen momentarily) by using (1) SendMessage(GetDesktopWindow(), WM_SETREDRAW, false, 0) before I hide my form and (2) SendMessage(GetDesktopWindow(), WM_SETREDRAW, true, 0) after I hide my form. This didn't work quite right: some areas of the screen would freeze, some weird black blocks would appear, etc. I do know, however, that (1) does work, because one time I called (1) and didn't call (2) and my desktop appeared completely frozen (had to reboot, even TaskMgr didn't render correctly). I also tried using SuspendLayout and ResumeLayout on my form, but I don't think they are meant to handle my case.
Any help would be greatly appreciated.
You can do the checking yourself since your need to customise beyond that what the standard functions offer.
Call EnumWindows() to get a list of top-level windows.
Remove your semi-transparent window from this list.
For each window in the list use PtInRegion() to determine whether or not the mouse is over the window. Remove any windows that don't fit the bill.
Use GetNextWindow(), starting from one of the remaining windows to walk the z-order and find out which of the candidates is at the top.

Categories