Почему не вызывается деструктор?
пока пользователь его не закроет (т.е. программа создает экземпляр этого класса, вызывает метод PokasatModalno() - на этой точке открывается модальный фрейм, возврат из метода - по закрытии фрейма). Т.е. что-то наподобие ShowModal в Delphi.
Вот исходный код
{
public:
CGraphWin(CWnd *);
void PokasatModalno();
afx_msg void OnClose(void);
afx_msg void OnPaint(void);
afx_msg void OnSize( UINT, int, int);
afx_msg void OnDestroy();
afx_msg void OnCommand_Vihod();
private:
CWnd *pWnd; // родительское окно, к которому прикрепляется "модальный фрейм"
...
}
Вот конструктор
{
pWnd=pWnd_;
// создание окно фрейма с меню
Create(NULL, "График", WS_OVERLAPPEDWINDOW, rectDefault, pWnd, "GRAPHMENU");
}
Теперь самое интересное - метод PokasatModalno и обработчик OnClose
{
pWnd->EnableWindow(FALSE);
RunModalLoop(MLF_SHOWONIDLE); // ждет пока не будет вызван EndModalLoop
BOOL b=pWnd->EnableWindow(TRUE);
}
afx_msg void CGraphWin::OnClose()
{
// завершить цикл обработки сообщений
EndModalLoop(0);
}
Таким образом описав этот класс можно его использовать, предположим в главном окне приложения при обработке выбора пункта меню пишем:
{
CGraphWin *gw=new CGraphWin(this);
gw->PokasatModalno();
delete gw;
}
Все работает, окно CGraphWin отображается как модальный фрейм, его можно закрывать, снова открывать, но обработчик
OnDestroy в CGraphWin не вызывается!
После закрытия главного окна приложения в окне Output появляется предупреждение
Warning: calling DestroyWindow in CWnd::~CWnd; OnDestroy or PostNcDestroy in derived class will not be called.
Кто-нибудь может помочь разобраться, в чем дело?
{
CGraphWin *gw=new CGraphWin(this);
gw->PokasatModalno();
//delete gw;
gw->DestroyWindow();
}
или
{
CGraphWin *gw=new CGraphWin(this);
gw->PokasatModalno();
gw->DestroyWindow();
delete gw;
}
попробуй такий варианты :
{
CGraphWin *gw=new CGraphWin(this);
gw->PokasatModalno();
//delete gw;
gw->DestroyWindow();
}
или
{
CGraphWin *gw=new CGraphWin(this);
gw->PokasatModalno();
gw->DestroyWindow();
delete gw;
}
В первом случае сообщает в окне Output
Detected Memory Leaks,
во втором возникает Access Violation
Событие OnDestroy по прежнему не вызывается.
Несколько не правильно сформулирован вопрос: констуктор для объекта будет вызван в любом случае, если использовать delete в случае указателя или неявно для автоматического объекта.
Загвоздка именно в том, что не вызывается обработчик OnDestroy. Т.е. не освобождается объект.
Неужели никто с этим не сталкивался!
В первом случае сообщает в окне Output
Detected Memory Leaks,
во втором возникает Access Violation
Событие OnDestroy по прежнему не вызывается.
Несколько не правильно сформулирован вопрос: констуктор для объекта будет вызван в любом случае, если использовать delete в случае указателя или неявно для автоматического объекта.
Загвоздка именно в том, что не вызывается обработчик OnDestroy. Т.е. не освобождается объект.
Неужели никто с этим не сталкивался!
попробуй переопределить деструктор окна и вызови в нем DestroyWindow... ты уверен что в первом случае не вызывается OnDestroy ? проверь внимательно....
{
DestroyWindow();
// здесь выполянешь всю очистку
}
а не OnDestroy...
деструктор окна это :
{
DestroyWindow();
// здесь выполянешь всю очистку
}
а не OnDestroy...
Не помогает...
Вызов DestroyWindow() из деструктора снова вызывает (рекурсивно) этот деструктор. По крайней мере, это ясно по работе дебаггера...
Далее следует аварийный выход с сообщением Debug Assertion Failed!
Не помогает...
Вызов DestroyWindow() из деструктора снова вызывает (рекурсивно) этот деструктор. По крайней мере, это ясно по работе дебаггера...
Далее следует аварийный выход с сообщением Debug Assertion Failed!
Как говорили на Руси : Утро вечера мудренее ... иди проспись... по идее DestroyWindow должен только ( где то в недрах системы win32 ) удалять окно... как это может привести к рекурсивному вызову деструктора не представляюю... надо смотреть исходники MFC... хотя если ты уж перешел к определению своего деструкора то свой код в 1 сообщении ( этой темы на это форуме ) оставь без изменений... должно помочь
Это простое WIn32 Application, только в свойствах проекта нужно поставить
Use MFC in Static Library. Далее добавить в проект файлы - main.cpp, test.cpp, resource.rc
Специально для тестирования создал простенький проект. Предлагаю его испытать.
Это простое WIn32 Application, только в свойствах проекта нужно поставить
Use MFC in Static Library. Далее добавить в проект файлы - main.cpp, test.cpp, resource.rc
Попробуй переделать все в таком стиле ( см. прикрепление ). По крайней мере там обработчик OnDestroy() вызывается.
А оператор delete вызывает деструкторы классов, никаких функций он, естественно, не вызывает
Для вызова DestroyWindow попробуй послать окну WM_DESTROY или переобредели его в своем классе и обрабатывай.
А оператор delete вызывает деструкторы классов, никаких функций он, естественно, не вызывает
Вообщем то сие не совсем правильно.
The WM_DESTROY message is sent when a window is being destroyed. It is sent to the window procedure of the window being destroyed after the window is removed from the screen.
другими словами после вызова DestoryWindow ( функции API или ее обертки в MFC ) окну посылается сообщение WM_DESTROY ( опять таки из недр системы Win32 ).
Я просто хочу все оформить в виде отдельного компонента... без привязки к конкретному приложению.
Чтобы можно было добавить пару файлов в проект и затем использовать этот компонент с помощью его общедоступных методов.
Почему же появляется сообщение
Warning: Calling DestroyWindow in CWnd::~CWnd" Message
и не освобождается память в том тестовом проекте (test.zip), который я разместил в этой теме - для меня остается загадкой...
class CMainFrame : public CFrameWnd
{
.....
protected:
DECLARE_MESSAGE_MAP()
}
.cpp файл
// сразу после инклудов
IMPLEMENT_DYNCREATE(CMainFrame, CFrameWnd)
BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd)
...
ON_WM_DESTROY()
END_MESSAGE_MAP()
// Должно помочь ;)
Всем спасибо за внимание!
И наконец я не уверен что вызывать Create в конструкторе хорошая идея.
Вот переделка функций первоначального варианта.
{
m_pMainWnd = new CMainWin;
reinterpret_cast<CFrameWnd *>(m_pMainWnd)->Create(NULL, "Это главное окно", WS_OVERLAPPEDWINDOW,
CFrameWnd::rectDefault, 0, "MENU");
m_pMainWnd->ShowWindow(m_nCmdShow);
m_pMainWnd->UpdateWindow();
return TRUE;
}
afx_msg void CMainWin::OnCommand_Dialog()
{
CGraphWin *gw = new CGraphWin(this);
gw->Create(NULL, "Тест", WS_OVERLAPPEDWINDOW, CFrameWnd::rectDefault, this);
gw->ShowWindow(SW_SHOW);
gw->PokasatModalno();
gw->DestroyWindow();
}
void CGraphWin::PokasatModalno(void)
{
pWnd->EnableWindow(FALSE);
RunModalLoop(MLF_SHOWONIDLE);
BOOL b2=pWnd->EnableWindow(TRUE);
}
afx_msg void CGraphWin::OnDestroy()
{
CFrameWnd::OnDestroy();
AfxMessageBox("inDestroy");
}
afx_msg void CGraphWin::OnClose()
{
EndModalLoop(0);
AfxMessageBox("inClose");
//CFrameWnd::OnClose(); - чето он плохо работает с ModalLoop, перенесем OnDestroy в OnCommand_Dialog()
}
Теперь тебе в принципе уже ModalLoop не нужен, окно не закроется, пока его не закроют вручную (или через DestroyWindow)
http://sources.codenet.ru/download.php?id=678&cid=11&o=2&my=0
Там размещен компонент, в котором используется аналогичная модель.
Смотри как легко с его помощью выводится 2-мерный график
float *x1;
float *y1;
float *x2;
float *y2;
n1=100;
n2=100;
srand( (unsigned)time( NULL ) );
x1=new float[n1];
y1=new float[n1];
x2=new float[n2];
y2=new float[n2];
for(i=0;i<n1;i++)
{
x1=(float)rand();
y1=(float)rand();
}
for(i=0;i<n2;i++)
{
x2=(float)rand();
y2=(float)rand();
}
CGraph2Win cgw(this);
cgw.DobavitNaborDannih(n1,x1,y1,"первый набор");
cgw.DobavitNaborDannih(n2,x2,y2,"второй набор");
cgw.PokasatModalno();
delete [] x1;
delete [] y1;
delete [] x2;
delete [] y2;
Если бы не ModalLoop, у тебя бы вызов метода PokasatModalno() не ждал бы когда пользователь закроет окно, т.е. сами данные для отображения пришлось бы копировать в члены класса, иначе они будут недоступны (сработает delete, т.к. PokasatModalno() не ждет).
Все работает, окно CGraphWin отображается как модальный фрейм, его можно закрывать, снова открывать, но обработчик
OnDestroy в CGraphWin не вызывается!
После закрытия главного окна приложения в окне Output появляется предупреждение
Warning: calling DestroyWindow in CWnd::~CWnd; OnDestroy or PostNcDestroy in derived class will not be called.
Кто-нибудь может помочь разобраться, в чем дело?
Видишь ли обработчик OnDestroy не вызывается так отсуствует команда типа
object_your_class->DestroyWindow().
вызов DestroyWindow происходит в базовом классе ( в данном случае CWnd ) и вследствии устройства MESSAGE_MAP в MFC твой обработчик ( в производном классе не вызывается ). Divide et impera.
По моему ты страдаешь херней. Все что тебе нужно эт грамотно переписать виртуальный деструктор. А также уменьшить кол-во самодеятельности при определении производных классов. Как я уже когда то заявлял ))) не надо бех крайней необходмости отклоняться от общепринятых паттернов ( в данном случае неявных ), так как они проверены многолетней практикой и имно она в этом деле основной аргумент. Если вышесказанное тебе непонятно то либо прочти инструкции ( в данном случае к MFC, а также приницпов OOP ), либо тебя научит жизнь... но на это может уйти много времени.
Честно говоря, не совсем понял, как переписать виртуальный деструктор в тестовом примере test.zip, чтобы все заработало...
Пробовал разные варианты, пока сам не понял, что логически нужно разнести процедуры, которые вызываются при посылке Windows сообщений (OnClose, On Destroy, OnPaint,...) и моих процедур, предназначенных для создания, отображения окна, добавления набора данных.
Когда это понял, создал 2 класса (файл test_fix.zip), один из которых включал в качестве члена указатель на другой.
Т.е. в первом классе разместил метод для отображения окна, второй класс и есть общепринятый паттерн.
И тогда все заработало.
Согласитесь, проще когда один класс ты создал сам, а второй полностью переписан в идеологии MFC (т.е. включает предопределенные в MFC функции).
Понимаю, что когда что-то проверено временем, на этом нужно основываться. И делать так, как это обычно все делают.
Но посмотрите исходники
http://sources.codenet.ru/download.php?id=678&cid=11&o=2&my=0
компонента для вывода графики, в котором использована модель, о которой мы говорим.
Вы просто добавляете два файла в проект - и можете простыми логичными методами, выводить окно с графиком.
По-моему общепринятые паттерны не дают такой возможности... Или там это делается сложнее. Может я не прав, тогда объясните, как позволяют это делать стандартные средства.
На мой взгляд, чем проще, логичнее сама идея, тем лучше это для пользователя, который с ней работает.
Я попытался создать простой логичный класс для вывода 2-d графики. И если есть недостатки, готов их рассмотреть.
Правильнее бы было использовать в качестве базового класса не CFrameWnd, а собственно CWnd. Кардинальным образом уменьшается кол-во всякого рода минингита, а также расширяется возможность использования...
Это правильно. Просто в CFrameWnd уже многое сделано, а при использовании CWnd нужно будет это доделывать.
Например, мне не удалось отобразить окно класса CWnd в том же виде, что и окно класса CFrameWnd (в частности, была системная иконка в левом верхнем углу для CWnd, а не иконка приложения в случае CFrameWnd, окно нельзя было активизировать, закрыть).
в коде MFC эти действия выполняются, если разобраться их можно реализовать.
Это правильно. Просто в CFrameWnd уже многое сделано, а при использовании CWnd нужно будет это доделывать.
Гмс... ничего там доделывать не надо... три строчки кода дополнительных небольше :)
Например, мне не удалось отобразить окно класса CWnd в том же виде, что и окно класса CFrameWnd (в частности, была системная иконка в левом верхнем углу для CWnd, а не иконка приложения в случае CFrameWnd, окно нельзя было активизировать, закрыть).
в коде MFC эти действия выполняются, если разобраться их можно реализовать.
Почитай основы создания оконных приложений под win32... в частности набор стилей для окна WS_... & WS_EX_.... зато скоко минингита будет что б использовать твое окно в диалоговом приложении ( концепции SDI & MDI не внемлю в принципе, а потому пользуюсь, диалогами :) ).
Гмс... ничего там доделывать не надо... три строчки кода дополнительных небольше :)
Почитай основы создания оконных приложений под win32... в частности набор стилей для окна WS_... & WS_EX_.... зато скоко минингита будет что б использовать твое окно в диалоговом приложении ( концепции SDI & MDI не внемлю в принципе, а потому пользуюсь, диалогами :) ).
Уважаемые читатели форума, коллеги!
Объясните пожалуйста (взяв за основу файл test_fix.zip (см. прикрепление выше)) как изменить класс отображаемого окна и сделать его не на основе CFrameWnd, а на основе CWnd.
У меня это к сожалению не получается.
Уважаемые читатели форума, коллеги!
Объясните пожалуйста (взяв за основу файл test_fix.zip (см. прикрепление выше)) как изменить класс отображаемого окна и сделать его не на основе CFrameWnd, а на основе CWnd.
У меня это к сожалению не получается.
)))
Уважаемые читатели форума, коллеги!
Объясните пожалуйста (взяв за основу файл test_fix.zip (см. прикрепление выше)) как изменить класс отображаемого окна и сделать его не на основе CFrameWnd, а на основе CWnd.
У меня это к сожалению не получается.
Ты знаешь, лет семь назад когда я начинал снова заниматься программированием после длительного перерыва ( на занятия спортом ) я задавал кучу гораздо менее глупых вопросов знакомым очень опытным и высокооплачиваемым программистам. Они всегда меня посылали куда подальше ( не прямым текстом конечно ).... только счас я понимаю какую НЕОЦЕНИМУЮ услугу они мне сделали... какое же это счастье иметь способность разобраться во всем самому... умрите ЛАМЕРЫ.
Уважаемые читатели форума, коллеги!
Объясните пожалуйста (взяв за основу файл test_fix.zip (см. прикрепление выше)) как изменить класс отображаемого окна и сделать его не на основе CFrameWnd, а на основе CWnd.
У меня это к сожалению не получается.
Ладно су.. уморили уже. Предлагаю следующее решение ( для тех конечно кто его понимает ).
{
public:
SetGraphFunction( // указатель на функцию озращающую необходмые значения );
// Также необходим ряд методов устанавливающих необходимые атрибуты : цвет графика, шаг сетки и т.п.
OutputTo( CDC* dc );
};
// sample to use class Graph.
//метод OnPaint какого-либо класса какого-либо окна :
CMyGraph::OnPaint()
{
CPaintDC dc( this );
Graph graph;
graph.SetFunction( ... );
graph.Set.....
graph.Set.....
graph.OutputTo( &dc );
}
Хотя вообщем то это частный случай паттерна Strategy и здесь я несколько его нарушаю... может кто скажет в чем ? :)))))
Гмс... ничего там доделывать не надо... три строчки кода дополнительных небольше :)
Специально поработал над CWnd. Ни о каких трех строках не может быть и речи. См. вложение.
Специально поработал над CWnd. Ни о каких трех строках не может быть и речи. См. вложение.
Если это была попытка переделать задачу в соответсвии с моим последним постом в этой теме то у меня есть ряд замечаний.
class Graph - представляет собой сущность - "График".
его метод OutputTo( CDC* dc, .... ) - должен реализовать алгоритм рисования графика в каком либо DeviceContext ( класс CDC* dc ), с использованием методов класса CDC. Остальные функции класса Graph просто задают параметры этого рисования ( то бишь функцию вида y=f(x), цвет, и т.п. ). Таким образом мы отвязываемся от какого-либо конкретного класса какого-либо конкретного окна и можем спокойно сосредоточиться на качественной реализации алгоритма рисования(функция OutputTo ). Помимо этого это дает возможность использовать данный класс для вывода графика на принтер и др.устройства ( посредством передачи ему соответсующего объекта класса CDC). Что же касается окон то уже в соответсвующем приложении мы создаем необходимое нам окно на основе подходящего для этого класса ( будь то CWnd or CFrameWnd ) и перегружаем в нем метод OnPaint в котором получаем DeviceContext для этого окна ( методом CPaintDC dc( this ) ). и выводим в него наш график. Помимо этого это дает нам возможность нарисовать еще что -нибудь в этом в окне в соответсвии со спецификой данного приложения а также реализовать дополнительную функциональность окна такую как PokasatModalno и др., которая в других приложения может оказаться лишней и даже мешать.
Учите паттерны.
Да, согласен, что такой подход обеспечит большую функциональность. Это будет достигаться более сложными (и вместе с тем более гибкими) методами.
Если создавать большой комплекс, где было бы несколько различных окон, обеспечивающих вывод графики, то многократное использование класса Graph с функцией Output несомненно давало бы преимущества.
Может в этом плане здесь есть действительно есть недостатки. Но честно говоря у меня не стоит такой задачи. Мне хватает этого компонента...пока.
Пожалуй у меня есть другие замечания к созданному компоненту. Это возможность обеспечить вывод данных, где ось X - нечисловая (например, название месяцев). Просто имею дело с временными рядами. Еще одно мелкое замечание - это вывод делений по осям. Я не могу найти простое решение.
Покажите что вы делаете, над чем работаете. Мне также интересно посмотреть на разработки других специалистов. Пусть это будет компонент для вывода графики, пусть это будет форум других разработчиков, пусть это будет сайт, где можно увидеть и обсудить аналогичные разработки.
Увидев разработки других специалистов можно понять свои недостатки.
Если кто-то готов заняться доработкой моего компонента для вывода графики - пожалуйста, вышлю все исходники. Если кому-то действительно интересно.
Вообще я хотел создать окно вывода графика на основе CWnd, а не CFrameWnd...
Да, согласен, что такой подход обеспечит большую функциональность. Это будет достигаться более сложными (и вместе с тем более гибкими) методами.
Не согласен что этот метод более сложен....на самом деле он гораздо проще.
Не согласен что этот метод более сложен....на самом деле он гораздо проще.
Мы говорим о разных способах достижения одной и той же цели. Представляю компонент для вывода графики в виде окна - его можно увидеть,"потрогать", переместить.
Т.е. это не контекст устройства, скрытый в недрах ОС, а то, что вполне осязаемо.
При таких подходах для решения одной и той же небольшой задачи мне не кажется, что они сильно отличны, хотя, повторюсь, для разработки своих приложений с множеством окон, в которые выводится графика, второй подход предпочтительнее.
У меня другой вопрос по графикам - как сделать, чтобы шкала по осям была степенью 2 (т.е. деления -0,5, -0,25, 0, 1, 0,25, 0,5).
И второе - обеспечение вывода данных, по оси X которым - подписи (например, название месяцев).
Если у кого-то есть идеи - было бы интересно их обсудить.
Мы говорим о разных способах достижения одной и той же цели. Представляю компонент для вывода графики в виде окна - его можно увидеть,"потрогать", переместить.
Т.е. это не контекст устройства, скрытый в недрах ОС, а то, что вполне осязаемо.
При таких подходах для решения одной и той же небольшой задачи мне не кажется, что они сильно отличны, хотя, повторюсь, для разработки своих приложений с множеством окон, в которые выводится графика, второй подход предпочтительнее.
У меня другой вопрос по графикам - как сделать, чтобы шкала по осям была степенью 2 (т.е. деления -0,5, -0,25, 0, 1, 0,25, 0,5).
И второе - обеспечение вывода данных, по оси X которым - подписи (например, название месяцев).
Если у кого-то есть идеи - было бы интересно их обсудить.
Елки... мне б твои проблемы....
Елки... мне б твои проблемы....
Это не так просто как кажется. Если в поисковике набрать "масштабирование осей", то можно найти множество вопросов, на которые не так много ответов. Нашел только одно более-менее ясное изложение - на rsdn.ru, но у этого подхода есть недостатки.
Это не так просто как кажется. Если в поисковике набрать "масштабирование осей", то можно найти множество вопросов, на которые не так много ответов. Нашел только одно более-менее ясное изложение - на rsdn.ru, но у этого подхода есть недостатки.
Я программировал вещи намного сложнее и там особых проблем при правильном подходе нету.. в частности я делал ActiveX для отображения объектов в системе кооррдинат азимут-дальнось, гистграмму для отображения частот объектов и т.п. там было и масщтабирование и т.п...
Я программировал вещи намного сложнее и там особых проблем при правильном подходе нету.. в частности я делал ActiveX для отображения объектов в системе кооррдинат азимут-дальнось, гистграмму для отображения частот объектов и т.п. там было и масщтабирование и т.п...
Покажите этот компонент. Хотя бы то, что касается масштабирования.
Покажите этот компонент. Хотя бы то, что касается масштабирования.
Сча ... тока шнурки поглажу.... ты что нибудь о процентах и пропорциях слышал ? :))))
Сча ... тока шнурки поглажу.... ты что нибудь о процентах и пропорциях слышал ? :))))
интересует лишь один аспект - это масштабирование.
Проценты и пропорции - к чему это?