Skip to content

Instantly share code, notes, and snippets.

@KOZ60
Created November 30, 2023 18:18
Show Gist options
  • Save KOZ60/0e9a8af444d55971ce2304cf9010ad0a to your computer and use it in GitHub Desktop.
Save KOZ60/0e9a8af444d55971ce2304cf9010ad0a to your computer and use it in GitHub Desktop.
VBForm
using System;
using System.Collections.Generic;
using System.Windows.Forms;
public class VBForm : Form
{
private readonly List<Control> tabIndexList = new List<Control>(512);
public VBForm() {
ControlAdded += ControlAddedEvent;
ControlRemoved += ControlRemovedEvent;
}
private void ControlAddedEvent(object sender, ControlEventArgs e) {
EnumRegistTabIndex(e.Control);
}
private void ControlRemovedEvent(object sender, ControlEventArgs e) {
EnumRemoveTabIndex(e.Control);
}
private void EnumRegistTabIndex(Control con) {
RegistTabIndex(con, false);
if (con.HasChildren) {
for (int i = 0; i < con.Controls.Count; i++) {
EnumRegistTabIndex(con.Controls[i]);
}
}
}
private void EnumRemoveTabIndex(Control con) {
EnumRemoveTabIndex(con, false);
}
private void EnumRemoveTabIndex(Control con, bool recursive) {
int tabIndex = con.TabIndex;
int index = RemoveTabIndex(con);
if (con.HasChildren) {
for (int i = 0; i < con.Controls.Count; i++) {
EnumRemoveTabIndex(con.Controls[i], true);
}
}
if (!recursive) {
supressChildTabIndexChanged = true;
for (int i = index; i < tabIndexList.Count; i++) {
tabIndexList[i].TabIndex = tabIndex;
tabIndex++;
}
supressChildTabIndexChanged = false;
}
}
private void RegistTabIndex(Control con, bool renumber) {
con.TabIndexChanged += OnChildTabIndexChanged;
con.ControlAdded += ControlAddedEvent;
con.ControlRemoved += ControlRemovedEvent;
int start = 0;
int end = tabIndexList.Count - 1;
int current = con.TabIndex;
while ((end - start) > 1) {
int m = (start + end) / 2;
int mIndex = tabIndexList[m].TabIndex;
if (current > mIndex)
start = m;
else
end = m;
}
for (int i = start; i <= end; i++) {
if (tabIndexList[i].TabIndex >= current) {
tabIndexList.Insert(i, con);
if (renumber) {
supressChildTabIndexChanged = true;
int newTabIndex = current + 1;
for (int j = i + 1; j < tabIndexList.Count; j++) {
tabIndexList[j].TabIndex = newTabIndex;
newTabIndex++;
}
supressChildTabIndexChanged = false;
}
return;
}
}
tabIndexList.Add(con);
}
private int RemoveTabIndex(Control con) {
int index = tabIndexList.IndexOf(con);
if (index >= 0) {
tabIndexList.RemoveAt(index);
con.TabIndexChanged -= OnChildTabIndexChanged;
con.ControlAdded -= ControlAddedEvent;
con.ControlRemoved -= ControlRemovedEvent;
}
return index;
}
private bool supressChildTabIndexChanged = false;
private void OnChildTabIndexChanged(object sender, EventArgs e) {
if (supressChildTabIndexChanged) return;
supressChildTabIndexChanged = true;
Control con = (Control)sender;
RemoveTabIndex(con);
RegistTabIndex(con, true);
supressChildTabIndexChanged = false;
}
private Control GetNextTabIndexControl(Control con, bool forward) {
int nextIndex;
if (con == null)
nextIndex = forward ? -1 : tabIndexList.Count;
else
nextIndex = tabIndexList.IndexOf(con);
if (forward) {
nextIndex++;
if (nextIndex < tabIndexList.Count)
return tabIndexList[nextIndex];
else
return null;
} else {
nextIndex--;
if (nextIndex >= 0)
return tabIndexList[nextIndex];
else
return null;
}
}
private Control GetNextTabIndexFocus(Control con, bool forward, bool tabStopOnly, bool wrap) {
Control start = GetNextTabIndexControl(con, forward);
while (start != null) {
if (!(start is ContainerControl) &&
start.CanFocus &&
(!tabStopOnly || start.TabStop))
return start;
start = GetNextTabIndexControl(start, forward);
};
if (con == null)
return null;
else {
if (wrap) {
return GetNextTabIndexFocus(null, forward, tabStopOnly, false);
}
return con;
}
}
public new bool SelectNextControl(Control ctl, bool forward, bool tabStopOnly, bool nested, bool wrap) {
Control nextControl = GetNextTabIndexFocus(ctl, forward, tabStopOnly, wrap);
if (nextControl != null) {
return nextControl.Focus();
}
return false;
}
protected override bool ProcessTabKey(bool forward) {
Control nextControl = GetNextTabIndexFocus(FocusedControl, forward, true, true);
if (nextControl != null) {
return nextControl.Focus();
}
return base.ProcessTabKey(forward);
}
protected Control FocusedControl {
get {
for (int i = 0; i < tabIndexList.Count; i++) {
Control con = tabIndexList[i];
if (con.ContainsFocus && con.CanSelect) {
return con;
}
}
return null;
}
}
const int WM_SHOWWINDOW = 0x0018;
protected override void WndProc(ref Message m) {
switch (m.Msg) {
case WM_SHOWWINDOW:
WmShowWindow(ref m);
break;
default:
base.WndProc(ref m);
break;
}
}
private void WmShowWindow(ref Message m) {
base.WndProc(ref m);
if (!DesignMode && m.WParam != IntPtr.Zero && ActiveControl == null) {
foreach (var con in tabIndexList) {
if (con.CanSelect) {
ActiveControl = con;
break;
}
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment