C++ C++ C# C# ASP.NET Security ASP.NET Security ASM ASM Скачать Скачать Поиск Поиск Хостинг Хостинг  
  Программа для работы с LPT портом...
Язык: .NET — ©Alexey...
  "ASP.NET Atlas" – AJAX в исполнении Micro...
Язык: .NET — ©legigor@mail.ru...
  "Невытесняющая" Многопоточность...
Язык: C/C++ — ©...
  01.05.2010 — Update World C++: Сборник GPL QT исходников
  15.12.2007 — Весь сайт целиком можно загрузить по ссылкам из раздела Скачать
Хостинг:
Windows 2003, ASP.NET 2.0
бесплатный и от 80 руб./мес


   Отправить письмо
Кулабухов Артем, Беларусь




 CTreeCtrl в диалоговом окне / Основы программирования с помощью библиотеки MFC / Visual C++

Он сказал "Поехали" и махнул рукой .

Итак, мы создаем простейший проект на основе диалогового окна в котором будут обьект CTreeCtrl и три кнопки управления этим объектом.
В даной статье освещены моменты работы с классом Tree Control специфические при работе его в Диалоговых окнах, приведен способ обойти БАГ связанный с неправильной обработкой нажатий клавиш ENTER (VK_RETURN) и ECS (VK_ESCAPE) при редактировании текста узла.

Теперь к делу.
* Создадим новый проект с помошью MFC AppWizard(exe) и зададим ему имя test и нажмем кнопку ОК.

* В появившемся окне выберем переключатель Dialog Based и далее нажимая кнопку Next оставляем все установки мастера по умолчанию.

* На четвертом шаге мастера нажимаем кнопку Finish затем кнопку ОК и становимся счастливыми обладателями готового шаблона приложения основаного на классе CDialog.

* Далее помещаем в поле диалога элемент Tree Control. и нажав правую кнопку мыши в контекстном меню вызываем ClassWizard.

* Здесь необходимо добавить переменную для обьекта Tree Control c с любым именем ( в нашем случае m_tree).Это делается так: переходим на вкладку Member Variables, выбираем объект IDC_TREE1 нажимаем на кнопку Add Varaible и в открывшемся окне вводим имя переменной m_tree. после чего нажимаем ОК. Теперь мы можем обрашаться к обьекту Tree Control через эту переменную.
Далее необходимо добавить три кнопки: Add Node, Delete Node, Edit Node, для осуществления операций добавления узла, удаления узла, и редактирования узла соответственно. Это сделать дотаточно легко воспользовавшись редактором форм.

* Теперь перейдем собственно к программированию :-))
Дважды щелкнув на кнопку в редакторе форм мы перейдем к программному коду для этой кнопки. Пускай кнопка Button 1 будет добавлять узел в элемент Tree Control. для этого необходимо добавить следующий код:

void CTestDlg::OnButton1()
{
// TODO: Add your control notification handler code here

m_tree.ModifyStyle(LVS_TYPEMASK,TVS_LINESATROOT | TVS_HASLINES |
TVS_HASBUTTONS | TVS_EDITLABELS );

TV_INSERTSTRUCT tvstruct;
HTREEITEM pNode;

tvstruct.hParent = 0;
tvstruct.item.mask = TVIF_TEXT ;
tvstruct.item.pszText = "node";
pNode = m_tree.InsertItem(&tvstruct);

}

Кнопка Button 1 теперь будет добавлять узлы в элемент Tree Control.

Пускай кнопка Button 2 будет удалять выбранный узел в элемент Tree Control. для этого необходимо добавить следующий код:

void CTestDlg::OnButton2()
{
// TODO: Add your control notification handler code here

m_tree.DeleteItem(m_tree.GetSelectedItem());

}

Пускай кнопка Button 3 будет выззывать редактирование выбранного узла в элементе Tree Control. для этого необходимо добавить следующий код:

void CTestDlg::OnButton3()
{
// TODO: Add your control notification handler code here

m_tree.EditLabel(m_tree.GetSelectedItem());

}


По идее все уже должно работать:Узлы должны добавляться, удаляться, и самое главное РЕДАКТИРОВАТЬСЯ!!! . И я так думал :-))
Оказывается не так. При запуске програмы все будет чудесно: Узлы дествительно и добавляются и удаляются, но MICROSOFT приподнесла нам сюрприз при редактировании элемента: при попытке нажать клавишу ENTER или ESC во время редактирования узла, программа успешно закрывается считая что нажата кнопка ОК или CANCEL нашего диалогового окна.
MICROSOFT сообщает: " да действительно есть такой БАГ в нашем немеряном продукте если CTreeCtrl является объектом порожденным от CDialog или от CFormView или от CPropertyPage " и предлагает два спосособа исправления ситуации.И как Вы думаете работают эти способы? Нет конечно, хотя идеи решения ситуации указаны правильно.
Тот способ который работает я Вам покажу:
Идея состоит в перегрузке функции PreTranslateMessage для нашего Диалогового окна. Для этого надо вызвать ClassWizard , на вкладке Message Map выбрать объект CTestDlg выбрав в правом окне "Messages" функцию PreTranslateMessage дважды по ней щелкнуть. В нижнем окне Member Function появится функция PreTranslateMessage.

Дважды щелкнув окне Member Function на функции PreTranslateMessage перейдем к коду. В него необхдимо добавить следующее.

BOOL CTestDlg::PreTranslateMessage(MSG* pMsg)
{
// TODO: Add your specialized code here and/or call the base class
if (pMsg->message == WM_KEYDOWN)
{
if (m_tree.GetEditControl() && (pMsg->wParam == VK_RETURN
|| pMsg->wParam == VK_ESCAPE
))
{
::DispatchMessage(pMsg);
return TRUE;
}
}
return CDialog::PreTranslateMessage(pMsg);
}

Догадайтесь с трех раз, а после этого будет работать? Опять нет конечно! Вся загвоздка состоит в том, что теперь, клавиши ENTER и ESC не закрывают диалоговое окно, но изменения сделанные при редактировании узла почему то не сохраняются.
Выход из ситуации предоставляет перегрузка еще одной функции: OnEndlabeledit Для этого надо вызвать ClassWizard , на вкладке Message Map выбрать объект IDC_TREE1 выбрав в правом окне "Messages" сообщение TWM_ENDLABELEDIT дважды по нему щелкнуть. В нижнем окне Member Function появится функция OnEndLabelEditTree1.

Дважды щелкнув окне Member Function на функции OnEndLabelEditTree1 перейдем к коду. В него необхдимо добавить следующее.

void CADlg::OnEndlabeleditTree1(NMHDR* pNMHDR, LRESULT* pResult)
{
TV_DISPINFO* pTVDispInfo = (TV_DISPINFO*)pNMHDR;
// TODO: Add your control notification handler code here

*pResult = TRUE;
}

Теперь все работает,все замечательно.
Пример рабочего проекта можно скачать здесь Пример проекта с TreeCtrl