This question already has answers here:
What is the "right" way to bring a Windows Forms Application to the foreground?
(12 answers)
Closed 4 years ago.
How do I take a form that is currently minimized and restore it to its previous state. I can't find any way to determine if its previous WindowState was Normal or Maximized; but I know the information has to be stored somewhere because windows doesn't have a problem doing it with apps on the taskbar.
There is no managed API for this. The way to do it is to PInvoke GetWindowPlacement and check for WPF_RESTORETOMAXIMIZED.
For details, see this Microsoft How To (which is demonstrating the technique in VB).
In C#, this would be:
[DllImport("user32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool GetWindowPlacement(IntPtr hWnd, ref WINDOWPLACEMENT lpwndpl);
private struct WINDOWPLACEMENT
{
public int length;
public int flags;
public int showCmd;
public System.Drawing.Point ptMinPosition;
public System.Drawing.Point ptMaxPosition;
public System.Drawing.Rectangle rcNormalPosition;
}
public void RestoreFromMinimzied(Form form)
{
const int WPF_RESTORETOMAXIMIZED = 0x2;
WINDOWPLACEMENT placement = new WINDOWPLACEMENT();
placement.length = Marshal.SizeOf(placement);
GetWindowPlacement(form.Handle, ref placement);
if ((placement.flags & WPF_RESTORETOMAXIMIZED) == WPF_RESTORETOMAXIMIZED)
form.WindowState = FormWindowState.Maximized;
else
form.WindowState = FormWindowState.Normal;
}
this.WindowState = FormWindowState.Normal;
You also have:
this.WindowState = FormWindowState.Minimized;
this.WindowState = FormWindowState.Maximized;
Ah, I misunderstood the question:
Restore WindowState from Minimized should be what you're looking for. It says you can mimic the taskbar behavior like this:
SendMessage(form.Handle, WM_SYSCOMMAND, SC_RESTORE, 0);
You can track the window state changes through the Resize event. Like this:
public partial class Form1 : Form {
public Form1() {
InitializeComponent();
prevState = currState = this.WindowState;
}
protected override void OnResize(EventArgs e) {
if (currState != this.WindowState) {
prevState = currState;
currState = this.WindowState;
}
base.OnResize(e);
}
private FormWindowState prevState, currState;
}
If you want to store the previous state whenever there's a change (maximize/minimize), you'll have to hook into the SizeChanged event, according to this post on MSDN. You can get the WindowState there and store it.
Related
I have a singletone instance of window in my WPF application (which is not main window). Due to it's structure, this window only closes when the main window is closed; If the user closes this window, it becomes hidden. When I click on some image in main window, I want the following behaviour of second window:
If window is hidden and image was clicked, I want to show it on top of all windows (but NOT by setting Topmost = true, I want just SHOW it on top, rather than fix it on top forever).
If window is shown on top, there is nothing to do.
If window is open, but covered by other window or minimized, I also want to show it on top only ONCE.
What I have at the moment:
// In some application class
private void Image_MouseDown(object sender, MouseButtonEventArgs e)
{
if (App.Current.MyWindow == null)
{
App.Current.MyWindow = WeightImageWindowView.Instance;
}
App.Current.MyWindow.ShowTop();
}
...
// in MyWindow class
public void ShowTop()
{
this.Topmost = true;
this.Show();
if (this.WindowState == WindowState.Minimized)
{
this.WindowState = WindowState.Normal;
}
var a = this.Activate();
var b = this.Focus();
this.Topmost = false;
}
I tried to use all these commands one by one, in pairs and all together, but didn't get the behaviour described above.
WndHelper.BringToFront(this);
Use the helper below and just call bringtofront
public class WndHelper
{
[DllImport("User32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool SetForegroundWindow(IntPtr hWnd);
[DllImport("User32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool ShowWindow(IntPtr hWnd, uint nCmdShow);
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool IsIconic(IntPtr hWnd);
public static void HideWindow(Window window)
{
var wih = new WindowInteropHelper(window);
WndHelper.ShowWindow(wih.Handle, 0);
}
public static void BringToFront(Window window)
{
var wih = new WindowInteropHelper(window);
BringToFront(wih.Handle);
}
//If the window is minimized, then Restore must be run first
//Windows that are in the background are enough to set as Foreground
public static void BringToFront(IntPtr hWnd)
{
if (hWnd == IntPtr.Zero)
return;
try
{
if (WndHelper.IsIconic(hWnd)) //the window is minimized
{
WndHelper.ShowWindow(hWnd, 9); // SW_RESTORE = 9
WndHelper.SetForegroundWindow(hWnd); // set window to foreground
}
else
WndHelper.SetForegroundWindow(hWnd);
}
catch { }
}
}
Thanks #Villiam! I found the following solution:
Set MyWindow.ShowActivated = true;
Rewrite ShowTop method as:
public void ShowTop()
{
if (this.WindowState == WindowState.Minimized)
{
this.WindowState = WindowState.Normal;
}
this.Topmost = true;
this.Show();
this.Topmost = false;
}
i have a windows desktop application with c# and framework 4.6
the app run in system tray and there is a shortcut icon on desktop
when user click the icon to run it if the app already run dont run new instance, only show (bring to front) existing app
public sealed class SingleInstance
{
private const int SW_HIDE = 0;
private const int SW_SHOW = 5;
public static bool AlreadyRunning()
{
bool running = false;
try
{
// Getting collection of process
Process currentProcess = Process.GetCurrentProcess();
// Check with other process already running
foreach (var p in Process.GetProcesses())
{
if (p.Id != currentProcess.Id) // Check running process
{
if (p.ProcessName.Equals(currentProcess.ProcessName) == true)
{
running = true;
IntPtr hFound = p.MainWindowHandle;
if (User32API.IsIconic(hFound)) // If application is in ICONIC mode then
User32API.ShowWindow(hFound, User32API.SW_RESTORE);
User32API.SetForegroundWindow(hFound); // Activate the window, if process is already running
break;
}
}
}
}
catch { }
return running;
}
}
public class User32API
{
[DllImport("User32.dll")]
public static extern bool IsIconic(IntPtr hWnd);
[DllImport("User32.dll")]
public static extern bool SetForegroundWindow(IntPtr hWnd);
[DllImport("User32.dll")]
public static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);
public const int SW_SHOW = 5;
public const int SW_RESTORE = 9;
}
if app run back of the any windows it can show (bring to front) but it in system tray cant show
EDIT:
minimize to tray
private void Form1_Resize(object sender, EventArgs e)
{
if (this.WindowState == FormWindowState.Minimized)
{
Hide();
}
}
to open
private void notifyIcon1_Click(object sender, EventArgs e)
{
this.WindowState = FormWindowState.Minimized;
this.Show();
this.WindowState = FormWindowState.Normal;
}
You can implement a Mutex to make sure there is only one instance of your application running. You can also use it to communicate between instances so the second instance can notify the first one that the user attempted to start your app a second time.
There is already a really good answer to this over here: https://stackoverflow.com/a/522874/14877741
It explains the Mutex concept a lot better than I could and it even has an example that brings the application window back to the foreground.
I have a winforms application where I want the close button in the top-right corner of the program to instead minimize the program.
I have been able to achieve this by using the form's FormClosing event like this:
this.Hide();
e.Cancel = true;
But this unfortunately also stops any other close buttons I place on the form.
Is there a way to only stop the default button in the top-right but still be able to close the form elsewhere?
This is a simple boolean example:
bool ExitApplication = false;
private void Form1_FormClosing(Object sender, FormClosingEventArgs e)
{
switch(ExitApplication)
{
case false:
this.Hide();
e.Cancel = true;
break;
case true:
break;
}
}
So when you want to close your application just set ExitApplication to true.
Use this to disable close button from your form at top right corner.
public partial class Form1 : Form
{
const int MfByposition = 0x400;
[DllImport("User32")]
private static extern int RemoveMenu(IntPtr hMenu, int nPosition, int wFlags);
[DllImport("User32")]
private static extern IntPtr GetSystemMenu(IntPtr hWnd, bool bRevert);
[DllImport("User32")]
private static extern int GetMenuItemCount(IntPtr hWnd);
public Form1()
{
InitializeComponent();
var hMenu = GetSystemMenu(Handle, false);
var menuItemCount = GetMenuItemCount(hMenu);
RemoveMenu(hMenu, menuItemCount - 1, MfByposition);
...
}
}
Another way to disable the "X" in the top right:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
protected override CreateParams CreateParams
{
get
{
const int CS_NOCLOSE = 0x200;
CreateParams cp = base.CreateParams;
cp.ClassStyle |= CS_NOCLOSE;
return cp;
}
}
}
The form can still be closed programmatically with this.Close();.
This question already has answers here:
How do I make a WinForms app go Full Screen
(10 answers)
C# Fullscreen, hiding the taskbar
(2 answers)
Closed 9 years ago.
I have WinForm application and i want to enter fullscreen mode and remove all bars and the task bar.
i done it with this:
this.WindowState = FormWindowState.Maximized;
this.FormBorderStyle = FormBorderStyle.None;
this.TopMost = true;
The top bar is really hidden but the Windows TaskBar is still visible.
Any idea what can be the trouble?
Run with full screen you can use this method..
private void Form1_Load(object sender, EventArgs e)
{
this.TopMost = true;
this.FormBorderStyle = FormBorderStyle.None;
this.WindowState = FormWindowState.Maximized;
}
To Hide TaskBar Just add this class into your project .it works as you expected.
using System;
using System.Runtime.InteropServices;
public class Taskbar
{
[DllImport("user32.dll")]
private static extern int FindWindow(string className, string windowText);
[DllImport("user32.dll")]
private static extern int ShowWindow(int hwnd, int command);
[DllImport("user32.dll")]
public static extern int FindWindowEx(int parentHandle, int childAfter, string className, int windowTitle);
[DllImport("user32.dll")]
private static extern int GetDesktopWindow();
private const int SW_HIDE = 0;
private const int SW_SHOW = 1;
protected static int Handle
{
get
{
return FindWindow("Shell_TrayWnd", "");
}
}
protected static int HandleOfStartButton
{
get
{
int handleOfDesktop = GetDesktopWindow();
int handleOfStartButton = FindWindowEx(handleOfDesktop, 0, "button", 0);
return handleOfStartButton;
}
}
private Taskbar()
{
// hide ctor
}
public static void Show()
{
ShowWindow(Handle, SW_SHOW);
ShowWindow(HandleOfStartButton, SW_SHOW);
}
public static void Hide()
{
ShowWindow(Handle, SW_HIDE);
ShowWindow(HandleOfStartButton, SW_HIDE);
}
}
USAGE:
Taskbar.Hide();
Reorder lines to maximize the form after will will be marked with FormBorderStyle.None and TopMost
this.FormBorderStyle = FormBorderStyle.None;
this.TopMost = true;
this.WindowState = FormWindowState.Maximized;
You need to reorder your statements, try:
this.TopMost = true;
this.FormBorderStyle = FormBorderStyle.None;
this.WindowState = FormWindowState.Maximized;
I have a WPF window that enables glass on itself during its SourceInitialized event. This works perfectly. I'll use the simplest example possible (just one window object) to demonstrate where the issue is.
public partial class MainWindow : Window
{
public bool lolz = false;
public MainWindow()
{
InitializeComponent();
this.SourceInitialized += (x, y) =>
{
AeroExtend(this);
};
}
private void Window_Loaded(object sender, RoutedEventArgs e)
{
if (!lolz)
{
MainWindow mw = new MainWindow();
mw.lolz = true;
mw.ShowDialog();
}
}
}
This creates two MainWindows. When I debug this in Visual Studio everything works as expected.
When I run without debugging, not so much.
The child window has an odd, incorrectly applied glass frame... but only when running it directly without Visual Studio debugging. Same code ran twice but with different results. It doesn't matter when I create the second window, I've tied it to a button click with the same output.
Any ideas?
EDIT: Here is an excerpt of the code I'm using for AeroExtend
[DllImport("dwmapi.dll")]
private static extern int DwmExtendFrameIntoClientArea(IntPtr hWnd, ref MARGINS pMargins);
[DllImport("dwmapi.dll", PreserveSig = false)]
private static extern bool DwmIsCompositionEnabled();
[StructLayout(LayoutKind.Sequential)]
private class MARGINS
{
public MARGINS(Thickness t)
{
cxLeftWidth = (int)t.Left;
cxRightWidth = (int)t.Right;
cyTopHeight = (int)t.Top;
cyBottomHeight = (int)t.Bottom;
}
public int cxLeftWidth, cxRightWidth,
cyTopHeight, cyBottomHeight;
}
...
static public bool AeroExtend(this Window window)
{
if (Environment.OSVersion.Version.Major >= 6 && DwmIsCompositionEnabled())
{
IntPtr mainWindowPtr = new WindowInteropHelper(window).Handle;
HwndSource mainWindowSrc = HwndSource.FromHwnd(mainWindowPtr);
mainWindowSrc.CompositionTarget.BackgroundColor = Colors.Transparent;
window.Background = System.Windows.Media.Brushes.Transparent;
MARGINS margins = new MARGINS(new Thickness(-1));
int result = DwmExtendFrameIntoClientArea(mainWindowSrc.Handle, ref margins);
if (result < 0)
{
return false;
}
return true;
}
return false;
}
The problem is that you have MARGINS defined as a class. You'll notice that if you tried using a different set of values for the margin (e.g. 10 pixels on each edge) that it will still try to fill the entire area. Also as I mentioned in my comment the other day, you will notice that you have an artifact in the lower right corner even in the original window that wasn't shown modally. If you simply change the MARGINS from a class to a struct then the problem does not occur. e.g.
[StructLayout(LayoutKind.Sequential)]
private struct MARGINS
Alternatively you could leave MARGINS a class but then you should change the way the DwmExtendFrameIntoClientArea is defined. e.g.
[DllImport("dwmapi.dll")]
private static extern int DwmExtendFrameIntoClientArea(IntPtr hWnd, [MarshalAs(UnmanagedType.LPStruct)] MARGINS pMargins);