Detection when my form focuses

I work in C # with WinForms in a large application with several forms.

At several points, I have another form that appears as a progress screen. Since I cannot freeze my UI thread, I have to start a new form in a new thread. I use progressform.ShowDialog() to run the form, but since it is in a new thread, you can click or Alt + Tab to return to the main form. I want to disable this.

My thought is that I can put an EventHandler in the mainForm.GotFocus event and redirect the focus to progressForm if it is shown. However, the GotFocus event does not fire when switching applications or moving between progressForm and mainForm . I guess this is because some element in mainForm has focus, not the form itself.

If anyone knows how best to do this (I am not committed to the EventHandler approach) or working code for the EventHandler approach, this will solve my problem.

Edit

According to the comment, I tried to use the Activated event.

 // in InitializeForm() this.Activated += FocusHandler; // outside of InitializeForm() void FocusHandler(object sender, EventArgs e) { if (ProgressForm != null) { ProgressForm.Focus(); } } 

But he still allowed me to return to the main form and press the buttons.

+4
source share
1 answer

I tried several ways and found it works as you want, the whole idea is to filter the message from the main user interface when your execution form is displayed:

 public partial class Form1 : Form { [DllImport("user32")] private static extern int SetForegroundWindow(IntPtr hwnd); public Form1() { InitializeComponent(); } ChildUI child = new ChildUI(); bool progressShown; IntPtr childHandle; //I suppose clicking on the button1 on the main ui form will show a progress form. private void button1_Click(object sender, EventArgs e) { if(!progressShown) new Thread(() => { progressShown = true; childHandle = child.Handle; child.ShowDialog(); progressShown = false; }).Start(); } protected override void WndProc(ref Message m) { if (progressShown&&(m.Msg == 0x84||m.Msg == 0xA1||m.Msg == 0xA4||m.Msg == 0xA3||m.Msg == 0x6)) //0x84: WM_NCHITTEST //0xA1: WM_NCLBUTTONDOWN //0xA4: WM_NCRBUTTONDOWN //0xA3 WM_NCLBUTTONDBLCLK //suppress maximizing ... //0x6: WM_ACTIVATE //suppress focusing by tab... { SetForegroundWindow(childHandle);//Bring your progress form to the front return;//filter out the messages } base.WndProc(ref m); } } 

if you want to show your execution form usually (and not a dialog) using Application.Run() , displaying the form usually (using Show() ) without processing some while loop, it will interrupt the form almost immediately after its display:

 private void button1_Click(object sender, EventArgs e) { //progressShown = true; //child.Show(); if (!progressShown) { new Thread(() => { progressShown = true; if (child == null) child = new ChildUI(); childHandle = child.Handle; Application.Run(child); child = null; progressShown = false; }).Start(); } } 

I tested and works like a charm.

0
source

Source: https://habr.com/ru/post/1488157/


All Articles