Отговори на тема  [ 22 мнения ]  Отиди на страница 1, 2  Следваща
Проблем с затваряне на модален диалог. 
Автор Съобщение
Ранг: Форумен бог
Ранг: Форумен бог
Аватар

Регистриран на: Нед Окт 31, 2004 9:19 pm
Мнения: 4464
Местоположение: Stara Zagora
Мнение Проблем с затваряне на модален диалог.
Случая е следния:
Имам един модален диалог който стартира друг модален диалог. Това е извикването на 2 рия модален диалог
Код:
CYesNoDlg *dlg = new CYesNoDlg(this);
dlg->DoModal();
dlg->DestroyWindow();
delete dlg;

Но в първия диалог имам проверка за наличност на един процес която се извиква периодично от таймера. Ако процеса е прекъснат дава OnOK() и по този начин диалога се затваря. Това е извикването на първия диалог от main window
Код:
иf ( stg.user )
    {
      CPhoneNumbersDlg *dlg = new CPhoneNumbersDlg(this);
                dlg->DoModal();
      dlg->DestroyWindow();
      delete dlg;
      return;
    }

Но по този начин 2 рия модален диалог не се затваря. Не намерих при затварянето си първия диалог да праща на 2 рия някакво съобщение. Затова и прецених че мога да проверявам CWnd * укзателя който предавам на 2 рия диалог.
След затварянето и изтриването на CPhoneNumbersDlg очаквам указателя към него който имам предаден на
2 рия диалог да е невалиден. А не е така. Получавам си съвсем валиден handle към класа също и не мога по него по нормален начин да установя дали първия диалог съществува.

Най накрая написах това в 2 рия диалог и неочаквано си работи съвсем нормално.
Код:
 
void CYesNoDlg::OnTimer(UINT_PTR nIDEvent)
{
   if (nIDEvent==TIMER_TEST)
   {
      if ( GetOwner()->IsWindowVisible() == NULL )
      {
         OnOK();
      }
   }
   CDialog::OnTimer(nIDEvent);

i


Някой може ли да обясни тази мистерия,как така извиквам функция в член на клас който е вече изтрит и това работи и стабилно на това отгоре.
И има ли някакъв по цивилизован метод по който да разбера дали parrent window се е затворил?


Чет Яну 10, 2008 4:16 pm
Профил
Ранг: Форумен бог
Ранг: Форумен бог
Аватар

Регистриран на: Съб Сеп 25, 2004 12:32 pm
Мнения: 8382
Местоположение: София
Мнение 
Диалозите се затварят единствено и само с OnOK() и OnCancel().


Чет Яну 10, 2008 5:48 pm
Профил
Ранг: Форумен бог
Ранг: Форумен бог
Аватар

Регистриран на: Нед Окт 31, 2004 9:19 pm
Мнения: 4464
Местоположение: Stara Zagora
Мнение 
Ами така е. Първия съм написал че го затварям с OnOK(). А втория в сорса се вижда че пак го затварям с OnOK. Но в случая това не е въпроса,с това проблеми няма.


Чет Яну 10, 2008 7:02 pm
Профил
Ранг: Форумен бог
Ранг: Форумен бог
Аватар

Регистриран на: Нед Юли 24, 2005 10:28 am
Мнения: 2658
Мнение 
Код:
dlg->DestroyWindow();

това е проблема, махни го. излизайки от ДоМодал, вече прозореца е утрепан.
а, и още нещо, защо new/delete? просто си декларирай "променлива", както си декларираш инт или флоат, динамичната памет не е за игра :)


Чет Яну 10, 2008 8:52 pm
Профил
Ранг: Форумен бог
Ранг: Форумен бог
Аватар

Регистриран на: Нед Окт 31, 2004 9:19 pm
Мнения: 4464
Местоположение: Stara Zagora
Мнение 
Това го сложих допълнително като видях че се държи алогично и тръгнах да търся проблема.
Чета тук в Msdn-a че е проблематично да изтривам с delete CWnd обект и било по добре така. Но Разлика нема.

В много книжки за visual C++ съм виждал че се създават диалозите динамично в примерите. И откак програмирам така си ги и създавам и аз. Явно не е съвсем неправилна техника.


Чет Яну 10, 2008 11:26 pm
Профил
Ранг: Форумен бог
Ранг: Форумен бог
Аватар

Регистриран на: Съб Сеп 25, 2004 12:32 pm
Мнения: 8382
Местоположение: София
Мнение 
Също така е много важно диалога да е направен в основния тред и пак там да е затворен. Иначе стават бози (най-често не се затваря коректно).


