I've an application that use two forms: Form1 (main) and Form2 (secondary). I show the Form2 with the following code:
Form2 frm = new Form2();
frm.TopMost = true;
frm.Show();
When the Form2 is visible, it hasn't the focus. How can I do the focus at the Form2 and keep the focus at the Form1? Sorry for my bad english!
try bellow code within MDI Parent Form (Main Form)
private Form2 _form2;
#region UtilOpenForm
/// <summary>
/// UtilOpenForm
/// </summary>
/// <param name="appContainer"></param>
/// <param name="childForm"></param>
private void UtilOpenForm(Form appContainer, Form childForm)
{
this.Cursor = Cursors.WaitCursor;
if (childForm == null)
{
throw new ArgumentNullException("childForm");
}
childForm.MdiParent = appContainer;
childForm.StartPosition = FormStartPosition.CenterScreen;
childForm.MaximizeBox = false;
childForm.MinimizeBox = false;
childForm.Closed += new EventHandler(childForm_Closed);
childForm.Show();
this.Cursor = Cursors.Default;
}
Now from Button / Menu click within MDI Parent
if (_form2 == null)
{
UtilOpenForm(this, _form2 = new Form2());
}
Now child form close Function within MDI Parent
#region childForm_Closed
/// <summary>
///
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void childForm_Closed(object sender, EventArgs e)
{
if (sender.GetType() == typeof(Form2))
{
_form2.Dispose();
if (_form2 != null)
{
_form2 = null;
}
}
Related
I have a mdi form which contains some child forms. One of this forms takes time to load. I need to use a backgroundworker to load this form. I tried this code, but I get cross-thread error. Actually I can't set mdiParent for my 'form' through backgroundworker.
any help will be appreciated.
code :
private void tsmiNewExpense_Click(object sender, EventArgs e)
{
tss_lbl1.Text = "Loading...";
if (!BW1.IsBusy)
{
BW1.RunWorkerAsync();
}
}
private void BW1_DoWork(object sender, DoWorkEventArgs e)
{
frmNewExpense frm = new frmNewExpense();
showChildForm(frm);
}
/// <summary>
/// Checks for one instance of this form is running
/// </summary>
/// <param name="frm">the form that will be shown.</param>
private void showChildForm(Form frm)
{
bool exists = false;
foreach (Form item in this.MdiChildren)
{
if (item.Name == frm.Name)
{
item.Activate();
item.StartPosition = FormStartPosition.CenterParent;
item.WindowState = formWindowState;
exists = true;
break;
}
}
if (!exists)
{
frm.MdiParent = this;//this line gets cross-thread error
frm.StartPosition = FormStartPosition.CenterParent;
frm.WindowState = formWindowState;
frm.Show();
}
}
This is using Synchronization context to update Form's lblTimer label:
CS:
public partial class MainForm : Form
{
private readonly SynchronizationContext _context;
public MainForm()
{
InitializeComponent();
// the context of MainForm, main UI thread
// 1 Application has 1 main UI thread
_context = SynchronizationContext.Current;
}
private void BtnRunAnotherThreadClick(object sender, EventArgs e)
{
Task.Run(() =>
{
while (true)
{
Thread.Sleep(1000);
//lblTimer.Text = DateTime.Now.ToLongTimeString(); // no work
UpdateTimerInMainThread(); // work
}
});
}
private void UpdateTimerInMainThread()
{
//SynchronizationContext.Current, here, is context of running thread (Task)
_context.Post(SetTimer, DateTime.Now.ToLongTimeString());
}
public void SetTimer(object content)
{
lblTimer.Text = (string)content;
}
}
Hope this help.
What is the best way to hide the main form on application's startup to show it later?
If I just call the Hide method in the Load event of this form it gives a terrible flash for some time before actually hiding it.
Thanks in advance.
The simplest way is to set Opacity = 0 in the designer. Of course you will want to set it back to 100 at some point later..
Or you may want to use a splash screen, maybe like this:
static class Program
{
/// <summary>
/// Der Haupteinstiegspunkt für die Anwendung.
/// </summary>
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Splash splash = new Splash();
splash.Show();
Application.Run();
}
}
With a splash screen:
public partial class Splash : Form
{
public Splash()
{
InitializeComponent();
}
Form1 form1 = new Form1();
private void Splash_Load(object sender, EventArgs e)
{
form1.WindowState = FormWindowState.Minimized;
form1.Hide();
}
}
You can then show it for example when the splash screen is closed:
private void Splash_FormClosed(object sender, FormClosedEventArgs e)
{
form1.Show();
form1.WindowState = FormWindowState.Normal;
}
Which would happen whenever you want or maybe after some time:
public Splash()
{
InitializeComponent();
Timer timer = new Timer();
timer.Interval = 5000;
timer.Enabled = true;
timer.Tick += (s,e) =>{ this.Close();};
}
Since the program is not watching a Form to close we also need to add this to the main form's closed event:
private void Form1_FormClosed(object sender, FormClosedEventArgs e)
{
Application.Exit();
}
If you don't want the splash screen to be visible at all you can hide it like this:
public Splash()
{
InitializeComponent();
this.Opacity = 0;
But please make sure you don't leave the users in the blind: When I start a program I want immediate response!!
You can proceed like this:
private void Form1_Load(object sender, EventArgs e)
{
if (Settings.Instance.HideAtStartup)
{
BeginInvoke(new MethodInvoker(delegate
{
Hide();
}));
}
}
An alternative way can be to use the Application.Run(Form) method. You can create the main form with its Visible property initially set to false, and provide no argument to Application.Run() in main loop.
Modify your Program class - this is where the form is created and shown:
static class Program {
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main () {
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Form1 frm = new Form1();
frm.Visible = false;
Application.Run();
}
}
Hopefully your adding some sort of user interface?
I tried:
Form myForm = new EULA();
myForm.Show();
this.WindowState = FormWindowState.Minimized;
myForm.BringToFront();
myForm.Activate();
myForm.Focus();
This code brings it to the front, but for some reason I still have to click on the Form for it to have focus, can anyone tell me why?
The form may be focused already, perhaps you want a control inside it (like a textbox or a combo) to be selected instead?
I'll use this code at the form's load method:
private void Form_Load(object sender, System.EventArgs e)
{
controlName.Select();
}
Hi leaf68 just follow my codes. try to figure it out :)
Let say we have MainForm and LoginForm
In our project we have a Static Class we called Program -> The main entry point for the application. as default class to run our projects.
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new LoginForm());
if (LoginForm._loginSuccess)
{
var m = new MainForm();
Application.Run(m);
}
else
Application.Exit();
}
public static bool UserLogin() //Add some parameter
{
//You Logic here
LoginForm._loginSuccess = true;
return LoginForm._loginSuccess;
}
}
then this is our LoginForm codes
public partial class LoginForm : Form
{
public LoginForm()
{
InitializeComponent();
}
public static bool _loginSuccess { get; set; }
public event EventHandler Login;
private void loginButton_Click(object sender, EventArgs e)
{
if (Program.UserLogin())
{
Close();
Dispose();
if (Application.OpenForms.Count > 0)
if (Application.OpenForms["MainForm"].Name == "MainForm")
{
Application.OpenForms["MainForm"].WindowState = FormWindowState.Normal;
Application.OpenForms["MainForm"].Enabled = true;
}
if (Login != null)
Login(this, EventArgs.Empty);
}
}
}
then assuming that we successfully Login To MainForm so this is our MainForm codes
public partial class MainForm : Form
{
public MainForm()
{
InitializeComponent();
}
private void logOutButton_Click(object sender, EventArgs e)
{
//Hide();
Enabled = false;
WindowState = FormWindowState.Minimized;
var f = new LoginForm();
f.Login += loginShow;
f.Show();
f.Activate();
}
private void loginShow(object sender, EventArgs args)
{
Show();
}
}
I hope it helps you :)
I have a form not visible, so only the tray icon.
I just use:
this.ShowInTaskbar = true;
this.WindowState = FormWindowState.Normal;
this.Activate();
In the above order. Program comes to the front and is activated, meaning typing actually writes in the active field.
This works:
when program appears automatically and
when user selects tray menu item.
I have a control on my GUI which I would like to make visible only case when I run BackgroundWorkers (many different operations). Some of these operations last less than 500ms, and I feel that making the control visible for so short a time is useless. Therefore, I would like to make the control visible only if a BackgroundWorker has already been working for 500ms.
Just start a timer at the same time you start the BGW:
private void button1_Click(object sender, EventArgs e) {
timer1.Enabled = true;
backgroundWorker1.RunWorkerAsync();
}
private void timer1_Tick(object sender, EventArgs e) {
timer1.Enabled = false;
myControl1.Visible = true;
}
private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) {
timer1.Enabled = myControl1.Visible = false;
}
Leverage the ReportProgress method on the BackgroundWorker. You can place whatever you want in the state parameter and then perform the calculation accordingly.
public class MyObject
{
public DateTime TimeStarted {get; set;}
}
Then in your ProgressChanged event handler...
private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
if(DateTime.Now.Subtract(((MyObject)e.UserState).TimeStarted).TotalMilliseconds > 500)
{
//show your control
}
}
You can use a Timer inside the BackgroundWorker and call the ReportProgress method once 500ms have passed.
In the UI thread you then just need to handle the ProgressChanged event and show/hide your control as required.
public partial class Form1 : Form
{
/// <summary>
/// Timer.
/// </summary>
private Timer timer = new Timer();
/// <summary>
/// Initializes a new instance of the <see cref="Form1"/> class.
/// </summary>
public Form1()
{
InitializeComponent();
backgroundWorker1.WorkerReportsProgress = true;
backgroundWorker1.DoWork += BackgroundWorker1DoWork;
backgroundWorker1.ProgressChanged += BackgroundWorker1ProgressChanged;
timer.Interval = 500;
timer.Tick += TimerTick;
}
/// <summary>
/// Handles the Tick event of the timer control.
/// </summary>
/// <param name="sender">The source of the event.</param>
/// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
void TimerTick(object sender, EventArgs e)
{
timer.Enabled = false;
backgroundWorker1.ReportProgress(99);
}
/// <summary>
/// Handles the Click event of the button1 control.
/// </summary>
/// <param name="sender">The source of the event.</param>
/// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
private void Button1Click(object sender, EventArgs e)
{
timer.Enabled = true;
backgroundWorker1.RunWorkerAsync();
}
/// <summary>
/// Handles the DoWork event of the backgroundWorker1 control.
/// </summary>
/// <param name="sender">The source of the event.</param>
/// <param name="e">The <see cref="System.ComponentModel.DoWorkEventArgs"/> instance containing the event data.</param>
private void BackgroundWorker1DoWork(object sender, DoWorkEventArgs e)
{
BackgroundWorker worker = sender as BackgroundWorker;
// Do your work...
Thread.Sleep(2000);
}
/// <summary>
/// Handles the ProgressChanged event of the backgroundWorker1 control.
/// </summary>
/// <param name="sender">The source of the event.</param>
/// <param name="e">The <see cref="System.ComponentModel.ProgressChangedEventArgs"/> instance containing the event data.</param>
private void BackgroundWorker1ProgressChanged(object sender, ProgressChangedEventArgs e)
{
label1.Visible = (e.ProgressPercentage == 99);
}
}
Is it possible to drag and drop a path in a wpf using Mouse Eventhandlers? In partcular I want to drag a path with the left mouse button and to mouse it on the grid. How can this be done?
Try this:
Given:
TextBox name is "TextBox1"
public MainWindow()
{
// Initialize UI
InitializeComponent();
// Loaded event
this.Loaded += delegate
{
TextBox1.AllowDrop = true;
TextBox1.PreviewDragEnter += TextBox1PreviewDragEnter;
TextBox1.PreviewDragOver += TextBox1PreviewDragOver;
TextBox1.Drop += TextBox1DragDrop;
};
}
/// <summary>
/// We have to override this to allow drop functionality.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
void TextBox1PreviewDragOver(object sender, DragEventArgs e)
{
e.Handled = true;
}
/// <summary>
/// Evaluates the Data and performs the DragDropEffect
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void TextBox1PreviewDragEnter(object sender, DragEventArgs e)
{
if (e.Data.GetDataPresent(DataFormats.FileDrop))
{
e.Effects = DragDropEffects.Copy;
}
else
{
e.Effects = DragDropEffects.None;
}
}
/// <summary>
/// The drop activity on the textbox.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void TextBox1DragDrop(object sender, DragEventArgs e)
{
// Get data object
var dataObject = e.Data as DataObject;
// Check for file list
if (dataObject.ContainsFileDropList())
{
// Clear values
TextBox1.Text = string.Empty;
// Process file names
StringCollection fileNames = dataObject.GetFileDropList();
StringBuilder bd = new StringBuilder();
foreach (var fileName in fileNames)
{
bd.Append(fileName + "\n");
}
// Set text
TextBox1.Text = bd.ToString();
}
}