WWW.DISSERS.RU

БЕСПЛАТНАЯ ЭЛЕКТРОННАЯ БИБЛИОТЕКА

   Добро пожаловать!


Pages:     | 1 |   ...   | 6 | 7 || 9 | 10 |   ...   | 14 |

Можно поместить все невизуальные компоненты для работы с БД непо- средственно на форму. В этом случае взаимосвязь компонентов приложения и таблиц БД и используемые при этом свойства компонентов будут иметь вид, как это показано на рис. 53.

Рис. 53. Взаимосвязь компонентов и БД при размещении всех компонентов на форме Но для невизуальных компонентов в Delphi предусмотрен особый тип формы, называемый модулем данных (Data Module). Этот модуль предназна- чен для размещения только невизуальных компонентов, таких как DataSourse и TQuery. Таким образом, компоненты, предназначенные для доступа к дан- ным, размещаются в отдельном контейнере - модуле данных. Существует три типа модуля данных:

-78- Рис. 54. Взаимосвязь компонентов и БД при использовании модуля данных • простой модуль данных;

• удаленный модуль данных;

• Web-Модуль.

В приложениях, работающих в рамках локальной сети, используются простые модули данных, поэтому мы будем иметь дело с простым модулем данных, представленным объектом DataModule. При использовании простого модуля данных взаимосвязь компонентов приложения и БД имеет вид, показанный на рис. 54. Для создания простого модуля данных:

1. Добавьте в программу модуль данных, выбрав пункт меню File/New и щелкнув по кнопке Data Module на странице New. Поместите на страничку Components компоненты TDataSourse, TDataBase, TQuery, TStoredProc (рис.

55). В левой панели при этом появляется дерево, отображающее все связи ме- жду компонентами, а также позволяющее изменять эти связи.

2. Установите для компонента Databasel свойство DatabaseName равным TEACHER. Это приведет к появлению имени БД в соответствующей ветке дерева на левой панели.

Рис. 55. Модуль данных с Рис. 56. Дерево компонентов Рис. 57. Иерархия компонентами доступа к модуля данных компонентов модуля данных данным после редактирования - 79- 3. Дерево поддерживает режим «перетаскивания», то есть вы можете пере- мещать мышкой его элементы, формируя новые связи между ними. Например, вы можете перенес ти мышкой элемент DataSoursel на ветку «Queryl» (рис.

56). Этим вы подключите компонент Queryl к источнику данных DataSoursel.

При этом у компонента DataSoursel устанавливается свойство DataSet = Queryl.

Таким же образом можно перенести ветку Queryl на элемент DataBasel (рис. 57). В результате мы получаем дерево, содержащее объект Session с име- нем Default, который, в свою очередь, содержит БД TEACHER. Доступ к этой БД осуществляется через компоненты Queryl и DataSoursel. При обращении к содержащимся в модуле данных компонентам для них указывается составное имя, в которое, кроме имени компонента, входит также имя модуля данных.

Мы привели стандартную схему создания модуля данных. Но как мы опи- сали выше, наша программа содержит оболочку, которая по требованию поль- зователя вызывает DLL-библиотеки, с размещенными на них формами. Обо- лочка приложения, содержащая модуль данных, создает только соединение с БД, поэтому в модуле данных мы оставим только компонент Database1. А соб- ственно источник данных и прочие компоненты типа Query и TStoredProc вынесем в DLL. В результате модуль данных будет выглядеть так:

unit uDM;

interfасе uses Windows, Messages, SysUtils,. Classes, Graphics, Controls, Forms, Dialogs, DBTables, DB, BDE;

type TfDM = class(TDataModule) Databasel: TDatabase;

private { Private declarations } public { Public declarations } function GetSessionHandle: HDBIDB;

end;

var fDM: TfDM;

implementation {$R *.dfm) function TfDM.GetSessionHandle: HDBIDB;

begin result:=Session.Databases[Session.DatabaseCount-1].Handle;

end;

end.

Обратите внимание, что для получения описателя (дескриптора) БД в мо- дуле UDM создана специальная функция - метод GetSessionHandle. Выражение Session.Databases[Session.DatabaseCount-1] является указателем на последнюю БД в массиве (в нашем случае она является и единственной).

