Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Основная";
Текущий архив: 2005.02.06;
Скачать: [xml.tar.bz2];

Вниз

TForm::OnShow   Найти похожие ветки 

 
Ермак ©   (2005-01-17 21:14) [0]

Значится, встала такая проблемка. Перед открытием главной формы программы необходимо показать форму запроса логина и пароля.

Сделал эту форму и функцию для ее создания/отображения/получения данных/закрытия (пардон, что исходники на C++ Builder):

bool EntranceBox(unsigned maxlen,AnsiString& login,AnsiString& password,bool& change)
{
       Application->CreateForm(__classid(TEntranceForm), &EntranceForm);
       EntranceForm->Edit1->Text = "";
       EntranceForm->Edit2->Text = "";
       EntranceForm->Edit1->MaxLength = maxlen;
       EntranceForm->Edit2->MaxLength = maxlen;
       switch( EntranceForm->ShowModal() ){
       case mrOk:
               login = EntranceForm->Edit1->Text;
               password = EntranceForm->Edit2->Text;
               change = false;
               EntranceForm->Close();
               return true;
       case mrRetry:
               login = EntranceForm->Edit1->Text;
               password = EntranceForm->Edit2->Text;
               change = true;
               EntranceForm->Close();
               return true;
       default:
               EntranceForm->Close();
               return false;
       }
}

Поместил ее вызов в OnCreate главной формы, и ясень пень, это не заработало - после закрытия единственного окна ввода пароля Винда  завершает приложение. Недолго думая, засунул вызов в OnShow - и все стало работать прекрасно.

Затем пишу второе приложение, которое точно так же запрашивает пароль. Но... После того, как OnShow отрабатывает, главная форма почему-то закрывается. Зарывается корректно - то есть, вызывается
OnClose, все деструкторы и т.п. Если перехватывать OnCloseQuery(), то закрытие можно пресечь, но это же не выход - почему вообще форма закрываться начинает?

Приложения идентичны, правда, создаются несколько лишних мьютексов, но дело не в них - если закомментировать вызов EntranceBox(), все работает нормально.

В чем же проблема? Подскажите, уважаемые!


 
Arnold ©   (2005-01-17 22:44) [1]

Ясень пень в С++ при обработке оператора switch компилятор пробегает по всем ветвям case и обязательно в этом случае  нужно в конце каждого case ставить break. Поробуй должно вроде так работать.

switch( EntranceForm->ShowModal() ){
      case mrOk:
              login = EntranceForm->Edit1->Text;
              password = EntranceForm->Edit2->Text;
              change = false;
              EntranceForm->Close();
              return true;
             break;
       case mrRetry:
              login = EntranceForm->Edit1->Text;
              password = EntranceForm->Edit2->Text;
              change = true;
              EntranceForm->Close();
              return true;
              break;
      default:
              EntranceForm->Close();
              return false;
              break
      }


 
jack128 ©   (2005-01-18 01:43) [2]

Arnold ©   (17.01.05 22:44) [1]
так у автора же в каждой ветке switch"a по return"у стоит

Ермак ©   (17.01.05 21:14)
Поместил ее вызов в OnCreate главной формы, и ясень пень, это не заработало - после закрытия единственного окна ввода пароля Винда  завершает приложение.

Дело не в Винде, а в том как устроена VCL. Если бы ты создовал окно так EntranceForm := TEntranceForm.Create(Application){сорри за Object Pascal} то все бы заработало.
Ермак ©   (17.01.05 21:14)
Но... После того, как OnShow отрабатывает, главная форма почему-то закрывается

а вот это странно. Приведи весь обработчик OnShow..


 
Ермак ©   (2005-01-18 12:06) [3]

>Дело не в Винде, а в том как устроена VCL.

Не-а. Это я точно знаю, Рихтера хорошо читал. Пока процесс не создал ни одного окна, он работает сколько угодно. После того, как хотя бы одно окно создано, Винда считает его за главное и при его закрытии отрубает процесс. Никакие VCL-деструкторы уже не вызваются.

А насчет обработчика - вот он:

