버전 : Delphi6
DBMS : Oracle
컴포넌트 : ODAC
MDIChild방식으로 데이타모듈을 이용하여 ODAC 컴포넌트의 OraSession컴포넌트를 올려놓고 사용했습니다. 실행파일의 메인메뉴에서 메뉴를 클릭하여 Child폼(폼속성은 MDIChild로 지정)을 호출하는데 호출은 정상적으로 됩니다 그런데 자료를 조회하는 버튼을 여속적으로 10번을 클릭을 하면
Access Violation 에러가 발생합니다. 소스를 보시고 문제가 되는부분을 해결 부탁합니다.
- 메인소스 -
unit Nis_Main;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, Menus, ExtCtrls, DB, DBAccess, Ora, StdCtrls, psapi;
type
TNis_MainW = class(TForm)
MainMenu1: TMainMenu;
N1: TMenuItem;
N2: TMenuItem;
N3: TMenuItem;
procedure FormClose(Sender: TObject; var Action: TCloseAction);
procedure N2Click(Sender: TObject);
procedure FormShow(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
type
TCreateChildForm = procedure (MainApp : TApplication; exe_scr : Tscreen; GP_OraSession: TComponent; GPs_Dat : Array of PChar); stdcall;
var
Nis_MainW: TNis_MainW;
implementation
Uses
Nis_Dm;
{$R *.dfm}
procedure TNis_MainW.FormClose(Sender: TObject; var Action: TCloseAction);
var
i : integer ;
begin
for i:=0 to Screen.FormCount - 1 do
begin
if Screen.Forms[i].Name <> 'Nis_MainW' then
Screen.Forms[i].close ;
end;
Nis_DmW.OraSession1.Disconnect;
Action := caFree;
end;
procedure TNis_MainW.N2Click(Sender: TObject);
var
DllHandle : THandle;
ProcAddr : Pointer;
CreateChildForm : TCreateChildForm;
i : Integer;
Form: TForm;
AControl: TControl;
begin
for i:=0 to Screen.FormCount - 1 do
begin
if Screen.Forms[i].Name = 'wf_Lv1w' then
begin
Screen.Forms[i].BringToFront;
exit;
end;
end;
DllHandle := LoadLibrary(PChar('Lv1.dll'));
if DllHandle > 32 then
begin
ProcAddr := GetProcAddress(DllHandle, 'CreateMDIChildForm');
if ProcAddr <> nil then
begin
CreateChildForm := ProcAddr;
CreateChildForm(Application, Screen, Nis_DmW.OraSession1, ['11','12']);
end;
end;
end;
procedure TNis_MainW.FormShow(Sender: TObject);
begin
Nis_DmW.OraSession1.Connect;
end;
end.
- DLL 소스 -
library Lv1;
uses
SysUtils,
Classes,
Forms,
Ora,
wf_Lv1 in 'wf_Lv1.pas' {wf_Lv1w},
Init in 'Init.pas';
procedure CreateMDIChildForm(MainApp : TApplication; exe_scr : Tscreen; GP_OraSession: TComponent; GPs_Dat : Array of PChar); stdcall;
begin
Application := MainApp;
Screen := Exe_scr;
if wf_Lv1w = nil then
begin
wf_Lv1w := Twf_Lv1w.Create(nil);
wf_Lv1w.Edit1.Text := GPs_Dat[0];
wf_Lv1w.Edit2.Text := GPs_Dat[1];
wf_Lv1w.OraQuery1.Session := TOraSession(GP_OraSession);
wf_Lv1w.Show;
end;
end;
exports
CreateMDIChildForm;
begin
end.
- DLL에 포함된 폼(wf_Lv1.pas) 소스 -
unit wf_Lv1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, dxCntner, dxTL, dxDBCtrl, dxDBGrid, DB, MemDS, DBAccess, Ora,
StdCtrls, dxDBTLCl, dxGrClms;
type
Twf_Lv1w = class(TForm)
Edit1: TEdit;
Edit2: TEdit;
Button1: TButton;
Button2: TButton;
Edit3: TEdit;
Label1: TLabel;
OraDataSource1: TOraDataSource;
OraQuery1: TOraQuery;
dxDBGrid1: TdxDBGrid;
dxDBGrid1Column1: TdxDBGridColumn;
OraQuery1LVY_KEY: TStringField;
procedure Button1Click(Sender: TObject);
procedure FormClose(Sender: TObject; var Action: TCloseAction);
procedure FormShow(Sender: TObject);
procedure dxDBGrid1DblClick(Sender: TObject);
procedure Button2Click(Sender: TObject);
procedure FormDestroy(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
wf_Lv1w: Twf_Lv1w;
implementation
procedure ShowChildForm_Lv2(MainApp : TApplication; exe_scr : Tscreen; GP_OraSession: TComponent; GPs_Dat : Array of PChar); stdcall; external 'Lv2.dll'
{$R *.dfm}
procedure Twf_Lv1w.Button1Click(Sender: TObject);
begin
Label1.Caption := '';
Label1.Refresh;
with OraQuery1 do
try
Close;
Sql.Clear;
Sql.Text := 'SELECT LVY_KEY FROM RISTNLVBOOK';
Label1.Caption := OraQuery1.Session.Username+','+OraQuery1.Session.Password+','+OraQuery1.Session.Server;
Open;
Edit3.Text := IntToStr(OraQuery1.RecordCount);
except
on E : Exception do
begin
Edit3.Text := '0';
Application.MessageBox(Pchar(E.Message+#13#10+OraQuery1.Session.Username+','+OraQuery1.Session.Password+','+OraQuery1.Session.Server),
'확인',MB_OK);
end;
end;
end;
procedure Twf_Lv1w.FormClose(Sender: TObject; var Action: TCloseAction);
begin
Action := caFree;
end;
procedure Twf_Lv1w.FormShow(Sender: TObject);
begin
Left := 0;
Top := 0;
end;
procedure Twf_Lv1w.dxDBGrid1DblClick(Sender: TObject);
begin
ShowChildForm_Lv2(Application, Screen, OraQuery1, [PChar(OraQuery1.FieldByName('LVY_KEY').AsString)]);
end;
procedure Twf_Lv1w.Button2Click(Sender: TObject);
begin
if OraQuery1.Session.Connected then
ShowMessage(OraQuery1.Session.Username+','+OraQuery1.Session.Password+','+OraQuery1.Session.Server)
else
ShowMessage('해제');
end;
procedure Twf_Lv1w.FormDestroy(Sender: TObject);
begin
wf_Lv1w := nil;
end;
end.
- DLL에 포함된 Init.pas 소스-
unit Init;
interface
Uses
Forms;
var
DllApplication : TApplication;
DllScreen : TScreen;
implementation
initialization
DllApplication := Application;
DllScreen := Screen;
finalization
Application := DllApplication;
Screen := DllScreen;
end.
exe와 dll프로젝트를 모두 bpl를 사용하는 방식으로 컴파일을 해야 가능합니다.
물론 배포상의 불편은 감수해야 합니다.