Вопрос № 164086: Пишу в MS Visual Studio. Проект Visual C++ Windows Form Application. В файле "Form1.h" содержится класс описывающий форму, в файле "HF.h" содержатся мои собственные классы, всё работает, но, как из файла "HF.h" обраща...
Вопрос № 164.086
Пишу в MS Visual Studio. Проект Visual C++ Windows Form Application. В файле "Form1.h" содержится класс описывающий форму, в файле "HF.h" содержатся мои собственные классы, всё работает, но, как из файла "HF.h" обращаться к форме ? В файле ".cpp" порядок инклудов такой: сначала "HF.h", затем "Form1.h", т.е. мои классы не знаю ни про какую форму. Или может я что-то неправильно делаю ? Надеюсь доступно объяснил
Отвечает: Micren
Здравствуйте, Юрий Анатольевич! Вот пример приложения построенного по типу Документ-Представление В программе 2 класса. 1й форма(Form1.h):
Код:
#include "TestClass.h"
#pragma once
namespace My164086 {
using namespace System; using namespace
System::ComponentModel; using namespace System::Collections; using namespace System::Windows::Forms; using namespace System::Data; using namespace System::Drawing;
/// <summary> /// Summary for Form1 /// /// WARNING: If you change the name of this class, you will need to change the /// 'Resource File Name' property for the managed resource compiler tool /// associated with all .resx files this cla
ss depends on. Otherwise, /// the designers will not be able to interact properly with localized /// resources associated with this form. /// </summary> public ref class Form1 : public System::Windows::Forms::Form { public: Form1(void) { InitializeComponent(); // //TODO: Add the constructor code here // }
protected: /// <summary> /// Clean up any resources being used. /// </summary> ~Form1() { if
(components) { delete components; } } private: System::Windows::Forms::Label^ label1; protected: private: System::Windows::Forms::TextBox^ textBox1; private: System::Windows::Forms::Button^ button1; private: System::Windows::Forms::Button^ button2;
} #pragma endregion // Обработчик события Load private: System::Void Form1_Load(System::Object^ sender, System::EventArgs^ e) { // Создаем документ document=gcnew TestDocument(); button1->Click+=gcnew EventHandler(document,&TestDocument::Button1ClickEventHandler); button2->Click+=gcnew EventHandler(document,&TestDocument::Button2ClickEventHandler);
// Связываем документ с контролами формы textBox1->DataBindings->Add(gcnew Binding(L"Text",document,L"Str",false,DataSourceUpdateMode::OnPropertyChanged,String::Empty)); button1->DataBindings->Add(gcnew Binding(L"Enabled",document,L"EnabledButton")); button1->DataBindings->Add(gcnew Binding(L"Text",document,L"Button1Caption")); button2->DataBin
dings->Add(gcnew Binding(L"Text",document,L"Button2Caption")); // И больше ни о чем не беспокоимся }
TestDocument^ document;
}; }
2й класс обработки данных формы(TestClass.h):
Код:
#pragma once
using
namespace System; using namespace System::ComponentModel;
namespace My164086 { ref class TestDocument:INotifyPropertyChanged // Этот интерфейс позволяет посылать события об исменении свойств документа { public: // Конструктор. Ничего необычного TestDocument() { EnabledButton=false; Str=String::Empty; Button1Caption=L"Кнопка включится когда будет введено 10 символов"; Button2Caption=L"Преобразо
вание к верхнему регистру"; toUpCase=true; } // Обработчики событий от кнопок void Button1ClickEventHandler(Object^ sender,EventArgs^ e) { Str=String::Empty; } void Button2ClickEventHandler(Object^ sender,EventArgs^ e) { if(toUpCase) { Str=Str->ToUpper(); Button2Caption=L"Преобразовать к нижнему регистру"; } else { Str=Str->ToLower(); Button2Caption=L"Преобразовать к верхнему регистру"; } toUpCase^=true; } //
Свойство Str property String^ Str { String^ get(){return str;} void set(String^ val) { if(val!=str) { // Если свойство изменилось - обработаем его str=val; // И пошлем событие NotifyPropertyChanged(L"Str"); // Включим или выключим кнопку if(str->Length<10)EnabledButton=false; else EnabledButton=true; } } } // Свойство включения кнопки property bool EnabledButton { bool get(){return enabledButton;} void set(bool val) { if(enabledButton!=val) { enabledButton=val; NotifyPropertyChanged(L"EnabledButton"); if(enabledButton)Button1Caption=L"Теперь нажав на кнопку можно очистить поле ввода"; else Button1Caption=L"Снова ждем 10 символов"; } } } // Заголовки кнопок property
String^ Button1Caption { String^ get(){return button1Caption;} void set(String^ val) { if(val!=button1Caption) { button1Caption=val; NotifyPropertyChanged(L"Button1Caption"); } } } property String^ Button2Caption { String^ get(){return button2Caption;} void set(String^ val) { if(val!=button2Caption) { button2Caption=val; No
tifyPropertyChanged(L"Button2Caption"); } } } // Событие virtual event PropertyChangedEventHandler^ PropertyChanged; private: // Этот метод просто генерирует событие void NotifyPropertyChanged(String^ info) { PropertyChanged(this,gcnew PropertyChangedEventArgs(info)); } // Скрытые члены String^ str; bool enabledButton; String^ button1Caption; String^ button2Caption; bool toUpCase; }; }
main()
Код:
#include "stdafx.h" #include "Form1.h"
using namespace My164086;
[STAThreadAttribute] int main(array<System::String ^> ^args) { // Enabling Windows XP visual effects before any contro
ls are created Application::EnableVisualStyles(); Application::SetCompatibleTextRenderingDefault(false);
// Create the main window and run it Application::Run(gcnew Form1()); return 0; }
Обратите внимание, что ни один класс не работает напрямую со свойствами другого. Тем не менее все работает. Связь между ними происходит через класс Binding и события. Это, конечно, демонстрационный пример. И в простых приложениях можно обойтись без этого. Но! Такой метод
программирования избавит Вас от головной боли в дальнейшем. И упростит дальнейшую модификацию приложения. Так как чем меньше части кода связаны друг с другом, тем меньше вероятность, что при изменении одной части возникнет необходимость в серьезном изменении другой.
* Стоимость одного СМС-сообщения от 7.15 руб. и зависит от оператора сотовой связи.
(полный список тарифов)
** При ошибочном вводе номера ответа или текста #thank услуга считается оказанной, денежные средства не возвращаются.
*** Сумма выплаты эксперту-автору ответа расчитывается из суммы перечислений на портал от биллинговой компании.