Restrict Focus

Naren_sub81

Member
Joined
Nov 16, 2023
Messages
5
Programming Experience
Beginner
Hello,

I have several textboxes in my app. How to restrict the focus of mouse to other textboxes when one textbox has focus? For example, I have 5 textboxes named txt1, txt2, txt3, txt4 and txt5. When I am editing in txt1 and click the mouse in any of the other textboxes the focus should remain in txt1 itself. How to accomplish this task? It would be very helpful please if somebody could help me with a code sample.

Thanks in advance and good day...
 
Why not simply disable those other textboxes while focus is in one textbox? It's a lot better than trying to setup on focus event handlers on each textbox that resets the focus to the primary textbox. You will need to contend with more than just focus changing by mouse clicks: keyboard focus changes, assistive UI focus changes for the disabled, focus changes by testing frameworks, focus changes by AutoHotKey, focus changes by computer based training global hooks, etc.

As an aside, that is a terrible naming convention for your textboxes.

As another aside, I have a feeling that you are going against Windows UI guidelines by forcing focus to a particular textbox while the UI shows other textboxes as being active and available to accept focus. It is doing stunts like this that go against the UI guidelines that gives the Windows nay sayer who say that "Windows has such an inconsistent look and feel -- give me that consistent UI experience of a Mac instead" so much ammunition.
 
How, then, would focus ever leave that TextBox? How exactly would the application know that the user has finished editing and is allowed to shift focus? By definition, if the user clicks another TextBox, they are no longer editing in the original. You need to think about the problem a bit more and reformulate/restate it with more precise language and better logic.
 
How, then, would focus ever leave that TextBox? How exactly would the application know that the user has finished editing and is allowed to shift focus? By definition, if the user clicks another TextBox, they are no longer editing in the original. You need to think about the problem a bit more and reformulate/restate it with more precise language and better logic.

I can move the focus through keyboard. The only thing needed is to restrict the mouse interaction. I have seen many such applications where the focus will not be shifted to the next screen or control until a particular form is validated or requirements are met. One such popular example is amazon cart where-in, the user will not be able to move to the next step until first step is completed. I am trying to implement that concept here. Anyway, appreciate your efforts. Have a good day...
 
Last edited:
Why not simply disable those other textboxes while focus is in one textbox? It's a lot better than trying to setup on focus event handlers on each textbox that resets the focus to the primary textbox. You will need to contend with more than just focus changing by mouse clicks: keyboard focus changes, assistive UI focus changes for the disabled, focus changes by testing frameworks, focus changes by AutoHotKey, focus changes by computer based training global hooks, etc.

As an aside, that is a terrible naming convention for your textboxes.

As another aside, I have a feeling that you are going against Windows UI guidelines by forcing focus to a particular textbox while the UI shows other textboxes as being active and available to accept focus. It is doing stunts like this that go against the UI guidelines that gives the Windows nay sayer who say that "Windows has such an inconsistent look and feel -- give me that consistent UI experience of a Mac instead" so much ammunition.

I have named the textboxes according to the convention. Just to make things easy to understand I have given the names as such.
 
I have seen many such applications where the focus will not be shifted to the next screen or control until a particular form is validated or requirements are met. One such popular example is amazon cart where-in, the user will not be able to move to the next step until first step is completed. I am trying to implement that concept here.

Those are web UI. You are writing code in WinForms which is Windows UI.

But if you really want that stepwise input, use a Wizard type UI instead of a dialog box style UI. Each page of the wizard should be completed before proceeding to the next page.
 
How about restricting cursor movement?

C#:
using System;
using System.Drawing;
using System.Windows.Forms;

public partial class Form1 : Form
{
    public Form1() {
        InitializeComponent();
        foreach (Control txt in new TextBox[] { txt1, txt2, txt3, txt4, txt5 }) {
            txt.GotFocus += Txt_GotFocus;
            txt.LostFocus += Txt_LostFocus;
        }
    }

    private void Txt_GotFocus(object sender, EventArgs e) {
        var txt = (TextBox)sender;
        Cursor.Clip = txt.Parent.RectangleToScreen(txt.Bounds);
    }