- 80- 3.3. СВЯЗЬ С БАЗОЙ ДАННЫХ Доступ к информации, хранимой в БД общего пользования, необходимо ограничивать или санкционировать. Для большинства SQL-серверов защита реализуется на уровне имени пользователя и пароля. Подключением пользователя к БД управляет компонент типа TDatabase. У него имеется свойство LoginPromt, определяющее необходимость вывода входного диалога. Если LoginPromt =f alse, то пользователь сам организует ввод и передачу имени пользователя и пароля в массив параметров Params.

Поэтому в первую очередь необходимо создать форму входного диалога.

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

Для передачи этих данных из DLL в модуль главного приложения используется следующий прием:

• в основном приложении создается некоторая структура, содержащая пере- менные для передачи данных;

• указатель на эту структуру передается в DLL в качестве параметра проце- дуры или функции;

• вызываемая процедура из DLL в процессе работы изменяет переменные, входящие в структуру, обращаясь к ней через переданный указатель.

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

И, наконец, последний шаг в главном модуле: организуется вызов DLL и передача данных, сформированных в ходе работы DLL, в главный модуль.

3.3.1. СОЗДАНИЕ ПРОЕКТА DLL_LOGIN 1. Создайте в группе проектов COURSE новый проект. Для этого в Менеджере проектов в контекстном меню выберите пункт «Add New Project», а в появившемся диалоге на странице New - значок DLL.

2. Сохраните проект Projectl под именем login в каталоге dll_login, ко- торый следует создать в основном каталоге приложения COURSE.

3. Создайте подкаталоги COURSE\DCU и COURSE\EXE. Выберите пункт меню Project\0ptions и в появившемся окне Project Options for Login.dll на странице Directories\Conditionals установите параметры Unit Output Di- rectory = COURSE\DCU, Output Directory = COURSE\EXE.

4. Модуль входного диалога является частью проекта, однако, присутствует в нем только в виде описания типа. Для того чтобы им воспользоваться, нам необходимо самим создать экземпляр этого диалога путем вызова конструктора:

fLogin := TfLogin.Create(Application);

-81- а после использования — уничтожить при помощи деструктора:

fLogin.Free;

Лучше всего это сделать, поместив все эти вызовы в одну функцию, и сделав ее доступной внешним приложениям, т. е. экспортировать. Назовем эту функцию. Добавьте в файл проекта раздел exports:

library login;

uses SysUtils, Classes, uLogin in 'uLogin.pas' {fLogin};

{$R *.RES} exports ShowLoginDialog name 'SHOWLOGINDIALOG';

begin end.

Саму функцию ShowLoginDialog определим в модуле uLogin, только что подключенном нами к проекту.

5. Проект login.dll должен компилироваться раньше, чем основной проект, поэтому в группе проектов переместите его на самый верх.

3.3.2. СОЗДАНИЕ ПРОГРАММНОГО КЛАССА При описании общей схемы диалога в разделе 3.3.5 был описан процесс передачи данных из DLL в основное приложение с помощью специальной структуры, содержащей переменные для хранения передаваемых данных.

Реализуем эту структуру в виде класса в отдельном модуле.

1. Добавьте в проект login.dll новый модуль, выбрав пункт меню FIе\New\Unit. Delphi добавит к проекту новый модуль, создав его с именем по умолчанию Unitl. Сохраните его под именем uLoginData в новом каталоге COURSE\common.

2. Добавьте в модуль раздел type и наберите следующее определение класса:

type TLoginData = class modalResult : TModalResult;

user id, password : shortstring;

constructor create;

end;

С помощью конструктора свойствам класса присваиваются начальные зна- чения. Чтобы закончить создание конструктора, поставьте курсор на любую строку определения класса и нажмите SHIFT+CTRL+C. Delphi автоматически создаст заготовки всех методов, входящих в класс; в данном случае - это заго товка конструктора Create.

-82- constructor TLoginData.Create begin inherited;

ModalResult: = 0;

user_id: = '';

password: = '';

end;

Кроме того, добавьте в раздел uses модуль Controls, чтобы использовать стандартный тип TModalResult, заданный в этом модуле.

В окончательном варианте uLoginData должен выглядеть следующим обра- зом:

unit uLoginData;

interface uses Controls type TLoginData = class modalResult : TModalResult;

user_id, password : shortstring;

constructor create;

end;

implementation {TLoginData} constructor TLoginData.Create begin inherited;

