Страница 1 из 2
Как сделать правильно окошко логина?
Добавлено: 18 май 2006, 09:44
Alchazar
Как правильно сделать окошко логина, может уже кто делал, поделитесь опытом, а то у меня никак невыходит
где ошибка?
Код: Выделить всё
begin
Application.Initialize;
// логотип
F_Logo:=TF_Logo.Create(Application);
F_Logo.Show;
F_logo.Update;
// загрузка основной формы
Application.CreateForm(TF_Main, F_Main);
Application.CreateForm(TF_Login, F_Login);
F_Login.ShowModal;
// закрывыю логотип
F_Logo.Hide;
F_Logo.Free;
if loginStat= true then
Application.Run
else
Application.Terminate;
end.
Код: Выделить всё
Unit Login
procedure TF_Login.BitBtn_okClick(Sender: TObject);
var UserLogin, pass: string;
begin
F_Main.IBQ_User.Close;
F_Main.IBQ_User.SQL.Clear;
F_Main.IBQ_User.SQL.Add('Select User_Login, User_Pass FROM TBUSER WHERE User_Login ="'+Ed_Login.Text+'"');
F_Main.IBQ_User.Open;
UserLogin:=F_Main.IBQ_User.fieldByName('User_Login').AsString;
pass:=F_Main.IBQ_User.FieldByName('User_pass').AsString;
if (Ed_Login.Text=UserLogin) and (Ed_Pass.Text=pass) then loginStat:=true
else
begin
Ed_Pass.Text:='';
Ed_Pass.SelectAll;
loginStat:=false;
end;
end;
end.
прога вылетает с ошибкой
Добавлено: 18 май 2006, 10:01
vunder
А что за ошибка?
Вообще
Код: Выделить всё
Application.CreateForm(TF_Login, F_Login);
F_Login.ShowModal;
неправильно. Во-первых, убеди TF_Login из AutoCreate Forms. Создавай ее так же, как и окно логотипа. Должно сработать.
Добавлено: 18 май 2006, 11:24
Naeel Maqsudov
Ошибка понятно какая - нарушение общей защиты при обращении к памяти по адресу 0.
Т.к. делается F_Main.IBQ_User.Close; в то время, когда F_Main равна nil.
Есть КУЧА способов решить эту задачу.
Один из наиболее корректных с точки зрения VCL это оставить все формы в автозагрузке, но у Main выставить Visible=false (в desing-time) и сделать следующее:
Код: Выделить всё
begin
Application.Initialize;
Application.ShowMainForm:=false;
Application.CreateForm(TF_Main, F_Main);
Application.CreateForm(TF_Login, F_Login);
if LoginSuccess then begin
Application.ShowMainForm:=false;
Application.Run
end;
end.
Функцию LoginSuccess написать "по вкусу" в модуле Login.
Начать ее можно с заполне ния полей (например вставить имя пользователя, который логинился последний раз),
затем сделать F_Login.ShowModal и проверить пароль.
Если пароль правильный функция должна вернуть True.
Есть с десяток способов сделать то же самое.
Добавлено: 18 май 2006, 13:23
vunder
Интересно, как F_Main м.б. равен nil, когда он уже инициализирован Application.CreateForm(TF_Main, F_Main).
Добавлено: 19 май 2006, 13:26
Naeel Maqsudov
Да, точно уже инициализирован.... Извиняюсь. Неправильно прочитал исходник.
Однако, какая ошибка вылетает и в каком месте?
Как осуществляется возврат из ShowModal?
Если ошибку я угадал, то возможно, вы где-то разрушаете форму при закрытии. И по возвращении из ShowModal вызывае Hide и Free для уже несуществующего объекта.
А loginStat - это глобальная переменная что ли?
Хм.... Да-а-а. Так не делается!
Если форма была открыта по ShowModal то закрыть ее можно в обработчике события можно так:
Self.ModalResult := mrOk; {или mrCancel.....}
Причем значение, присвоенное в ModalResult будет результатом функции ShowModal!
Т.е. мой пример можно переписать без функции LoginSuccess:
Код: Выделить всё
begin
Application.Initialize;
Application.ShowMainForm:=false;
Application.CreateForm(TF_Main, F_Main);
Application.CreateForm(TF_Login, F_Login);
if TF_Login.ShowModal=mrOk then begin
Application.ShowMainForm:=true;
Application.Run
end;
end.
Добавлено: 20 май 2006, 20:26
Alchazar
а о глобальной переменной можно побольше?
Добавлено: 21 май 2006, 10:11
vunder
Можно, только осторожно.
В данном примере разницы нет. Все хависит от того, как реализуется проект. Если это будут потоки или подключаемые модули, то глобальные переменные для этого не подходят. Нужно все реализовывать через свойства объекта:
Код: Выделить всё
...
type
...
tMyObj = class (TComponent)
private
fField: String;
procedure SetField (const Value: String);
...
published
property Field: String read fField write SetField;
...
end;
...
procedure tMyObj.SetField (const Value: String);
begin
if Value<>fField then
begin
fField := Value;
...
end;
end;
Код: Выделить всё
var
obj: tMyObj;
...
obj.Field := 'abc';
...
Добавлено: 22 май 2006, 10:35
Alchazar
Вот, разобрался
Спасибо за помощь
Форма - Логин
Код: Выделить всё
F_Main.IBQ_User.Close;
F_Main.IBQ_User.SQL.Clear;
F_Main.IBQ_User.SQL.Add('Select User_Login, User_Pass FROM TBUSER WHERE User_Login ="'+Ed_Login.Text+'"');
F_Main.IBQ_User.Open;
UserLogin:=F_Main.IBQ_User.fieldByName('User_Login').AsString;
pass:=F_Main.IBQ_User.FieldByName('User_pass').AsString;
if (Ed_Login.Text=UserLogin) and (Ed_Pass.Text=pass) then ModalResult:=mrOk
else
begin
MessageDlg('Имя пользователя и/или пароль неверны!'+#10#13+'', mtError, [mbok], 0);
ModalResult:=mrNone;
Ed_Pass.Text:='';
Ed_Pass.SelectAll;
end;
end;
Главная форма
Код: Выделить всё
procedure TF_Main.FormShow(Sender: TObject);
var rez: TModalResult;
begin
rez:=F_Login.ShowModal;
if rez = mrOk then F_Main.Visible:=true;
if rez = mrCancel then Application.Terminate;
end;
Вроде всё работает хорошо

Добавлено: 22 май 2006, 18:07
Игорь Акопян
мне кажется, что приложение не закроется, если пользователь наврёт пароль

проще разрешить только одно действие:
Код: Выделить всё
procedure TF_Main.FormShow(Sender: TObject);
begin
if F_Login.ShowModal = mrOK then
F_Main.Visible:=true
else
Application.Terminate;
end;
Вы, естесственно, знаете, что хранить пароль в базе в открытом виде можно только если вы хотите исключить случайный набор неверного пароля пользователем. Иначе такая секьюрити никуда не годится

Добавлено: 22 май 2006, 18:18
vunder
оно точно не закроется:
Код: Выделить всё
MessageDlg('Имя пользователя и/или пароль неверны!'+#10#13+'', mtError, [mbok], 0);
ModalResult:=mrNone;
, а проверка идет только на mrOk и mrCancel. Надо быть внимательнее!!!