    private void Txt_LostFocus(object sender, EventArgs e) {
        Cursor.Clip = Rectangle.Empty;
    }
}
 
Last edited by a moderator:
And how will you move the cursor to click on the OK or Cancel button?
 
So a naive Windows user will be stuck with that dialog or window until they fill everything out, but a power Windows user can get around.
 
Thanks for the reply KOZ60. I do not want to restrict the mouse movement. I just want to avoid clicking on textboxes. As Skydiver mentioned I have context menus and buttons on the form. Is it possible to avoid clicking on textboxes and enable it elsewhere?

KOZ60 and Skydiver please help...
 
How about this?
C#:
using System;
using System.Collections.Generic;
using System.Windows.Forms;

public partial class Form1 : Form
{
    readonly List<NativeWindow> nativeWindows = new List<NativeWindow>();

    public Form1() {
        InitializeComponent();
        foreach (Control txt in new Control[] { txt1, txt2, txt3, txt4, txt5 }) {
            nativeWindows.Add(new DisableFocusOnMouseDown(txt));
        }
    }

    private class DisableFocusOnMouseDown : NativeWindow {
        private readonly Control owner;
        private const int
            WM_NCDESTROY = 0x0082,
            WM_LBUTTONDOWN = 0x0201,
            WM_RBUTTONDOWN = 0x0204,
            WM_MBUTTONDOWN = 0x0207,
            WM_XBUTTONDOWN = 0x020B;

        public DisableFocusOnMouseDown(Control owner) {
            this.owner = owner;
            if (owner.IsHandleCreated) {
                AssignHandle(owner.Handle);
            }
            owner.HandleCreated += Owner_HandleCreated;
        }

        private void Owner_HandleCreated(object sender, EventArgs e) {
            AssignHandle(owner.Handle);
        }
        
        protected override void WndProc(ref Message m) {
            switch (m.Msg) {
                case WM_NCDESTROY:
                    base.WndProc(ref m);
                    ReleaseHandle();
                    break;
                case WM_LBUTTONDOWN:
                case WM_RBUTTONDOWN:
                case WM_MBUTTONDOWN:
                case WM_XBUTTONDOWN:
                    if (!owner.Focused) {
                        return;
                    }
                    base.WndProc(ref m);
                    break;
                default:
                    base.WndProc(ref m);
                    break;
            }
        }
    }
}
 
How about this?
C#:
using System;
using System.Collections.Generic;
using System.Windows.Forms;

public partial class Form1 : Form
{
    readonly List<NativeWindow> nativeWindows = new List<NativeWindow>();

    public Form1() {
        InitializeComponent();
        foreach (Control txt in new Control[] { txt1, txt2, txt3, txt4, txt5 }) {
            nativeWindows.Add(new DisableFocusOnMouseDown(txt));
        }
    }

    private class DisableFocusOnMouseDown : NativeWindow {
        private readonly Control owner;
        private const int
            WM_NCDESTROY = 0x0082,
            WM_LBUTTONDOWN = 0x0201,
            WM_RBUTTONDOWN = 0x0204,
            WM_MBUTTONDOWN = 0x0207,
            WM_XBUTTONDOWN = 0x020B;

        public DisableFocusOnMouseDown(Control owner) {
            this.owner = owner;
            if (owner.IsHandleCreated) {
                AssignHandle(owner.Handle);
            }
            owner.HandleCreated += Owner_HandleCreated;
        }

        private void Owner_HandleCreated(object sender, EventArgs e) {
            AssignHandle(owner.Handle);
        }
       
        protected override void WndProc(ref Message m) {
            switch (m.Msg) {
                case WM_NCDESTROY:
                    base.WndProc(ref m);
                    ReleaseHandle();
                    break;
                case WM_LBUTTONDOWN:
                case WM_RBUTTONDOWN:
                case WM_MBUTTONDOWN:
                case WM_XBUTTONDOWN:
                    if (!owner.Focused) {
                        return;
                    }
                    base.WndProc(ref m);
                    break;
                default:
                    base.WndProc(ref m);
                    break;
            }
        }
    }
}

Thank you very much KOZ60. I will definitely try this and update you at the earliest.

Have a great day...
 

Latest posts

Back
Top Bottom