Пет Яну 11, 2008 2:08 am
Профил
Ранг: Форумен бог
Ранг: Форумен бог
Аватар

Регистриран на: Нед Окт 31, 2004 9:19 pm
Мнения: 4464
Местоположение: Stara Zagora
Мнение 
Така е направено. Не е проблема в това.


Пет Яну 11, 2008 2:56 am
Профил
Ранг: Форумен бог
Ранг: Форумен бог
Аватар

Регистриран на: Нед Юли 24, 2005 10:28 am
Мнения: 2658
Мнение 
динамичното създаване не е проблем технически, абсолютно еквивалентно е на директното инстанциране. за това че в книгите така го показват и аз май съм виждал, което ме дразни. както и да е, проблема явно е някъде извън това което си дал. явно още овладяваш нещата, понеже си писал някои забавни неща, например това GetOwner()->IsWindowVisible() == NULL :)
значи кажи накратко какво трябва да става по замисъл, какво става реално и може да дадеш ключовите парчета код, ако не е твърде много.


Пет Яну 11, 2008 9:25 am
Профил
Ранг: Форумен бог
Ранг: Форумен бог
Аватар

Регистриран на: Нед Окт 31, 2004 9:19 pm
Мнения: 4464
Местоположение: Stara Zagora
Мнение 
Виж в първото съобщение. Там детайлно съм описал какво правя и какво става. Друга част от кода не е намесена. Нещо особенно има в работата с динамични обекти което не схващам. А и вероятно това което искам да направя се прави по някакъв по цивилизован начин.

Най синтезирано казано трябва в един модален диалог да правя проверка дали диалога който го е стартирал не е затворен вече.

А какво му е комичното на
GetOwner()->IsWindowVisible() == NULL
освен че трябва да е GetOwner()->IsWindowVisible() == 0 но и така с NULL си работи по същия начин и се интерпретира като 0.
Не че твърдя че съм спец по VC++. По скоро съм аматьор. :)


Пет Яну 11, 2008 1:39 pm
Профил
Ранг: Форумен бог
Ранг: Форумен бог
Аватар

Регистриран на: Пет Яну 19, 2007 9:16 am
Мнения: 1063
Местоположение: путинофили: "иди н***й"
Мнение 
Nikola Kirov написа:
Виж в първото съобщение. Там детайлно съм описал какво правя и какво става. Друга част от кода не е намесена. Нещо особенно има в работата с динамични обекти което не схващам. А и вероятно това което искам да направя се прави по някакъв по цивилизован начин.

Най синтезирано казано трябва в един модален диалог да правя проверка дали диалога който го е стартирал не е затворен вече.

А какво му е комичното на
GetOwner()->IsWindowVisible() == NULL
освен че трябва да е GetOwner()->IsWindowVisible() == 0 но и така с NULL си работи по същия начин и се интерпретира като 0.
Не че твърдя че съм спец по VC++. По скоро съм аматьор. :)


не ползвам VC ... и без да се задълбавам в проблема ти:

1) това: GetOwner()->IsWindowVisible()
никак не е желателно - ако GetOwner() - е вече невалиден - викаш функция от невалиден клас.

2) най-лесния и сигурен начин да провериш дали един прозорец е валиден е:
::IsWindow(hWnd);
където hWnd е хендъла на прозореца.

ако искаш да затвориш прозорец - най-сигурно е с

::SendMessage (WM_CLOSE, hWnd, 0, 0);

...

в противен случай - трябва да си направиш комуникация м/у прозорците !


това dlg->DestroyWindow();

мисля че се дублира с delete dlg; - тъй че и то май е проблем!

това дето в таймера проверяваш ... също е доста недобър подход ... ама това е друга тема :)

_________________
путинофили: "иди н***й"


Пет Яну 11, 2008 4:27 pm
Профил
Ранг: Форумен бог
Ранг: Форумен бог
Аватар

Регистриран на: Нед Окт 31, 2004 9:19 pm
Мнения: 4464
Местоположение: Stara Zagora
Мнение 
точно от ::IsWindow(hWnd) почнах и аз. И макар първия диалог да е вече затворен си казва че е валиден window. Което много ме учуди.

И оттам почнах с шамански похвати като да извиквам функция от несъществуващ вече обект. Интересното е че работи устойчиво. Това ми е другия въпрос. Що така може?

а delete не парви нищо ако е приложено към невалиден обект. По нагоре казах защо съм го написал така и че това не е проблем.


Пет Яну 11, 2008 4:53 pm
Профил
Ранг: Форумен бог
Ранг: Форумен бог
Аватар

