ShowDialog() doesn't bring form to top when the owner is minimized. It is shown and visible, but it is not focused and behind the current window. Even using the commented lines, I see the issue.
public void Form1_Click(object sender, EventArgs e)
{
this.WindowState = FormWindowState.Minimized;
// this.Hide();
using (var f = new Form1())
{
// this.WindowState = FormWindowState.Normal;
f.Text = "ShowDialog()";
f.Click -= new EventHandler(f.Form1_Click);
f.ShowDialog(this); // f is not on top?
this.Show();
}
}
this.WindowState = FormWindowState.Minimized;
As soon as that executes, there is no window left in your application that can still receive the focus. Windows needs to find another one to give the focus to, it will be a window of another app. A bit later your dialog shows up, but that's too late, focus is already lost.
Using a trick like Control.BeginInvoke() to minimize the form after the dialog is displayed doesn't work either, the dialog automatically closes when it parent minimizes. The best you can do is hide it. You'll have to use the same trick to restore it before the dialog closes or you'll still lose focus. Like this:
protected override void OnClick(EventArgs e) {
using (var f = new Form1()) {
f.Text = "ShowDialog()";
this.BeginInvoke(new Action(() => this.Hide()));
f.FormClosing += delegate { this.Show(); };
f.ShowDialog();
}
}
Related
I m trying to solve problem in my fullscreen application. When I start the app it is fullscreen. That is handled by this code
public MainForm()
{
//this.TopMost = true;
InitializeComponent();
this.FormBorderStyle = FormBorderStyle.None;
}
private void Hlavni_Load (object sender, EventArgs e)
{
this.WindowState = FormWindowState.Maximized;
//this.Bounds = Screen.PrimaryScreen.Bounds;
}
When opening another fullscreen Form, everything works fine. Taskbar is cover with and doesn't show up. The problem occurs when I want to open 3rd form. This one is not meant to be fullscreen and serves for purpose similar to MessageBox.
While is this form open, taskbar is also visible untill the form is closed again. I tried somehow to update/change bounds of that form but it only led to making this form fullscreen.
Any idea how to show desired form and keep taskbar hidden?
Thanks in advance
EDIT
Adding the code for 3rd form
public RadForm3()
{
InitializeComponent();
//this.TopMost = true;
this.FormBorderStyle = FormBorderStyle.None;
this.ShowInTaskbar = false;
}
private void RadForm3_Load(object sender, EventArgs e)
{
//this.Bounds = Screen.PrimaryScreen.Bounds;
this.CenterToScreen();
...
}
//Splash form:
//------------
frmMain main = new frmMain();
this.Hide();
main.Show();
//MainForm:
//---------
var formToShow = (frmSplash)System.Windows.Forms.Application.OpenForms.Cast<Form>().FirstOrDefault(c => c is frmSplash);
formToShow.Show();
//formToShow.ShowDialog() execute the load event which I dont want.
formToShow.RunTestMetod()
//How I can get the splash hidden form without loading its Load Event and running its //TestMethod(). I want the mainform under it not accessible same like a message box dialog.
I dont want formtoShow.topmost = true as that keep it on the top but the 2nd form is still clickable. Any help would be greatly appreciated.
You can use myNewForm.Show(this); for the Window you want to be shown as a dialog. This will show myNewForm as a child of the current form, but lets you interact with the current form.
You could just disable MainForm?
// ...
var formToShow = (frmSplash)System.Windows.Forms.Application.OpenForms.Cast<Form>().FirstOrDefault(c => c is frmSplash);
this.Enabled = false;
formToShow.FormClosed += frm_FormClosed;
formToShow.Show(this);
formToShow.RunTestMetod()
void frm_FormClosed(object sender, FormClosedEventArgs e)
{
this.Enabled = true;
}
I have the following code in C#:
Form f = new MyForm();
f.Visible = false;
f.Show();
f.Close();
Despite the f.Visible = false, I am seeing a flash of the form appearing and then disappearing. What do I need to do to make this form invisible?
I need to show the form (invisibly) during the splash of my app because doing this removes a cold start delay when showing this form.
If you want to show the form without actually seeing it, you can do this:
public Form1()
{
InitializeComponent();
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None;
this.ShowInTaskbar = false;
this.Load += new EventHandler(Form1_Load);
}
void Form1_Load(object sender, EventArgs e)
{
this.Size = new Size(0, 0);
}
If at a later point you want to show it, you can just change everything back. Here is an example after 10 seconds, it shows the form:
Timer tmr = new Timer();
public Form1()
{
tmr.Interval = 10000;
tmr.Tick += new EventHandler(tmr_Tick);
tmr.Start();
InitializeComponent();
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None;
this.ShowInTaskbar = false;
this.Load += new EventHandler(Form1_Load);
}
void tmr_Tick(object sender, EventArgs e)
{
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.Sizable;
this.ShowInTaskbar = true;
this.Size = new Size(300, 300);
}
void Form1_Load(object sender, EventArgs e)
{
this.Size = new Size(0, 0);
}
By far the simplest way to keep a form invisible is just by not showing it. It is a big deal in Winforms, calling Show() or setting the Visible property to true (same thing) does a lot of things. It is the way the native Windows window gets created. In typical .NET 'lazy' fashion. Any attempt to set Visible back to false (like in OnLoad) will be defeated.
Technically it is possible, you have to override the SetVisibleCore() method. Like this:
protected override void SetVisibleCore(bool value) {
if (!this.IsHandleCreated) {
this.CreateHandle();
value = false; // Prevent window from becoming visible
}
base.SetVisibleCore(value);
}
This ensures that the window doesn't become visible the first time you call Show(). Which is handy when you have NotifyIcon for example, you typically want the icon directly in the notification area and only display a window when the user clicks on the icon. Beware that OnLoad() doesn't run until the window actually becomes visible so move code to the constructor or the override if necessary.
Simply Because f.Show() is making the form Visible again and f.Close() is Closing it... so the flash.
If you see the MSDN doc for Form.Show() method it clearly mentions that:
Showing the control is equivalent to setting the Visible property to true. After the Show method is called, the Visible property returns a value of true until the Hide method is called.
If you don't want the flash just don't show the Form at all.
You need to edit the MyForm class, and add the following override method:
protected override void SetVisibleCore(bool value)
{
//just override here, make sure that the form will never become visible
if (!IsHandleCreated) CreateHandle();
value = false;
base.SetVisibleCore(value);
}
You should ask yourself if this is really necessary however - probably indicative of poor design really.
Edit:
It's pretty rare that you need to do this, the only situation I've used it is when I needed a form I could place a COM component on (since the COM component needed a Window handle), and I had to run Application.Run(formInstance) which calls the Show method of the form. By forcing the form to always be invisible, you get a window handle and a message loop without seeing anything on screen.
I've created helper method that will to show invisible form and subsequent Show calls will show window as usually:
public static class FormHelper
{
public static void ShowInvisible(this Form form)
{
// saving original settings
bool needToShowInTaskbar = form.ShowInTaskbar;
WindowState initialWindowState = form.WindowState;
// making form invisible
form.ShowInTaskbar = false;
form.WindowState = FormWindowState.Minimized;
// showing and hiding form
form.Show();
form.Hide();
// restoring original settings
form.ShowInTaskbar = needToShowInTaskbar;
form.WindowState = initialWindowState;
}
}
So form will be rendered (and Load event will trigger) without any blink.
if you run this snippet of code(put it in form1) in a fresh new winform app with 2 forms
private void Form1_Load(object sender, EventArgs e)
{
Form2 newForm = new Form2();
Button b = new Button();
newForm.Controls.Add(b);
b.Click += new EventHandler(click);
this.Show();
newForm.ShowDialog();
}
private void click(object sender, EventArgs e)
{
((Form)((Control)sender).Parent).ShowInTaskbar = false;
}
and you click on the button on the new form(should be form2), form2 will close.
How to keep it open?
It is not possible. I actually filed a bug report about it at Microsoft's feedback site but they flipped me the bird on it.
Admittedly, it is a tricky problem to solve, changing the property requires Windows Forms to recreate the window from scratch because it is controlled by a style flag. The kind you can only specify in a CreateWindowEx() call with the dwExStyle argument. Recreating a window makes it difficult to keep it modal, as required by the ShowDialog() method call.
Windows Forms works around a lot of User32 limitations. But not that one.
You keep it open by setting ShowInTaskbar to false before you ShowDialog();
private void Form1_Load(object sender, EventArgs e)
{
Form2 newForm = new Form2();
Button b = new Button();
newForm.Controls.Add(b);
b.Click += new EventHandler(click);
this.Show();
// add this line of code...
newForm.ShowInTaskbar = false;
newForm.ShowDialog();
}
private void click(object sender, EventArgs e)
{
((Form)((Control)sender).Parent).ShowInTaskbar = false;
}
Or just don't make the second form modal. This works also.
private void Form1_Load(object sender, EventArgs e)
{
Form2 newForm = new Form2();
Button b = new Button();
newForm.Controls.Add(b);
b.Click += new EventHandler(click);
this.Show();
newForm.Show();
}
I don't know the specific mechanism here, but clearly what is happening is that changing the flag (which actually changes one or more WS_EX_xxx window styles) is causing the modal pump of ShowDialog() to exit. This, in turn is causing you to (finally!) exit Form1_Load and then your newForm goes out of scope and is destroyed.
So your problem is a compbination of ShowDialog() and the fact that you aren't prepared for ShowDialog() to ever exit.
Now a modal for shouldn't show up with a taskbar icon in the first place, there really should be only 1 taskbar icon for an application and all of it's modal forms, since when a modal form is running, the main form is disabled anyway. When the main form is minimized, all of the modal forms that it owns will be hidden, etc.
So if you really want this second form to be modal, you shouldn't give the user the ability to give it a taskbar icon. If using ShowDialog() was just test code, then don't worry about it. The problem will go away when the form runs on the main application pump.
Your question isn't very clear to me. Anyway, the newForm form is displayed as a modal dialog, which means that it blocks the user from working with the parent form until it is closed. Modal dialogs usually have some buttons that automatically close them returning either OK or Cancel to the calling form (as a return value of ShowDialog). This is done using the DialogResult property, so if this property is set for your button, this may be a reason why the modal form closes when you click on it.
If you want to show more forms in a way that allows the user to work with both of them, you'll need to use modeless dialog. Here is a good overview article on MSDN.
how... my... this is an ugly hack
this work
private void Form1_Load(object sender, EventArgs e)
{
Form2 newForm = new Form2();
Button b = new Button();
newForm.Controls.Add(b);
b.Click += new EventHandler(click);
newForm.FormClosed += new FormClosedEventHandler(form2_closed);
newForm.FormClosing += new FormClosingEventHandler(form2_closing);
this.Show();
do
{
newForm.ShowDialog();
} while (newForm.IsDisposed == false );
}
private void click(object sender, EventArgs e)
{
((Form)((Control)sender).Parent).ShowInTaskbar = !((Form)((Control)sender).Parent).ShowInTaskbar;
}
private void form2_closed(object sender, FormClosedEventArgs e)
{
((Form)sender).Dispose();
}
private void form2_closing(object sender, FormClosingEventArgs e)
{
if (e.CloseReason == CloseReason.None)
e.Cancel = true;
}
I've successfully created an app that minimizes to the tray using a NotifyIcon. When the form is manually closed it is successfully hidden from the desktop, taskbar, and alt-tab. The problem occurs when trying to start with the app minimized. At first the problem was that the app would be minimized but would still appear in the alt-tab dialog. Changing the FormBorderStyle to one of the ToolWindow options (from the "None" option) fixed this, but introduced another problem. When the app first starts the titlebar of the minimized window is visible just above the start menu:
Opening the form and the closing it causes it to hide properly. I've tried lots of variations, but here's essentially how it's working right now...
WindowState is set to Minimized in the Designer. After some initialization in the constructor I have the following lines:
this.Visible = false;
this.ShowInTaskbar = false;
When the NotifyIcon is double-clicked I have the following:
this.WindowState = FormWindowState.Normal;
this.Visible = true;
this.ShowInTaskbar = true;
Like I said, I've tried lots of minor variations on this (this.Hide(), etc.). Is there a way to have the NotifyIcon be the primary component such that I can completely start and dispose of the form while leaving the NotifyIcon running? There's got to be a way to start the app with the form minimized without any of the weirdness. Please help me find it!
The right way to do this is to prevent the form from getting visible in the first place. That requires overriding SetVisibleCore(). Let's assume a context menu for the NotifyIcon with a Show and Exit command. You can implement it like this:
public partial class Form1 : Form {
public Form1() {
InitializeComponent();
notifyIcon1.ContextMenuStrip = contextMenuStrip1;
this.showToolStripMenuItem.Click += showToolStripMenuItem_Click;
this.exitToolStripMenuItem.Click += exitToolStripMenuItem_Click;
}
private bool allowVisible; // ContextMenu's Show command used
private bool allowClose; // ContextMenu's Exit command used
protected override void SetVisibleCore(bool value) {
if (!allowVisible) {
value = false;
if (!this.IsHandleCreated) CreateHandle();
}
base.SetVisibleCore(value);
}
protected override void OnFormClosing(FormClosingEventArgs e) {
if (!allowClose) {
this.Hide();
e.Cancel = true;
}
base.OnFormClosing(e);
}
private void showToolStripMenuItem_Click(object sender, EventArgs e) {
allowVisible = true;
Show();
}
private void exitToolStripMenuItem_Click(object sender, EventArgs e) {
allowClose = true;
Application.Exit();
}
}
Note a wrinkle with the Load event, it won't fire until the main form is first shown. So be sure to do initialization in the form's constructor, not the Load event handler.
I'm reading all the answers and see hacks and black magic... (no offense, mates)
No hacks needed. You don't even have to set "ShowInTaskbar=false" and other stuff. Just do this:
//"Form Shown" event handler
private void Form_Shown(object sender, EventArgs e)
{
//to minimize window
this.WindowState = FormWindowState.Minimized;
//to hide from taskbar
this.Hide();
}
NOTE: I strongly recommend NOT TOUCHING the "ShowInTaskbar" property. For example, if your application registers system-wide hotkeys or other similar stuff (hooks, etc) - setting ShowInTaskBar=false and minimizing your app will prevent Windows from sending some messages to your window... And your hooks/hotkeys/etc will stop working.
In the constructor, remove these two lines:
this.Visible = false;
this.ShowInTaskbar = false;
and add after InitializeComponent();:
this.WindowState = FormWindowState.Minimized;
In designer, set ShowInTaskbar to false & FormWindowState to Normal.
EDIT:
If you post the same in Load event, the window does get minimized but still shows minimized on the desktop. I think this is a bug.
When minimizing an application and you want to hide it from Alt+Tab:
You also need to set the Opacity to stop the titlebar showing near the Start Menu when you set the Border Style to a Tool Window.
On Minimize Event:
this.Visible = false;
this.Opacity = 0;
this.FormBorderStyle = FormBorderStyle.FixedToolWindow;
this.ShowInTaskbar = false;
On Normalize Event:
this.Visible = true;
this.Opacity = 100;
this.FormBorderStyle = FormBorderStyle.FixedSingle; //or whatever it was previously set to
this.ShowInTaskbar = true;
Move the following code from the Form's constructor to Form_Main_Load(). With the same setup on Notification_Icon when Form_Resize().
// Hide the Form to System Tray
this.WindowState = FormWindowState.Minimized;
This "quick and dirty fix" worked for me:
$form1.FormBorderStyle = "fixedtoolwindow"
$form1.top = -1000000
$form1.Left = -1000000
$form1.Width = 10
$form1.Height = 10
$form1.WindowState = "normal"
$form1.ShowInTaskbar = $False
$form1.Opacity = 0
$form1.Hide()
Hope it helps someone else...