Форум: "Основная";
Текущий архив: 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.068 c