Регистриран на: Пет Яну 19, 2007 9:16 am
Мнения: 1063
Местоположение: путинофили: "иди н***й"
Мнение 
Nikola Kirov написа:
точно от ::IsWindow(hWnd) почнах и аз. И макар първия диалог да е вече затворен си казва че е валиден window. Което много ме учуди.

И оттам почнах с шамански похвати като да извиквам функция от несъществуващ вече обект. Интересното е че работи устойчиво. Това ми е другия въпрос. Що така може?


теоретически ::IsWindow не ти гарантира че hWnd е валиден :)

проблема е че ако твоя hWnd вече е умрял ... друго приложение може да създаде друг прозорец и Windows да му присвои същия hWnd като на твоя!
така IsWindow(hWnd) ще е true, но за друг прозорец ...

затова най-добре е да имаш комуникация м/у прозорците - примерно родителя ако ще мре - вдига флаг в детето че вече то е сираче ... и обратно ако детето ще мре - казва на родителя че е умряло (флаг) ... методи много въпрос на реализация!

Що се отнася до: "...като да извиквам функция от несъществуващ вече обект ..."
проблема е че класа сочи в свободен блок и резултатите са непредсказуеми - на практика "this" сочи към обекта който е изтрит, но всяко new/delete, malloc, .... може да му скапе съдържанието и бозата е пълна!

затова и ползвам BCB - там CodeGuard е невероятно полезна - лови 99.9% от подобни проблеми (0.01% остават за програмиста:) )!

_________________
путинофили: "иди н***й"


Пет Яну 11, 2008 5:00 pm
Профил
Ранг: Форумен бог
Ранг: Форумен бог
Аватар

Регистриран на: Нед Окт 31, 2004 9:19 pm
Мнения: 4464
Местоположение: Stara Zagora
Мнение 
Не е е към друг прозорец този хендъл. Точно към този изтрития е проверих. И аз се замислих за варианта с комуникация. Но използването става сложно по този начин. Трябва в класа на диалога който извиква 2 рия диалог да направя указател към диалога който отварям /2рия/ и чрез него от функцията OnClose на първия да затворя 2 рия. Пълна боза.
Има ли начин да изпратя Мessage на 2 рия прозорец без да имам указател към него. Тоест OnClose на първия диалог да праща Message към евентулано отворен модален диалог. Нещо като изпращане на Message на всички child window на диалога. То модалния диалог е малко странен child window също и нямам идея каква ще е хавата при такава ситуация.


Пет Яну 11, 2008 5:26 pm
Профил
Ранг: Форумен бог
Ранг: Форумен бог
Аватар

Регистриран на: Пет Яну 19, 2007 9:16 am
Мнения: 1063
Местоположение: путинофили: "иди н***й"
Мнение 
Nikola Kirov написа:
... Трябва в класа на диалога който извиква 2 рия диалог да направя указател към диалога който отварям /2рия/ и чрез него от функцията OnClose на първия да затворя 2 рия. Пълна боза...


не е боза - просто така трябва да се прави - и двата класа да си имат указателите един друг и при някое събитие да си се разбират!

без hWnd - няма как да прaтиш съобщение - просто SendMessage/PostMessage си иска hWnd :)
а и обработката на съощенията е асихронна (PostMessage) - и може да доведе до други проблеми ... така че първия метод е за предпочитане.

_________________
путинофили: "иди н***й"


Пет Яну 11, 2008 5:57 pm
Профил
Ранг: Форумен бог
Ранг: Форумен бог
Аватар

Регистриран на: Нед Окт 31, 2004 9:19 pm
Мнения: 4464
Местоположение: Stara Zagora
Мнение 
Май трябва да отворя тема "Ах как мразя MFC"
Що всичко трябва да става с много писане ......
В последно време поусвоявам по малко QT.
Там нещата си личи че са мислени,не като при тия тъпаци от Мокрософт.


Пет Яну 11, 2008 6:35 pm
Профил
Покажи мненията от миналия:  Сортирай по  
Отговори на тема   [ 22 мнения ]  Отиди на страница 1, 2  Следваща

Кой е на линия

Потребители разглеждащи този форум: 0 регистрирани и 1 госта


Вие не можете да пускате нови теми
Вие не можете да отговаряте на теми
Вие не можете да променяте собственото си мнение
Вие не можете да изтривате собствените си мнения
Вие не можете да прикачвате файл

Търсене:
Иди на:  
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group.
Designed by ST Software for PTF.
Хостинг и Домейни