Created
November 30, 2023 18:18
-
-
Save KOZ60/0e9a8af444d55971ce2304cf9010ad0a to your computer and use it in GitHub Desktop.
VBForm
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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