БлогNot. Делаем ListBox с редактированием элементов

Помощь дата->рейтинг Поиск Почта RSS канал Статистика nickolay.info Домой

Делаем ListBox с редактированием элементов

Вообще-то, элементы базового списка ListBox "на месте" не редактируются, для этого можно использовать ListView или табличные компоненты. Тем не менее, можно, например, выводить текстовое поле в том месте, где находится выбранный элемент списка и выполнять редактирование непосредственно в TextBox, по завершении редактирования передавая информацию обратно в список.

На форму добавлен TableLayoutPanel из 2 столбцов и 1 строки, относительная ширина столбцов равна 75% и 25%, выравнивание Dock = Fill.

В левую ячейку поместили список ListBox, а в правую - панель для кнопок Panel, также поставив им свойство Dock=Fill.

Кроме того, у ListBox установлено свойство ScrollAlwaysVisible=True (полоса прокрутки).

На панель поместим 3 кнопки Button с именами Name = addButton, deleteButton, editButton, у всех них установлено Dock = Top.

Вот вид формы в конструкторе:

вид формы приложения
вид формы приложения

Нам понадобится пара новых свойств класса формы, как обычно, опишем их под директивой #pragma endregion файла MyForm.h:

private: 
 int Cnt, //номер очередной строки
  EditIndex; //номер редактируемого элемента
 TextBox ^textBox1; //текстовое поле

На загрузку формы программно создадим и спрячем TextBox, пока не позиционируя его:

private: System::Void MyForm_Load(System::Object^  sender, System::EventArgs^  e) {
 Cnt = 0;
 textBox1 = gcnew TextBox();
 textBox1->Location = System::Drawing::Point(0, 0);
 textBox1->Size = System::Drawing::Size(0, 0);
 textBox1->Parent = this;
 textBox1->Hide();
 textBox1->Text = "";
 textBox1->BackColor = Color::Beige;
 textBox1->ForeColor = Color::Blue;
 textBox1->Font = gcnew System::Drawing::Font("Microsoft Sans Serif", 10, 
  FontStyle::Regular | FontStyle::Underline, GraphicsUnit::Pixel);
 textBox1->BorderStyle = BorderStyle::FixedSingle;
 textBox1->KeyPress += gcnew System::Windows::Forms::KeyPressEventHandler(this, &MyForm::textBox_KeyPress);
 textBox1->LostFocus += gcnew System::EventHandler(this, &MyForm::textBox_LostFocus);
 this->Controls->Add(textBox1);
}

Из кода видно, как "украсить" поле ввода.

Код также программно добавил созданному текстовому полю обработчики событий "нажатие клавиши" и "потеря фокуса", оба метода просто будут переписывать значение из поля ввода в список а потом вызывать ещё не написанный метод hideTextEditor, который передаст управление из поля ввода снова в список.

private: System::Void textBox_KeyPress(System::Object ^sender, System::Windows::Forms::KeyPressEventArgs^  e) {
 if (e->KeyChar == 13) {
  listBox1->Items[EditIndex] = textBox1->Text;
  hideTextEditor();
 }
}

private: System::Void textBox_LostFocus(System::Object ^sender, System::EventArgs ^e) {
 listBox1->Items[EditIndex] = textBox1->Text;
 hideTextEditor();
}

Самому списку можно добавить обработчики событий через конструктор форм, мы будем отслеживать двойной щелчок с списке, а также нажатие клавиш Enter или F2, все эти действия будут вызывать ещё не написанный метод CreateEditBox, ответственный за переход к редактированию элемента.

private: System::Void listBox1_DoubleClick(System::Object^  sender, System::EventArgs^  e) {
 CreateEditBox(sender);
}

private: System::Void listBox1_KeyPress(System::Object^  sender, System::Windows::Forms::KeyPressEventArgs^  e) {
 if (e->KeyChar == 13) CreateEditBox(sender);
}

private: System::Void listBox1_KeyDown(System::Object^  sender, System::Windows::Forms::KeyEventArgs^  e) {
 if (e->KeyData == Keys::F2) CreateEditBox(sender);
}

Кнопки "Добавить", "Удалить" и "Править" выполнят несложную работу по управлению элементами списка, причём, последняя также лишь вызывает метод CreateEditBox.

private: System::Void addButton_Click(System::Object^  sender, System::EventArgs^  e) {
 String ^Str = gcnew String("Строка " + ++Cnt);
 listBox1->Items->Add(Str);
}
	
private: System::Void deleteButton_Click(System::Object^  sender, System::EventArgs^  e) {
 int n = listBox1->SelectedIndex;
 if (n == -1) {
  MessageBox::Show("Сначала выберите строку", "Ошибка", MessageBoxButtons::OK);
  return;
 }
 listBox1->Items->RemoveAt(n);
}

private: System::Void editButton_Click(System::Object^  sender, System::EventArgs^  e) {
 CreateEditBox(listBox1);
}

Наконец, нам остаётся написать собственные методы класса, которые ранее мы неоднократно вызывали.

private: System::Void CreateEditBox (System::Object ^sender) {
 ListBox ^listBox1 = (ListBox ^)sender;
 int n = listBox1->SelectedIndex;
 if (n < 0) {
  MessageBox::Show("Сначала выберите строку", "Ошибка", MessageBoxButtons::OK);
  return;
 }
 Rectangle ^r = listBox1->GetItemRectangle(n);
 String ^itemText = (String ^)listBox1->Items[n];
 int delta = 2; //Смещение от позиции элемента списка
 textBox1->Location = System::Drawing::Point(r->X + delta, r->Y + delta);
 textBox1->Size = System::Drawing::Size(r->Width - 10, r->Height - delta);
 showTextEditor();
 textBox1->Text = itemText;
 textBox1->Focus();
 textBox1->SelectAll();
 EditIndex = n;
}

private: System::Void showTextEditor(System::Void) {
 listBox1->SendToBack();
 textBox1->BringToFront();
 textBox1->Show();
}

private: System::Void hideTextEditor() {
 textBox1->Hide();
 textBox1->SendToBack();
 listBox1->BringToFront();
}

Текстовое поле появляется прямо поверх списка, это достигается сменой переднего/заднего планов списка и текстового поля.

 Скачать этот пример в архиве .zip, внутри - папка с решением Visual Studio 2015 (7 Кб)


теги: c++ studio список программирование

комментарии (0)

08.10.2017, 16:30; рейтинг: 120

  в началопоиск по блогунаписать авторустатистика

Наверх Яндекс.Метрика
© PerS
вход