void __fastcall TFormMain::FormShow(TObject *Sender)
{
       try{
       HINSTANCE hashlib = LoadLibrary("hash.dll");
       void __stdcall (*hashinit)() =
               (void __stdcall (*)())GetProcAddress(hashlib,"HashInit");
       hashinit();
       HashString = (void __stdcall (*)(char*,void*,unsigned))
               GetProcAddress(hashlib,"HashString");
       if( !HashString ) throw 1;
       }
       catch(...)
       {
               MessageBox(Handle,"Модуль hash.dll отсутствует или поврежден!",
               "Ошибка",MB_OK|MB_ICONERROR);
               TerminateThread(GetCurrentThread(),1);
       }
       user[0] = 0;

       base = new AuTrade::DriverAccess();
       TIniFile* ini = new TIniFile(".\\acslocal.ini");
       AnsiString path = ini->ReadString("LOCAL BASE","path","?");
       delete ini;
exclusive:
       HANDLE mutex = CreateMutex(0,TRUE,"AuTradeBaseAccess");
       if( GetLastError() == ERROR_ALREADY_EXISTS )
       {
               CloseHandle(mutex);
               if( MessageBox(Handle,"Следует закрыть все другие окна, работающие \
с этой базой!","Ошибка",MB_RETRYCANCEL|MB_ICONWARNING) == ID_RETRY )
                       goto exclusive;
               else
                       TerminateThread(GetCurrentThread(),1);
       }
       AuTrade::ShopOpen(path.c_str());
       if( !AuTrade::ShopState() )
       {
               MessageBox(Handle,"Невозможно открыть или создать базу данных \
по пути, указанному в acslocal.ini!","Ошибка",MB_OK|MB_ICONERROR);
               TerminateThread(GetCurrentThread(),1);
       }
       base->Products = AuTrade::ShopProducts();
       base->Suppliers = AuTrade::ShopSuppliers();
       base->Actions = AuTrade::ShopActions();
       base->Acts = AuTrade::ShopActs();
       base->Invoices = AuTrade::ShopInvoices();
       base->Main = AuTrade::ShopMain();

       AnsiString login, password;
       bool change_password;
entrance:
       if( !EntranceBox(15,login,password,change_password) )
                       goto terminate;

       if( password == "" ) password = " ";
       char p[16];
       HashString(password.c_str(),p,15);
       p[15] = 0;

       try{
               shop = base->Main->GetAccess(login.c_str(),p,0);
               products = base->Products->GetAccess(login.c_str(),p,0);
               suppliers = base->Suppliers->GetAccess(login.c_str(),p,0);
               actions = base->Actions->GetAccess(login.c_str(),p,0);
               acts = base->Acts->GetAccess(login.c_str(),p,0);
               invoices = base->Invoices->GetAccess(login.c_str(),p,0);
       }
       catch(AuTrade::ErrorUnknownLogin)
       {
               MessageBox(Handle,"Пользователя с таким именем не существует.",
                       "Неверное имя пользователя",MB_OK|MB_ICONERROR);
               goto entrance;
       }
       catch(AuTrade::ErrorWrongPassword)
       {
               MessageBox(Handle,"Старый пароль введен неверно.",
                       "Неверный пароль",MB_OK|MB_ICONERROR);
               goto entrance;
       }

       OpenProductPart();
       ApplySettings();

       return;
terminate:
       AuTrade::ShopClose();
       CloseHandle(mutex);
       TerminateThread(GetCurrentThread(),1);
}

Кстати, интересно, что из FormShow программу никак иначе не прервешь, кроме TerminateThread(GetCurrentThread(),1), стандартные средства, натипа exit (аналог halt) вызывают ошибку: "невозможно изменить вс-во Visible".


 
Ермак ©   (2005-01-18 12:32) [4]

EntranceForm := TEntranceForm.Create(Application)

Попробовал так сделать. Проблема исчезла! Но либо я дурак, либо одно из двух...

Вернул обратно Application.CreateForm - и оно тоже работает! Фигня какая-то... Открыты два окна Билдера с похожими программами - в одной работает, в другой нет! Потом меняю строчку - работает, меняю обратно - снова работает! Честное слово, со вчерашнего вечера к клаве не прикасался...

Объянение одно: глюкавость IDE, которая чего-то вовремя не пересобрала, либо в отладочном режиме накосячила. У Билдера такое бывает, к сожалению, в отличие от Дельфи. Надо на VC переходить...

Ну ладно, проблема решилась. Спасибо!


 
KSergey ©   (2005-01-18 14:04) [5]

> [3] Ермак ©   (18.01.05 12:06)
> >Дело не в Винде, а в том как устроена VCL.
> Не-а. Это я точно знаю, Рихтера хорошо читал. Пока процесс
> не создал ни одного окна, он работает сколько угодно. После
> того, как хотя бы одно окно создано, Винда считает его за
> главное (?) и при его закрытии отрубает процесс. Никакие VCL-деструкторы
> уже не вызваются.

Бред!

Впрочем, если использовать такие решения

TerminateThread(GetCurrentThread(),1);

то, конечно, можно многое поиметь, в том числе - и невызов деструкторов VCL


 
jack128 ©   (2005-01-18 18:06) [6]

KSergey ©   (18.01.05 14:04) [5]
Это я точно знаю, Рихтера хорошо читал

то что ты рихтера читал - это хорошо, но наверника в плохом переводе. Мне такие встечались.

Процесс завершается в ТРЕХ(!!!) случаях
1) Завершаются все его потоки(это нормальный вариант)
2) Вызов ExitProcess
3) TerminateProcess


 
jack128 ©   (2005-01-18 18:08) [7]

jack128 ©   (18.01.05 18:06) [6]
KSergey ©   (18.01.05 14:04) [5]
Это я точно знаю, Рихтера хорошо читал

Сорри, естественно эту фразу сказал не Сергей, а Ермак


 
Дмитрий В. Белькевич   (2005-01-23 02:43) [8]

Так должно работать:

Application.Initialize;
PasswordDlg := TPasswordDlg.Create(Application);
if PasswordDlg.ShowModal <> mrOK then //нажали Cancel
 begin
  PasswordDlg.Free;
  exit;
 end;
Application.CreateForm(TForm1, Form1); //основная форма
for i := 0 to Screen.FormCount - 1 do
 Internat.Execute(Screen.Forms[i]); //переводим на другой язык
Application.Run;



Страницы: 1 вся ветка

Форум: "Основная";
Текущий архив: 2005.02.06;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.49 MB
Время: 0.034 c
14-1105405127
Поручик
2005-01-11 03:58
2005.02.06
Как вы думаете


3-1105067306
makz
2005-01-07 06:08
2005.02.06
Снова ХП


14-1105909240
Profi
2005-01-17 00:00
2005.02.06
Опрос


14-1105790085
DSKalugin
2005-01-15 14:54
2005.02.06
Где можно стырить список городов Украины?


4-1103374683
Zodchi
2004-12-18 15:58
2005.02.06
Получение списка устройств системы





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский