0

I have a form application that listenes a named pipeline. When message arrives from pipeline, it launches a new child form. But child form loses focus.

This is where i handle new message from named pipe:

private void OnMessage(CommunicationObject message)
    {
        switch (message.MessageType)
        {
            case MessageTypes.Pop:
                {
                    if (isLoginSessionActive) return;

                    StartSTATask(() =>
                    {
                        OpenLoginSession();
                    });

                    break;
                }
        }
    }

And this is OpenLoginSession method:

private void OpenLoginSession()
    {
        loginForm = new LoginForm(clientPipe);

        loginForm.FormClosing += (ss, ee) =>
        {
            ee.Cancel = !loginSuccessful;
        };

        loginForm.FormClosed += (ss, ee) =>
        {
            isLoginSessionActive = false;
            loginForm = null;
        };

        loginForm.Shown += (ss, ee) =>
        {
            this.InvokeIfRequired(() =>
            {
                loginForm.WindowState = FormWindowState.Maximized;
                loginForm.Activate();
                loginForm.BringToFront();
                loginForm.Focus();
                loginForm.TxtUsername.Focus();
            });
        };

        loginForm.ShowDialog();
    }

This is StartSTATask method:

private Task StartSTATask(Action func)
    {
        var tcs = new TaskCompletionSource<object>();

        Thread thread = new Thread(() =>
        {
            func();
            tcs.SetResult(null);
        });

        thread.SetApartmentState(ApartmentState.STA);
        thread.Start();

        return tcs.Task;
    }

I tried many methods but no result.

Thanks.

candogg
  • 145
  • 7
  • Are you sure you want to use `loginForm.ShowDialog();` instead of only `Show()` don’t think dialog will play nicely if the parent is from another thread. – Rand Random Aug 10 '22 at 21:19
  • When i use Show(), child form completely goes away. – candogg Aug 10 '22 at 21:21
  • After googling a bit I‘d prefer calling Application.Run(loginForm); eg like here https://stackoverflow.com/questions/167323/how-to-open-a-form-in-a-thread-and-force-it-to-stay-open or https://stackoverflow.com/questions/47438631/c-sharp-open-form-in-a-new-thread-or-task – Rand Random Aug 10 '22 at 21:26
  • 1
    Do you really want the other form to run on a different thread? That's going to complicate everything. As @RandRandom points out, I don't think two threads can access anything created by `Application.Run` (since that's basically the thread proc for your form). What's wrong with using a single UI thread and marshalling any calls from the background threads to the UI thread with `Form.Invoke` in the normal fashion. Using two threads is going to drive you batty – Flydog57 Aug 10 '22 at 21:34
  • Ok i tried it. Application works well but not focusing textbox. case MessageTypes.Pop: { if (isLoginSessionActive) return; //StartSTATask(() => //{ // OpenLoginSession(); //}); this.InvokeIfRequired(() => { OpenLoginSession(); }); break; } – candogg Aug 10 '22 at 21:44
  • When i place OpenLoginSession to main ui thread; to Parent Form_Load method, focus to textbox works. But, when i invoke OpenLoginSession, it opens the child login form without focusing the element i need. – candogg Aug 10 '22 at 22:00

1 Answers1

0

Ok i did it with mouse_event by clicking on textbox. Here is the code if anyone needs it.

  • First i get current cursor location,

  • Second i set cursor location to textbox pointtoscreen,

  • I simulate mouse click with

    [DllImport("user32.dll")] private static extern void mouse_event(int dwFlags, int dx, int dy, int dwData, int dwExtraInfo);

  • Then i set cursor location to previous location.

candogg
  • 145
  • 7