ModalResult: = 0;

user_id: = ' ';

password: = ' ';

end;

end;

Рис. 58. Форма входного диалога -83- 3.3.3. СОЗДАНИЕ ФОРМЫ ДИАЛОГА Теперь после проведения предварительной подготовки можно приступить к разработке формы входного диалога, которая будет реализована в отдельном модуле.

1. Добавьте в проект новую форму (File\New\Form). Отредактируйте ее и переименуйте компоненты, как показано на рис. 58. Сохраните модуль в ката- логе проекта под именем uLogin.

2. Установите значения свойств компонентов в соответствии с таблицей:

КОМПОНЕНТ СВОЙСТВО ЗНАЧЕНИЕ ! fLogin biSystemMenu false biMinimize false biMaximize false BorderStyle bsDialog Caption Вход в систему Position poScreenCenter Имя Label Пароль Caption ebUserName Text ebPassword Text _ I * PasswordChar btnCancel Caption Отмена ModalResult mrCancel btnOK Caption ок mrOK ModalResult Отредактируйте модуль uLogin, как показано в листинге:

unit uLogin;

interface uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, ExtCtrls, uLoginData;

type TfLogin = class(TForm) Labell: TLabel;

Label2: TLabel;

ebUserName: TEdit;

ebPassword: TEdit;

btnCancel: TButton;

btnOk: TButton;

procedure FormShow(Sender: Tobject);

procedure btnOkClick(Sender: Tobject);

procedure btnCancelClick(Sender: Tobject);

private { Private declarations } - 84- public { Public declarations } LoginData: TLoginData;

end;

procedure ShowLoginDialog(Handle: THandle; p: pointer);

var fLogin: TfLogin;

implementation {$R *.DFM} procedure ShowLoginDialog(Handle: THandle; p: pointer);

begin Application.Handle := Handle;

fLogin := TfLogin.Create(Application);

fLogin.LoginData:=TLoginData(p);

fLogin.ShowModal;

fLogin.Free;

end;

procedure TfLogin.FormShow(Sender: TObject);

begin ebPassword.Text:='';

end;

procedure TfLogin.btnOkClick(Sender: Tobject);

begin LoginData.user_id:=ebUserName.Text;

LoginData.password:=ebPassword.Text;

LoginData.modalResult:=mrOK;

end;

procedure TfLogin.btnCancelClick(Sender: Tobject);

begin LoginData.ModalResult:=mrCancel;

end;

end.

Рассмотрим процедуру ShowLoginDialog. В качестве второго параметра этой процедуры использован указатель, на класс TLoginData. Такой же указа- тель добавлен и в раздел public определения самого входного диалога:

public {Private declaration} LoginData: TLoginData;

Полученный указатель присваивает члену класса LoginData с использова- нием преобразования типа fLogin.LoginData: = TLoginData(p);

-85- Этот член класса введен для удобства обращения к переданному классу из других процедур диалога, а именно из обработчиков нажатия кнопок «ок» и «ОТМЕНА».

При нажатии «ок» происходит передача введенных пользователем пароля и имени в класс TLoginData:

LoginData.user_id: = ebUserName.Text;

LoginData.password: = ebPassword.Text;

LoginData.ModalResult: = mrOk;

При нажатии кнопки «ОТМЕНА» передается значение modalResult, инфор- мирующее о том, что нажата кнопка отмены, LoginData.ModalResult:=mrCancel;

Для удаления прежнего введенного значения пароля при повторном вызове входного диалога в модуль введена процедура Formshow.

Скомпилируйте проект login.dll и после этого в каталоге COURSE появит- ся файл login.dll.

3.3.4. ОРГАНИЗАЦИЯ ВЫЗОВА ВХОДНОГО ДИАЛОГА В ГЛАВНОМ МОДУЛЕ Теперь займемся вызовом входного диалога из основного приложения. Так как для передачи данных между DLL и основной программой мы воспользова- лись классом TLoginData, то необходимо обеспечить видимость этого класса и из основной программы.

30. С этой целью подключите к проекту main находящийся в подкаталоге Common файл uLoginData.pas. При этом дерево группы примет вид, приведен- ный на рис. 59.

Рис. 59. Дерево проектной группы - 86- 2. Отредактируйте процедуру, отвечающую за подключение к БД так, чтобы она выглядела следующим образом:

unit uMain;

interface uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, Menus, ComCtrls;

type TfMain = class(TForm) MainMenul: TMainMenu;

MainMenul: TMainMenu;

N1 TMenuItem;

N2 TMenuItem;

N3 TMenuItem;

N4 TMenuItem;

N5 TMenuItem;

N6 TMenuItem;

N7 TMenuItem;

N8 TMenuItem;

N9 TMenuItem;

N10: TMenuItem;

N11: TMenuItem;

N12: TMenuItem;

N13: TMenuItem;

N14: TMenuItem;

StatusBarl: TStatusBar;

procedure N2Click(Sender: TObject);

procedure N3Click(Sender: TObject);

procedure NSClick(Sender: TObject);

private { Private declarations } public { Public declarations } end;

var fMain: TfMain;

implementation uses uDM;

($R *.dfm} procedure TfMain.N3Click(Sender: TObject);

type TShowLoginDialog = procedure(Handle: THandle; p: pointer);

var hLib: Thandle;

ShowLog in Dialog: TShowLo.ginDialog;

LoginData: TLoginData;

begin hLib := LoadLibrary('LOGIN.DLL');

if hLib < 32 then - 87- begin ShowMessage('Отсутствует библиотека LOGIN.DLL');

Exit end;

LoginData := TLoginData.Create;

ShowLoginDialog := TShowLoginDialog(GetProcAddress(hLib, 'SHOWLOGINDIALOG'));

ShowLoginDialog(Application.Handle, LoginData);

FreeLibrary(hLib);

if LoginData.ModalResult=mrOK then begin try with fDM.Databasel do begin if Connected then Close;

//LoginPromt:=false;

Params.Values['PASSWORD'] := Trim(LoginData.password) ;

Params.Values['USER NAME'] := Trim(LoginData.user_id);

Open;

end;

StatusBarl.SimpleText := 'Соединение выполнено.';

except StatusBarl.SimpleText := 'Ошибка подключения к БД.';

end;

end;

end;

procedure TfMain.N4Click(Sender: TObject);

begin with fDM.Databasel do begin if Connected then Close;

end;

StatusBarl.SimpleText:='Отключение выполнено.' end;

procedure TfMain.N5Click(Sender: TObject);

begin N4Click(Sender);

Application.Terminate;

end;

end.

В приведенной процедуре производятся все манипуляции с DLL: загрузка ее в память, вызов экспортируемой процедуры и вход в базу с использованием введенных имени и пароля, поэтому рассмотрим ее подробнее.

Загрузка DLL в память. Для загрузки DLL в память используется функция LoadLibrary:

hLib: = LoadLibrary('LOGIN.DLL' );

Эта функция возвращает описатель (хэндл) загруженной библиотеки.

- 88- Причем если DLL уже загружена в память, то будет возвращен описатель загру- женной библиотеки - повторно она загружаться не будет. В этом проявляется основное достоинство использования DLL: несмотря на то, что DLL используется несколькими программами, она загружается в память только один раз.

Для проверки успешнос ти загрузки, используется следующий фрагмент программы:

if hLib<32 then begin ShowMessage ( ' Отсутствует Login.dll');

Exit;

end;

Здесь проверяется, не является ли возвращаемое функцией LoadLibrary значение < 32.

Определение адреса экспортируемой процедуры. После успешной загруз- ки DLL необходимо найти адрес экспортируемой процедуры. Для этого исполь- зуется функция GetProcAddress:

ShowLoginDilog:= TShowLoginDialog(GetProcAddress(hLib,'SHOWLOGINDIALOG'));

Найденный адрес процедуры присваивается специально объявленной пе- ременной, имеющей процедурный тип, объявленный здесь же в разделе type:

type TShowLoginDialog = procedure(Handle: Thandle; p: pointer);

var ShowLoginDialog: TShowLoginDialog;

Pages:     | 1 |   ...   | 6 | 7 || 9 | 10 |   ...   | 14 |






















© 2011 www.dissers.ru - «Бесплатная электронная библиотека»

Материалы этого сайта размещены для ознакомления, все права принадлежат их авторам.
Если Вы не согласны с тем, что Ваш материал размещён на этом сайте, пожалуйста, напишите нам, мы в течении 1-2 рабочих дней удалим его.