У меня есть настройка в моем приложении, которая требует любое значение между 24 и 65520, которое должно быть равномерно делено на 24. Я решил реализовать это с горизонтальной полосой прокрутки и текстовым полем, которое показывает текущее значение полосы прокрутки, и может иметьзначение, введенное в него вручную (которое затем устанавливает значение полосы прокрутки).Полоса прокрутки имеет минимум = 24, максимум = 65520, маленькие и большие приращения = 1. Значение по умолчанию при запуске приложения - 960. В итоге мне пришлось использовать несколько обработчиков событий как для текстового поля, так и для полосы прокрутки, и даже до сих порне работал идеально.Моя первая в основном рабочая попытка была такой:
private void hScrollBar_TicksPerQuarter_Scroll(object sender, ScrollEventArgs e)
{
int NewValue = e.NewValue;
if (e.Type != ScrollEventType.EndScroll)
{
if (e.NewValue < e.OldValue)
{
NewValue = e.NewValue - (e.NewValue % 24);
}
else if (e.NewValue > e.OldValue)
{
NewValue = e.NewValue + (e.NewValue % 24 == 0 ? 0 : 24 - (e.NewValue % 24));
}
txtTicksPerQuarter.Text = NewValue.ToString();
}
else
{
hScrollBar_TicksPerQuarter.Value = NewValue;
}
}
private void hScrollBar_TicksPerQuarter_ValueChanged(object sender, EventArgs e)
{
if (hScrollBar_TicksPerQuarter.Value.ToString() != txtTicksPerQuarter.Text)
{
hScrollBar_TicksPerQuarter.Value = Convert.ToInt32(txtTicksPerQuarter.Text);
}
}
private void txtTicksPerQuarter_Leave(object sender, EventArgs e)
{
TrySetTicksPerQuarter();
}
private void txtTicksPerQuarter_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Enter)
TrySetTicksPerQuarter();
}
private void TrySetTicksPerQuarter()
{
bool useOldValue = false;
int TicksPerQuarter_OldValue = hScrollBar_TicksPerQuarter.Value;
int TicksPerQuarter = 0;
if (Int32.TryParse(txtTicksPerQuarter.Text, out TicksPerQuarter))
{
if (TicksPerQuarter % 24 == 0)
{
hScrollBar_TicksPerQuarter.Value = TicksPerQuarter;
}
else
{
useOldValue = true;
MessageBox.Show("Must enter a value that is a multiple of 24, with a minimum of 24 and a maximum of 65520.", "Invalid TicksPerQuarter", MessageBoxButtons.OK, MessageBoxIcon.Warning);
}
}
else
{
useOldValue = true;
}
if (useOldValue)
txtTicksPerQuarter.Text = TicksPerQuarter_OldValue.ToString();
}
Это работает довольно хорошо, если я введу значение в текстовое поле и оставлю поле или нажму Enter, оно соответствующим образом обновит полосу прокрутки, и если значениене является правильным кратным 24, он просто сбрасывает себя к последнему действительному значению и отображает сообщение пользователю, указывающее проблему.Прокрутка полосы прокрутки обновляет текстовое поле в режиме реального времени во время прокрутки, и все в основном работает.Проблема в том, что при нажатии и перетаскивании полосы прокрутки момент, когда вы позволяете, приводит к скачку значения (обычно это пара сотен или около того, в любом направлении).Не зная, почему это происходило, я начал экспериментировать с изменениями события «Прокрутка» на полосе прокрутки, чтобы посмотреть, смогу ли я исправить это, поэтому при отпускании полосы прокрутки после ее перетаскивания значение остается на том же уровне, что и на момент его отпускания.,Потребовалось много экспериментов, в том числе некоторые радикальные изменения всего, что даже не работало, а также кода, который я выложил выше, но в конечном итоге лучшее, что я мог получить, - это сохранить весь код выше в других событиях, ипросто измените событие прокрутки на следующее:
ScrollEventType[] IncrementScrollEvents = new ScrollEventType[] { ScrollEventType.LargeIncrement, ScrollEventType.SmallIncrement, ScrollEventType.Last };
ScrollEventType[] DecrementScrollEvents = new ScrollEventType[] { ScrollEventType.LargeDecrement, ScrollEventType.SmallDecrement, ScrollEventType.First };
private void hScrollBar_TicksPerQuarter_Scroll(object sender, ScrollEventArgs e)
{
int NewValue = e.NewValue;
if (IncrementScrollEvents.Contains(e.Type))
{
NewValue = e.NewValue + (e.NewValue % 24 == 0 ? 0 : 24 - (e.NewValue % 24));
}
else if (DecrementScrollEvents.Contains(e.Type))
{
NewValue = e.NewValue - (e.NewValue % 24);
}
else if (e.Type == ScrollEventType.ThumbTrack)
{
if (e.NewValue < e.OldValue)
{
NewValue = e.NewValue - (e.NewValue % 24);
}
else if (e.NewValue > e.OldValue)
{
NewValue = e.NewValue + (e.NewValue % 24 == 0 ? 0 : 24 - (e.NewValue % 24));
}
}
else if (e.Type == ScrollEventType.EndScroll)
{
hScrollBar_TicksPerQuarter.Value = NewValue;
}
else
{
return;
}
txtTicksPerQuarter.Text = NewValue.ToString();
}
Это определенно работает лучше, и если бы мне пришлось его оценивать, я бы сказал, что, возможно, 4 из 5 раз вы отпустите полосу прокрутки, значение останется там, где онобыл в последний момент, прежде чем отпустить кнопку мыши.Но это все еще не идеально.
Я надеялся, что есть лучший способ сделать это, и с точки зрения функциональности, будучи немного более совершенным, чем сейчас, и, возможно, даже с точки зренияобщая сложность кода.Я не ожидал, что для этого потребуется написать код в 4 разных событиях на 2 элементах управления, но, возможно, в конце концов нет лучшего способа?
РЕДАКТИРОВАТЬ 1:
У меня былоидея использовать приращения 1 и мин / макс 1-2730 вместо 24-65520, а затем вместо того, чтобы выполнять математику и проверку и вручную устанавливать значение полосы прокрутки, чтобы она была кратна 24, я вместо этого просто умножу ее действительноезначение на 24, чтобы получить полезное значение и отображаемое значение для текстового поля.Этот код теперь идентичен по функциональности тому, что я имел выше, с гораздо меньшей сложностью.Я также переместил окно с предупреждением о недопустимой записи в текстовое поле, чтобы оно отображало сообщение, даже когда пользователь вводит что-то, что даже не может быть преобразовано в целое число:
private void hScrollBar_TicksPerQuarter_Scroll(object sender, ScrollEventArgs e)
{
txtTicksPerQuarter.Text = (e.NewValue * 24).ToString();
}
private void txtTicksPerQuarter_Leave(object sender, EventArgs e)
{
TrySetTicksPerQuarter();
}
private void txtTicksPerQuarter_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Enter)
TrySetTicksPerQuarter();
}
private void TrySetTicksPerQuarter()
{
bool useOldValue = false;
int TicksPerQuarter_OldValue = hScrollBar_TicksPerQuarter.Value;
int TicksPerQuarter = 0;
if (Int32.TryParse(txtTicksPerQuarter.Text, out TicksPerQuarter))
{
if (TicksPerQuarter % 24 == 0)
{
hScrollBar_TicksPerQuarter.Value = (TicksPerQuarter / 24);
}
else
{
useOldValue = true;
}
}
else
{
useOldValue = true;
}
if (useOldValue)
{
MessageBox.Show("Must enter a value that is a multiple of 24, with a minimum of 24 and a maximum of 65520.", "Invalid TicksPerQuarter", MessageBoxButtons.OK, MessageBoxIcon.Warning);
txtTicksPerQuarter.Text = (TicksPerQuarter_OldValue * 24).ToString();
}
}
Полоса прокрутки все еще время от времени скачет, когдаВы отпускаете кнопку мыши, когда перетаскиваете ее влево и вправо.У меня до сих пор нет решения этой конкретной проблемы, разве я не могу исправить это из-за того, как мышь и полоса прокрутки играют друг с другом?