#ifndef Form1
#define Form1
#include "Form1.h"
//тут все остальное
#endif
WinForms две формы
На первой и на второй есть одна кнопка и текстбокс. Нужно что бы при нажатии кнопки на 1й форме появлялась 2я форма, а при нажатии кнопки на второй форме, она записывала какой-то текст в текстбокс 1й формы.
По-идее реализуется след. кодом:
На 1й форме:
private: System::Void button1_Click(System::Object^ sender, System::EventArgs^ e) {
form2 ^myobj1=gcnew form2;
myobj1->Show();
}
На 2й форме:
private: System::Void button1_Click(System::Object^ sender, System::EventArgs^ e) {
Form1 ^frm1;
frm1=this->Owner;
frm1->textBox1->Text ="321";
}
Но возникают ошибки, т.к. первая форма незнает что такое form2, а вторая форма незнает что такое form1.
По-идее в каждой форме нужно подключить файл другой, т.е.
в первой:
#include "form2.h"
во второй
#include "form1.h"
Но в таком случае возникает окуча ошибок, по всей видимости из-за двойного определения.
#ifndef
#pragma once
не помогают
Подскажите, пожалуйста, как реализовать данную задачу. Задача по своей сути элементарна, но как сделать - хз
Реализуйте метод, свойство или еще что вам нарвится и в первой форме его читайте. Это так - кстати.
Ошибки видимо лучше привести - так как телепатов тут нет. Но вероятно они связаны с тем что вы пытаетесь получить доступ к защищенным/закрытым членам класса (модификатор компонента по умолчанию private)
Пойдем по-порядку.
Значит создано 2 формы, соответственно первая Form1 и вторая Form2
На первой создаем текстбокс и кнопку, которой задаем код, который бы показывал нам 2ю форму. Вот собственно код:
private: System::Void button1_Click(System::Object^ sender, System::EventArgs^ e) {
Form2 ^frm2 = gcnew Form2();
frm2->Show();
}
Пытаемся запустить... Бац - ошибка
1>d:\programs\2forms\Form1.h(98) : error C2065: 'Form2' : undeclared identifier
1>d:\programs\2forms\Form1.h(98) : error C2065: 'frm2' : undeclared identifier
1>d:\programs\2forms\Form1.h(98) : error C2061: syntax error : identifier 'Form2'
1>d:\programs\2forms\Form1.h(99) : error C2227: left of '->Show' must point to class/struct/union/generic type
Естественно мы понимаем, что компилятор, читая код в файле Form1.h понятия не имеет, что есть еще класс Form2.h Ну мы исправляем это досадное недоразумение, путем записи в файл Form1.h следующей строчки:
#include "Form2.h"
Запускаем... Вуаля!! У нас на экране появляется форма. При нажатии на кнопку у нас появляется наша 2я форма. Казалось бы, с половиной задачи мы справились. Теперь нам нужно, что бы при нажатии кнопки во второй форме у нас появлялся какой-то текст в окне первой.
Идем на 2ю форму, создаем на ней кнопку, задаем кнопке код:
private: System::Void button1_Click(System::Object^ sender, System::EventArgs^ e) {
Form1 ^frm1=this->Owner;
frm1->textBox1->Text ="123";
}
Попутно не забываем в файле Form1.h сделать доступ public для нашего текстбокса, т.е. public: System::Windows::Forms::TextBox^ textBox1;
Пробуем запустить...
Опа... получаем целую кучу ошибок:
1>Compiling...
1>Form2.cpp
1>d:\programs\2forms\Form2.h(97) : error C2065: 'Form1' : undeclared identifier
1>d:\programs\2forms\Form2.h(97) : error C2065: 'frm1' : undeclared identifier
1>d:\programs\2forms\Form2.h(98) : error C2227: left of '->textBox1' must point to class/struct/union/generic type
1> type is ''unknown-type''
1>d:\programs\2forms\Form2.h(98) : error C2227: left of '->Text' must point to class/struct/union/generic type
1>2forms.cpp
1>d:\programs\2forms\Form2.h(97) : error C2065: 'Form1' : undeclared identifier
1>d:\programs\2forms\Form2.h(97) : error C2065: 'frm1' : undeclared identifier
1>d:\programs\2forms\Form2.h(98) : error C2227: left of '->textBox1' must point to class/struct/union/generic type
1> type is ''unknown-type''
1>d:\programs\2forms\Form2.h(98) : error C2227: left of '->Text' must point to class/struct/union/generic type
Опять же логично... Компилятор просматривая файл Form2.h понятия не имеет что такое Form1, а тем более, что такое Form1->textBox1->Text... Т.к. с такой проблемой мы уже сталкивались немного выше, пробуем решить ее аналогично. Добавляем в код файла Form2.h
#ifndef Form1
#include "Form1.h"
#endif
Запускаем... И что мы видим. Мы видим те 4 ошибки, которые появились еще когда мы не сделали #include в файле Form1.h, а так же все ошибки, которые мы получили до #include в файл Form2.h. Да плюс еще притесалась ошибка:
1>d:\programs\2forms\Form2.h(102) : error C2440: 'initializing' : cannot convert from 'System::Windows::Forms::Form ^' to 'My2forms::Form1 ^'
1> No user-defined-conversion operator available, or
1> Cast from base to derived requires safe_cast or static_cast
В общем вот такие пироги. Как все-таки сделать возможным доступ из Form2 в Form1 я - хз.
Код:
так же и в коде во втором заголовочном файле. Вы просто проверяете не установлено ли - а оно собственно и не установлено. :)
последняя ошибка связана с тем, что надо приводить тип формы к базовому типу. И все должно работать.
Ну и кроме этого может поможет пример
Ну и рекомендовал бы не использовать прямой доступ к компонентам.
Код:
//form1
#ifndef Form1
#define Form1
#include "Form2.h"
//тут все остальное
#endif
//Form2
#ifndef Form2
#define Form2
#include "Form1.h"
//тут все остальное
#endif
#ifndef Form1
#define Form1
#include "Form2.h"
//тут все остальное
#endif
//Form2
#ifndef Form2
#define Form2
#include "Form1.h"
//тут все остальное
#endif
Попробовал добавить
//form1
#ifndef Form1
#define Form1
#include "Form2.h"
//тут все остальное
#endif
//Form2
#ifndef Form2
#define Form2
#include "Form1.h"
//тут все остальное
#endif
Ошибки:
1>Form2.cpp
1>d:\programs\2forms\Form1.h(32) : error C3179: an unnamed managed type is not allowed
.........
....
....
1>2forms - 49 error(s), 4 warning(s)
Что касается вопроса. "Игры" с #include и #define здесь особо не помогут. Основная проблема в том, что по умолчанию среда добавляет реализацию обработчиков событий прямо в h файл. Но это не меняет принцип работы директивы #include - она все также просто включает содержимое одного файла в другой.
Поэтому и получается, что при компиляции класса Form2, ему необходимо знать о Form1 - это мы и делаем с помощью #include "Form1.h". Но это же директива включает реализацию процедуры из класса Form1, которой требуется Form2, реализации процедуры которого требуется Form1 и т.д. Получается такой вот замкнутый круг.
Вообщем я эту задачку решил с помощью раздельной компиляции. Т.е. обявления и определения обработчика в разных файлах. Но насколько это правильно в контексте управляемого C++ сказать не могу.
Код Form1.cpp
private: System::Void Form1::button1_Click(System::Object^ sender, System::EventArgs^ e) {
Form2 ^frm2 = gcnew Form2();
frm2->Show();
}
Код Form2.cpp
private: System::Void Form2::button1_Click(System::Object^ sender, System::EventArgs^ e) {
Form1 ^frm1=this->Owner;
frm1->textBox1->Text ="123";
}
В хеадерах Form1 и Form2 код одинаков:
#pragma once
#include "Form1.h"
#include "Form2.h"
При компиляции возникает только одна ошибка - error C2440: 'initializing' : cannot convert from 'System::Windows::Forms::Form ^' to 'My2forms::Form1 ^'
Помогите плиз, как сделать преобразование в базовый тип - this->Owner, потому что только он имеет тип System::Windows::Forms::Form ^ , все остальное имеет тип - My2forms::Form1.
Код:
Form1 ^ frm1 = (Form1 ^)this->Owner;
Код:
Form1 ^ frm1 = (Form1 ^)this->Owner;
Компилируется и запускается без ошибок, но когда нажимаешь кнопку на второй форме:
Код Form2.cpp
Код:
System::Void Form2::button1_Click(System::Object^ sender, System::EventArgs^ e)
{
Form1 ^ frm1 = (Form1 ^)this->Owner;
frm1->textBox1->Text ="123";
this->Close();
}
{
Form1 ^ frm1 = (Form1 ^)this->Owner;
frm1->textBox1->Text ="123";
this->Close();
}
Вываливется вот такая бяка:
Код:
Необработанное исключение типа "System.NullReferenceException" произошло в Form1.exe
Дополнительные сведения: В экземпляре объекта не задана ссылка на объект.
Дополнительные сведения: В экземпляре объекта не задана ссылка на объект.
Подскажите плиз как с этим бороться?
Update:
посмотрел в дебаггере - на этой строке:
Код:
Form1 ^ frm1 = (Form1 ^)this->Owner;
frm1 не получает адреса Form1, вообще ничего не получает - неопределенное значение. Поэтому вылазиет исключение типа "System.NullReferenceException". Подскажите плиз рабочий вариант кода :)
Цитата: klifleopard
...
Update:
посмотрел в дебаггере - на этой строке:
frm1 не получает адреса Form1, вообще ничего не получает - неопределенное значение. Поэтому вылазиет исключение типа "System.NullReferenceException". Подскажите плиз рабочий вариант кода :)
Update:
посмотрел в дебаггере - на этой строке:
Код:
Form1 ^ frm1 = (Form1 ^)this->Owner;
frm1 не получает адреса Form1, вообще ничего не получает - неопределенное значение. Поэтому вылазиет исключение типа "System.NullReferenceException". Подскажите плиз рабочий вариант кода :)
Дык может
Код:
Form2 ^ frm2 = (Form2 ^)this->Owner;
З.Ы. Не вникал в суть, могу лохануться...
Цитата: Lerkin
Дык может
З.Ы. Не вникал в суть, могу лохануться...
Код:
Form2 ^ frm2 = (Form2 ^)this->Owner;
З.Ы. Не вникал в суть, могу лохануться...
Да не, суть в том чтобы получить адрес родительской формы, поэтому все таки Form1. У меня просто складывается впечатление, что этот метод вообще не отрабатывает как надо, хотя ошибку в компиляторе не дает. :(
Все еще жду помощи, вопрос так и висит в воздухе :)
Цитата: klifleopard
Подскажите плиз как с этим бороться?
Все проще.
Код:
Form2 ^ frm2 = gcnew Form2();
frm2->Owner = this;
frm2->Show();
frm2->Owner = this;
frm2->Show();
Цитата: nikitozz
Все проще.
Код:
Form2 ^ frm2 = gcnew Form2();
frm2->Owner = this;
frm2->Show();
frm2->Owner = this;
frm2->Show();
Спасибо за подсказку nikitozz, только сейчас дошел до этого своим умом :)
Итак готовое решение, цена решения для меня 3 дня, даст Бог кому то поможет и сохранит время:
Код Form1.h:
Код:
public: System::Windows::Forms::TextBox^ textBox1;//тут меняем с private на public чтобы был доступ из другой формы к этому объекту
Код Form2.h: без изменений
Код Form1.cpp:
Код:
#include "stdafx.h"
#include "Form1.h" //подключаем заголовки
#include "Form2.h"
using namespace My11;
System::Void Form1::button1_Click(System::Object^ sender, System::EventArgs^ e) //кнопка показывающая форму 2
{
Form2 ^frm2 = gcnew Form2(); //создаем объект типа Form2 - frm2
frm2->Owner=this; //тут присваиваем объекту frm2 свойству "Ссылка на родительский объект" адрес родительской формы
frm2->Show(); //делаем видимой форму 2
#include "Form1.h" //подключаем заголовки
#include "Form2.h"
using namespace My11;
System::Void Form1::button1_Click(System::Object^ sender, System::EventArgs^ e) //кнопка показывающая форму 2
{
Form2 ^frm2 = gcnew Form2(); //создаем объект типа Form2 - frm2
frm2->Owner=this; //тут присваиваем объекту frm2 свойству "Ссылка на родительский объект" адрес родительской формы
frm2->Show(); //делаем видимой форму 2
Код Form2.cpp:
Код:
#include "StdAfx.h"
#include "Form2.h"
#include "Form1.h"
using namespace My11;
System::Void Form2::button1_Click(System::Object^ sender, System::EventArgs^ e) //кнопка пересылки значения на родительскую форму
{
Form1 ^frm1 = (Form1 ^)this->Owner; //присваиваем объекту frm1 адрес родительской формы, который присвоили в Form1.cpp
frm1->textBox1->Text ="123";// тут меняем значения на форме 1
this->Close();
}
#include "Form2.h"
#include "Form1.h"
using namespace My11;
System::Void Form2::button1_Click(System::Object^ sender, System::EventArgs^ e) //кнопка пересылки значения на родительскую форму
{
Form1 ^frm1 = (Form1 ^)this->Owner; //присваиваем объекту frm1 адрес родительской формы, который присвоили в Form1.cpp
frm1->textBox1->Text ="123";// тут меняем значения на форме 1
this->Close();
}
Всем спасибо за участие, отдельное огромное спасибо nikitozz, ты очень помог. Тему можно закрывать, модераторам отдельная просьба - решение поместить в FAQ или закрепить тему чтобы другие не мучились, встречал много подобных тем на разных форумах и ни в одной решения не было.
Код:
// form1:
#include "form2.h"
//...
form2^ myform = gcnew form2;
IntPtr MainWnd = this->Handle();
myform->Form1Wnd = (HWND)MainWnd.ToInt32();
myform->Show();
//...
protected: virtual void WndProc(Message %m) override {
if (m.Msg == WM_USER_1)
this->textBox1->Text = "Some text.";
Form::WndProc(m);
}
//...
// form2
// никаких #include "form1"
#define WM_USER_1 0xA000
//...
public
HWND Form1Wnd;
//...
private: System::Void button1_Click(System::Object^ sender, System::EventArgs^ e) {
::SendMessage(Form1Wnd, WM_USER_1, 0, 0);
}
#include "form2.h"
//...
form2^ myform = gcnew form2;
IntPtr MainWnd = this->Handle();
myform->Form1Wnd = (HWND)MainWnd.ToInt32();
myform->Show();
//...
protected: virtual void WndProc(Message %m) override {
if (m.Msg == WM_USER_1)
this->textBox1->Text = "Some text.";
Form::WndProc(m);
}
//...
// form2
// никаких #include "form1"
#define WM_USER_1 0xA000
//...
public
HWND Form1Wnd;
//...
private: System::Void button1_Click(System::Object^ sender, System::EventArgs^ e) {
::SendMessage(Form1Wnd, WM_USER_1, 0, 0);
}