![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Передача значений из проекта в юнит
alex-ran © (2002-06-20 12:19:00)Привет всем!!
Мне необходимо перед запуском главной формы приложения спросить у юзера имя и пароль и ес-но пустить или не пустить его в приложение. Я делаю так:
program Test;
uses
Forms, WinTypes, SysUtils, MainFfm in "MainFfm.pas" {MainForm};
type
TGetUserPass = function (AHandle: THandle; DBAlias, DBNameTable: ShortString): ShortString; StdCall;
EDLLLoadError = class(Exception);
{$R *.RES}
var
LibHandle : THandle;
GetUserPass : TGetUserPass;
ResDll : String;
begin
LibHandle := LoadLibrary("UserDll.Dll");
try
if LibHandle = 0 then
raise EDLLLoadError.Create("Не могу загрузить UserDll");
@GetUserPass := GetProcAddress(LibHandle, "GetUserPass");
if not (@GetUserPass = nil) then
ResDll := GetUserPass (Application.Handle, "RegulUser", "BankUser")
else
RaiseLastWin32Error;
finally
FreeLibrary(LibHandle);
end;
if ResDll="" then Exit;
Application.CreateForm(TMainForm, MainForm);
Application.Run;
end.
Здесь GetUserPass - функция, возвращающая имя пользователя.
Не могу понять, как передать ее значение в MainForm
Помогите, плиз, решить проблему или посоветуйте как правильно ее реализовать?
P.S. Делать все это по Create главной формы все-же не хотелось бы, она и так перегружена.
alex-ran (2002-06-20 16:12:00) [1]>Толик ©
Блин, опять проблема.
На inherited Create(Owner) в конструкторе вываливаюсь с сообщением:
Access violation at address ...... in module "TEST.EXE"
Read of address fffffffff
Из-за чего это?
alex-ran (2002-06-20 14:50:00) [2]>Толик ©
Преогромное спасибо, буду знать.
alex-ran (2002-06-20 14:44:00) [3]> kull ©
Спасибо, работает. И по-моему так проще всего. :)
Спасибо всем кто откликнулся.
И в продолжение, по совету Толикапробовал менять (для начала упростил)
Application.CreateForm(TMainForm, MainForm); на
MainForm := TMainForm.Create(Application). и затем
Application.Run;
Так вот, при этом после отработки формы из ДЛЛ главная (MainForm) не появляется, а приложение завершает работу, что нужно еще сделать?
Толик (2002-06-20 14:31:00) [4]TUser = ...; //TUser - некий свой тип (либо строка, либо структура, да хоть класс - не важно), если это просто строка, тогда этого можно этого и не писать, а везде вместо TUser подставлять string
TMainForm = class(TForm)
...
private
FUser: TUser;
public
constructor Create(Owner: TComponent; User: TUser);
reintroduce; overload;
end;
constructor Create(Owner: TComponent; User: TUser);
begin
FUser := User; //в OnCreate проблем не будет!
inherited Create(Owner);
end;
Теперь следует понять, что значит главная форма приложения. Это та форма, которая идёт первой в списке создаваемых форм через CreateForm. Но использовать CreateForm нельзя, т.к. CreateForm передаёт в конструктор только один параметр - SELF. А нам необходимо передать ещё и TUser. Поэтому поступаем так:
{dpr-файл}
begin
Application.Initialize();
MainForm := TMainForm.Create(Application, GetUser()); // здесь GetUser - некая ф-я, возвращающая переменную TUser (все вызовы dll находятся внутри неё)
//А вот теперь указываем приложению, что MainForm - главная форма
TForm((@Application.MainForm)^) := MainForm;
Application.Run();
end;
вот собственно и всё, только следует не забывать, что GetUser() выделяет память под TUser, но не освобождает её. Эту память надо освобождать в деструкторе TMainForm.
kull (2002-06-20 14:27:00) [5]
> Снова не понял. Разве можно присваивать свойству объекта
> значение до создания экземпляра объекта?
MainFrm.UserName здесь MainFrm - это не объект, а имя юнита, просто уточняю в каком файле находится переменная UserName.
Skier (2002-06-20 14:05:00) [6]> alex-ran
В DLL склеиваешь MyRes в одну строку.
Проще всего так
var
ii : Integer;
AStrList : TStringList;
AStrToSend : String;
MyRes : TMyRes;
begin
....
AStrList := TStringList.Create;
try
for ii := 1 to 4 do AStrList.Add(MyRes[1]);
AStrToSend := AStrList.CommaText;
finally
AStrList.Free;
end; //try
//Отсылаешь AStrToSend
....
end;
В "принимающей" программе получаешь строку
иделаешь с ней :
var
AReceivedStr : String; //строка полученная из DLL
AStrList : TStringList;
MyRes : TMyRes;
ii : Integer;
begin
.....
AStrList := TStringList.Create;
try
AStrList.CommaText := AReceivedStr;
for ii := 0 to AStrList.Count - 1 do
MyRes[ii + 1] := AStrList[ii];
finally
AStrList.Free;
end; //try
.....
end;
alex-ran (2002-06-20 13:52:00) [7]> kull ©
Снова не понял. Разве можно присваивать свойству объекта значение до создания экземпляра объекта?
> Толик ©
Нельзя ли в примере поподробнее (как объявить и т.д.), я еще не силен в переопределении конструкторов
Skier (2002-06-20 13:37:00) [8]> alex-ran
TStringList умеет строки делить.
Через св-ва Text и CommaText
alex-ran (2002-06-20 13:35:00) [9]> Skier ©
К сожалению нет, я просто не стал в форуме усложнять и рисовать реальную задачу, теперь вижу что зря.
Моя функция из ДЛЛ-ки возвращает не ShortString a:
TMyRes : Array [1..4] of ShortString;
Можно конечно слить все элементы массива одну строку и ее передать, но а как потом разделить?
kull (2002-06-20 13:29:00) [10]Файл с формой:
.....
type
TMainForm = .....
...
...
end;
var
UserName: string; //вот переменная с юзером
implementation
......
Файл проекта:
...
MainFrm.UserName := ResDll; //вот передача юзера
Application.CreateForm(TMainForm, MainForm);
...
Толик (2002-06-20 13:25:00) [11]А в конструктор MainForm не пробовали значения передавать? Помогает... Написать в классе TMainForm свой конструктор, в который и передавать login user"а:
constructor TMainForm(Owner: TComponent, User: string);
begin
FUser := User;
// вот теперь в OnCreate будет виден user, т.к. OnCreate вызывается в конструкторе родителя
inherited Create(Owner);
end;
только MainForm придётся создавать не через Application.CreateForm, а MainForm := TMainForm.Create(Application, User);
alex-ran (2002-06-20 13:18:00) [12]> kull ©
Не понял, ведь присвонение MainForm.UserName := ResDll;
происходит после отработки OnCreate главной формы.
Или я чего-то недопонимаю?
Skier (2002-06-20 13:14:00) [13]> alex-ran
Может быть так ?
Application.Tag := Integer(PChar(ResDll))
Application.CreateForm(TMainForm, MainForm);
TMainForm.FormCreate(Sender: TObject);
var
AUserPass : String;
begin
...........
AUserPass := PChar(Application.Tag);
...........
Application.Tag := 0;
...........
end;
kull (2002-06-20 13:09:00) [14]Ну можно в юните с формой завести глобальную переменную
var UserName: string;
А потом ее проверять на OnCreate.
alex-ran (2002-06-20 13:05:00) [15]Спасибо за совет.
Но только возникла новая проблема :(
Мне это свойство необходимо для обработки в событии onCreate главной формы. А последовательность событий такова:
Application.CreateForm(TMainForm, MainForm); -
TMainForm.FormCreate(Sender: TObject); -
и только затем MainForm.UserName := ResDll;
так что немного не подходит, может есть еще способ?
> kull
> kull ©
kull (2002-06-20 12:30:00) [16]Application.CreateForm(TMainForm, MainForm);
MainForm.UserName := ResDll;
,где UserName свойство, которое ты сам определяешь.