Я пытаюсь реализовать альт-tab как поведение для нашего приложения. Когда пользователь нажимает ctrl-tab, появляется всплывающая форма (используя ShowDialog
); когда они снова нажимают его, он фокусирует следующий элемент управления в основной форме приложения. Когда они отпускают ctrl, форма скрыта.
К сожалению, когда это происходит, фокус отправляется на другой элемент управления в тот, который был сфокусирован. Как предотвратить изменение фокуса при выходе ShowDialog?
Вы можете написать настраиваемое диалоговое окно, которое примет управление "to" focus в качестве свойства.... тогда, когда вы выходите, вы можете настроить фокус на "to".
Я написал небольшое приложение, которое показывает, как я буду обрабатывать описанное вами поведение.
Я установил свою основную форму с четырьмя элементами управления (просто кнопки для этого примера могут быть любыми элементами управления, которые вы хотите). Затем я устанавливаю другую форму, которая действует как выбор. В этом примере он просто содержит ListBox с именами элементов управления в нем. Вы могли бы сделать что-то более увлекательное. Вы также можете передать текущий сфокусированный элемент управления, чтобы тот, который уже выбран в списке. Я по умолчанию был первым элементом управления в списке.
Я установил публичное свойство MainForm под названием NextControl, чтобы удерживать выбранный элемент управления в форме Chooser. Я также создал свойство List для хранения ссылок на все элементы управления, которые вы хотите выбрать. Используя этот метод, ShowDialog должен работать нормально, потому что фокус не установлен в элементе управления Next до тех пор, пока не выйдет Dialog.
MainForm:
using System.Collections.Generic;
using System.Windows.Forms;
namespace Tabber
{
public partial class MainForm : Form
{
public MainForm()
{
InitializeComponent();
ControlList = new List<Control>(new Control[] {button1, button2, button3, button4});
}
private List<Control> ControlList { get; set; }
public Control NextControl { get; set; }
private void MainForm_KeyDown(object sender, KeyEventArgs e)
{
if (e.Modifiers == Keys.Control && e.KeyCode == Keys.Tab)
{
using (var chooseDialog = new Chooser(this, ControlList))
{
if (chooseDialog.ShowDialog() == DialogResult.OK)
{
if (NextControl != null)
{
NextControl.Focus();
}
}
}
}
}
}
}
Chooser:
using System.Collections.Generic;
using System.Windows.Forms;
namespace Tabber
{
public partial class Chooser : Form
{
public Chooser(MainForm sender, List<Control> controls)
{
Sender = sender;
InitializeComponent();
foreach (Control control in controls)
{
listBox1.Items.Add(control);
}
listBox1.DisplayMember = "Name";
listBox1.SetSelected(0, true);
}
private MainForm Sender { get; set; }
private void Chooser_KeyDown(object sender, KeyEventArgs e)
{
if (e.Modifiers == Keys.Control && e.KeyCode == Keys.Tab)
{
if (listBox1.SelectedIndex == listBox1.Items.Count - 1)
{
listBox1.SetSelected(0, true);
}
else
{
listBox1.SetSelected(listBox1.SelectedIndex + 1, true);
}
e.Handled = true;
}
}
private void listBox1_KeyUp(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.ControlKey)
{
Sender.NextControl = (Control) listBox1.SelectedItem;
DialogResult = DialogResult.OK;
Close();
}
}
}
}
Вы можете изменить это в соответствии с вашими потребностями. Это изменило фокус для меня.
Вы не должны использовать ShowDialog() для таких целей. Вместо этого вы должны использовать Show() и Hide() с логикой управления внутри вашей основной формы.
Вы также можете захотеть предотвратить активацию формы вообще, в этом случае сделать потомка формы и переопределить метод ShowWithoutActivation.
Вы также можете прочитать мой пост здесь.
Возможно, вы захотите изменить способ работы вашего диалога. Если я понимаю, что вы говорите, вместо этого вы можете создать свойство на своем CtrlTabDialog
, которое укажет, какой элемент управления должен получить фокус. Затем, когда ShowDialog()
завершает работу, прежде чем вы удалите форму CtrlTabDialog
, вы можете прочитать это свойство и соответствующим образом настроить фокус из любого кода, порожденного формой.