问题:当调用DLL成功后显示的是默认的输入窗体(上面有个打印钮),在单击"打印"时报错,如何调出打印预览的窗体;
一个程序有共有两个窗体,一个是输入用的(sgdgd_tj.pas),一个是打印预览用的(SGDGD_TJDY.pas).两个窗体的FORMSTYLE都是FSNORMAL,确定正常后做成了DLL.代码如下:library dll_1;
uses
SysUtils,
ActiveX,
windows,
Classes,
sgdgd_tj in 'sgdgd_tj.pas' {Form1},
SGDGD_TJDY in 'SGDGD_TJDY.pas' {Form12};
procedure _DllProc(Reason: Integer);
begin if Reason = DLL_PROCESS_ATTACH then
CoInitialize(nil)
else if Reason = DLL_PROCESS_DETACH then CoUninitialize;
end;{$R *.res}
exports
myshowform1,
mycloseform1;
begin
DLLProc := @_DllProc;
_DllProc(DLL_PROCESS_ATTACH);end.调用的主程序如下:unit dll_tes;interfaceuses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;type
Ttest = class(TForm)
Button1: TButton;
Button2: TButton;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
procedure FormClose(Sender: TObject; var Action: TCloseAction);
private
{ Private declarations }
public
{ Public declarations }
end;var
test: Ttest;
formref:longint;
function myshowform1(ahandle:thandle):longint;stdcall;
procedure mycloseform1(aformref:longint);stdcall;implementation
function myshowform1;external 'dll_1.dll';
procedure mycloseform1;external 'dll_1.dll';{$R *.dfm}procedure Ttest.Button1Click(Sender: TObject);
begin
formref:=myshowform1(application.handle);
end;procedure Ttest.Button2Click(Sender: TObject);
begin
mycloseform1(formref);
test.Close;end;procedure Ttest.FormClose(Sender: TObject; var Action: TCloseAction);
begin
mycloseform1(formref);
end;end.
一个程序有共有两个窗体,一个是输入用的(sgdgd_tj.pas),一个是打印预览用的(SGDGD_TJDY.pas).两个窗体的FORMSTYLE都是FSNORMAL,确定正常后做成了DLL.代码如下:library dll_1;
uses
SysUtils,
ActiveX,
windows,
Classes,
sgdgd_tj in 'sgdgd_tj.pas' {Form1},
SGDGD_TJDY in 'SGDGD_TJDY.pas' {Form12};
procedure _DllProc(Reason: Integer);
begin if Reason = DLL_PROCESS_ATTACH then
CoInitialize(nil)
else if Reason = DLL_PROCESS_DETACH then CoUninitialize;
end;{$R *.res}
exports
myshowform1,
mycloseform1;
begin
DLLProc := @_DllProc;
_DllProc(DLL_PROCESS_ATTACH);end.调用的主程序如下:unit dll_tes;interfaceuses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;type
Ttest = class(TForm)
Button1: TButton;
Button2: TButton;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
procedure FormClose(Sender: TObject; var Action: TCloseAction);
private
{ Private declarations }
public
{ Public declarations }
end;var
test: Ttest;
formref:longint;
function myshowform1(ahandle:thandle):longint;stdcall;
procedure mycloseform1(aformref:longint);stdcall;implementation
function myshowform1;external 'dll_1.dll';
procedure mycloseform1;external 'dll_1.dll';{$R *.dfm}procedure Ttest.Button1Click(Sender: TObject);
begin
formref:=myshowform1(application.handle);
end;procedure Ttest.Button2Click(Sender: TObject);
begin
mycloseform1(formref);
test.Close;end;procedure Ttest.FormClose(Sender: TObject; var Action: TCloseAction);
begin
mycloseform1(formref);
end;end.
解决方案 »
- Grid 查询时显示 表中没有的字段
- 本人想从麦克风中采集音频数据,读到内存中,并从网络中发出;不知道用DSPACK组件如何实现?
- D7是最好的開發環境,不同觀點的接分點評
- ComboBox中的每一项如何使用不同的背景颜色
- 为什么最后一个字符串不能插入到表中?
- DELPHI处理批处理文件的问题。
- Save me!!!!!!!谁能够用ADO把下面文本完整读出来我给他二百分
- 请教各位大侠程序中如何判断系统有无安装tts
- @@@@@@@@@@@@@@@to zswangII(伴水II)(需要充充电)(副本) @@@@@@@@@@@@@@@
- 有关VFP数据库
- 请教关于用dbgird做数据录入时,如果检测某个字段不正确,怎样让焦点始终定位在这条记录上?具体如下:
- Delphi7中多个编辑框数所累加可否用循环来做?
记得要从主程序中把句柄传入到DLL中.这样好多东东都不会出错了.
用delphi制作dll小结一 Dll的制作一般分为以下几步:
1 在一个DLL工程里写一个过程或函数
2 写一个Exports关键字,在其下写过程的名称。不用写参数和调用后缀。
二 参数传递
1 参数类型最好与window C++的参数类型一致。不要用DELPHI的数据类型。
2 最好有返回值[即使是一个过程],来报出调用成功或失败,或状态。成功或失败的返回值最好为1[成功]或0[失败].一句话,与windows c++兼容。
3 用stdcall声明后缀。
4 最好大小写敏感。
5 无须用far调用后缀,那只是为了与windows 16位程序兼容。三 DLL的初始化和退出清理[如果需要初始化和退出清理]
1 DLLProc[SysUtils单元的一个Pointer]是DLL的入口。在此你可用你的函数替换了它的入口。但你的函数必须符合以下要求[其实就是一个回调函数]。如下:
procedure DllEnterPoint(dwReason: DWORD);far;stdcall;
dwReason参数有四种类型:
DLL_PROCESS_ATTACH:进程进入时
DLL_PROCESS_DETACH进程退出时
DLL_THREAD_ATTACH 线程进入时
DLL_THREAD_DETACH 线程退出时
在初始化部分写:
DLLProc := @DLLEnterPoint;
DllEnterPoint(DLL_PROCESS_ATTACH);
2 如Form上有TdcomConnection组件,就Uses Activex,在初始化时写一句CoInitialize (nil);
3 在退出时一定保证DcomConnection.Connected := False,并且数据集已关闭。否则报地址错。四 全局变量的使用
在widnows 32位程序中,两个应用程序的地址空间是相互没有联系的。虽然DLL在内存中是一份,但变量是在各进程的地址空间中,因此你不能借助dll的全局变量来达到两个应用程序间的数据传递,除非你用内存映像文件。五 调用静态载入
1 客户端函数声名:
1)大小写敏感。
2)与DLL中的声明一样。
如: showform(form:Tform);Far;external'yproject_dll.dll';
3)调用时传过去的参数类型最好也与windows c++一样。
4)调用时DLL必须在windows搜索路径中,顺序是:当前目录;Path路径;windows;widows\system;windows\ssystem32;六 调用动态载入
1 建立一种过程类型[如果你对过程类型的变量只是一个指针的本质清楚的话,你就知道是怎么回事了]。如:
type
mypointer=procedure(form:Tform);Far;external;
var
Hinst:Thandle;
showform:mypointer;
begin
Hinst:=loadlibrary('yproject_dll');//Load一个Dll,按文件名找。
showform:=getprocaddress(Hinst,'showform');//按函数名找,大小写敏感。如果你知道自动化对象的本质就清楚了。
showform(application.mainform);//找到函数入口指针就调用。
Freelibrary(Hinst);
end;七 在DLL建立一个TForM
1 把你的Form Uses到Dll中,你的Form用到的关联的单元也要Uses进来[这是最麻烦的一点,因为你的Form或许Uses了许多特殊的单元或函数]
2 传递一个Application参数,用它建立Form.八 在DLL中建立一个TMDIChildForM
1 Dll中的MDIForm.FormStyle不用为fmMDIChild.
2 在CreateForm后写以下两句:
function ShowForm(mainForm:TForm):integer;stdcall
var
Form1: TForm1;
ptr:PLongInt;
begin
ptr:=@(Application.MainForm);//先把dll的MainForm句柄保存起来,也无须释放,只不过是替换一下
ptr^:=LongInt(mainForm);//用主调程序的mainForm替换DLL的MainForm。MainForm是特殊的WINDOW,它专门管理Application中的Forms资源.
//为什么不直接Application.MainForm := mainForm,因为Application.MainForm是只读属性
Form1:=TForm1.Create(mainForm);//用参数建立
end;
备注:参数是主调程序的Application.MainForm九 示例:
DLL源代码:
library Project2;uses
SysUtils,
Classes,
Dialogs,
Forms,
Unit2 in 'Unit2.pas' {Form2};{$R *.RES}
var
ccc: Pchar;procedure OpenForm(mainForm:TForm);stdcall;
var
Form1: TForm1;
ptr:PLongInt;
begin
ptr:=@(Application.MainForm);
ptr^:=LongInt(mainForm);
Form1:=TForm1.Create(mainForm);
end;procedure InputCCC(Text: Pchar);stdcall;
begin
ccc := Text;
end;procedure ShowCCC;stdcall;
begin
ShowMessage(String(ccc));
end;exports
OpenForm;
InputCCC,
ShowCCC;
begin
end.调用方源代码:
unit Unit1;interfaceuses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls;type
TForm1 = class(TForm)
Button1: TButton;
Button2: TButton;
Edit1: TEdit;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;var
Form1: TForm1;implementation{$R *.DFM}
procedure OpenForm(mainForm:TForm);stdcall;External'project2.dll';
procedure ShowCCC;stdcall;External'project2.dll';
procedure InputCCC(Text: Pchar);stdcall;External'project2.dll';procedure TForm1.Button1Click(Sender: TObject);
var
Text: Pchar;
begin
Text := Pchar(Edit1.Text);
// OpenForm(Application.MainForm);//为了调MDICHILD
InputCCC(Text);//为了实验DLL中的全局变量是否在各个应用程序间共享
end;procedure TForm1.Button2Click(Sender: TObject);
begin
ShowCCC;//这里表明WINDOWS 32位应用程序DLL中的全局变量也是在应用程序地址空间中,16位应用程序或许不同,没有做实验。end;
引用单元中直接使用呀.
在这里可以找找http://japee.com.cn/jew/bbs.aspx
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, Menus, ExtCtrls, utchild;
const
WM_CALLBACK = WM_USER + 100;
type
TShowForm = function (App: TApplication; CallProc: Pointer; FormID: Integer; ParentForm: TForm; ParentContralHandle: HWND): Tform; stdcall;
TActiveForm = function : LongInt; stdcall;
TCloseForm = function : LongInt; stdcall;
TfrmMain = class(TForm)
MainMenu1: TMainMenu;
Open1: TMenuItem;
mmFileOpen: TMenuItem;
mmFileClose: TMenuItem;
Panel1: TPanel;
mmFileOpenFrm: TMenuItem;
mmFileCloseFrm: TMenuItem;
Report1: TMenuItem;
N1111: TMenuItem;
Panel2: TPanel;
Change1: TMenuItem;
procedure mmFileOpenClick(Sender: TObject);
procedure mmFileCloseClick(Sender: TObject);
procedure FormClose(Sender: TObject; var Action: TCloseAction);
procedure mmFileOpenFrmClick(Sender: TObject);
procedure N1111Click(Sender: TObject);
procedure Change1Click(Sender: TObject);
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
FLibHandle : THandle;
FShowForm : TShowForm;
FActiveForm : TActiveForm;
FCloseForm : TCloseForm;
List : TList;
//FFrm: TForm1;
procedure CallPostMessage(ID:Integer);
procedure BackCallMessage(var Msg: TMessage); message WM_CALLBACK; procedure WMHotKey(var Msg: TWMHotKey); message WM_HOTKEY;
function GetSysFocus: Integer;
public
{ Public declarations }
procedure WMACTIVATEAPP(var Msg: TMessage); message WM_ACTIVATEAPP;
end;var
frmMain: TfrmMain;
FFrm: TForm1;
implementation
const id_SnapShot = 115; //定义热键标识符{$R *.dfm}
procedure TfrmMain.WMHotKey(var Msg: TWMHotKey);
var
H: THandle;
begin
if Msg.HotKey = id_SnapShot then
begin
H := GetSysFocus;
while IsWindow(H) and (H <> frmMain.Handle) do
begin
SendMessage(H,WM_NEXTDLGCTL,0,0);
H := GetParent(H);
end;
end;
end; function TfrmMain.GetSysFocus: Integer;
var
hOtherWin,OtherThreadID,hFocusWin:integer;
begin
hOtherWin:=GetForegroundWindow;
OtherThreadID:=GetWindowThreadProcessID(hOtherWin,nil);
if AttachThreadInput(GetcurrentThreadID,OtherThreadID,True) then
begin
hFocusWin:=GetFocus;
result:=GetFocus;
if HFocusWin<>0 then
try
//
finally
AttachThreadInput(GetcurrentThreadID,OtherThreadID,False);
end;
end
else result:=GetFocus;
end; procedure TfrmMain.WMACTIVATEAPP(var Msg: TMessage);
begin
if Boolean(Msg.WParam) then
RegisterHotKey(frmMain.Handle, id_SnapShot, 0, VK_TAB)
else
UnRegisterHotKey(frmMain.Handle, id_SnapShot);
end; procedure CallBackProc(ID:Integer); stdcall;
begin
frmMain.CallPostMessage(ID);
end;procedure TfrmMain.CallPostMessage(ID: Integer);
begin
PostMessage(self.Handle, WM_CALLBACK, ID, 0);
end;procedure TfrmMain.BackCallMessage(var Msg: TMessage);
begin
if Msg.Msg = WM_CALLBACK then
begin
if Msg.WParam = FLibHandle then
begin
FreeLibrary(FLibHandle);
FLibHandle := 0;
end;
end;
end;procedure TfrmMain.mmFileOpenClick(Sender: TObject);
var
FarPointer : FarProc;
begin
if FLibHandle = 0 then
begin
try
FLibHandle := LoadLibrary('Project2.dll');
except
FLibHandle := 0;
end;
if FLibHandle <> 0 then
begin
FarPointer := GetProcAddress(FLibHandle, 'ShowForm');
FShowForm := FarPointer;
FarPointer := GetProcAddress(FLibHandle, 'ActiveForm');
FActiveForm := FarPointer;
FarPointer := GetProcAddress(FLibHandle, 'CloseForm');
FCloseForm := FarPointer;
if Assigned(FShowForm) then
//FShowForm(Application, @CallBackProc, FLibHandle, self, panel1.Handle);
List.add(FShowForm(Application, @CallBackProc, FLibHandle, self, panel1.Handle));
end;
end
else
begin
if Assigned(FActiveForm) then
begin
FActiveForm;
end;
end;
end;procedure TfrmMain.mmFileCloseClick(Sender: TObject);
begin
if FLibHandle <> 0 then
FCloseForm;end;procedure TfrmMain.FormClose(Sender: TObject; var Action: TCloseAction);
begin
if FLibHandle <> 0 then
FCloseForm;
if assigned(FFrm) then
FreeAndNil(FFrm);
end;procedure TfrmMain.mmFileOpenFrmClick(Sender: TObject);
begin
if not assigned(FFrm) then
begin
FFrm := TForm1.Create(nil);
with FFrm do
begin
ParentWindow := panel1.Handle;
align := alClient;
BorderStyle := bsNone;
BorderIcons := [];
end;
end;
FFrm.Show;
end;procedure TfrmMain.N1111Click(Sender: TObject);
begin
FFrm.Edit2.Text := 'abc';
end;procedure TfrmMain.Change1Click(Sender: TObject);
begin
if FFrm.ParentWindow = Panel1.handle then
FFrm.ParentWindow := Panel2.handle
else
FFrm.ParentWindow := Panel1.handle
end;procedure TfrmMain.FormCreate(Sender: TObject);
begin
List := TList.Create;
end;end.
//调用窗体End
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, Menus, ExtCtrls, utchild;
const
WM_CALLBACK = WM_USER + 100;
type
TShowForm = function (App: TApplication; CallProc: Pointer; FormID: Integer; ParentForm: TForm; ParentContralHandle: HWND): Tform; stdcall;
TActiveForm = function : LongInt; stdcall;
TCloseForm = function : LongInt; stdcall;
TfrmMain = class(TForm)
MainMenu1: TMainMenu;
Open1: TMenuItem;
mmFileOpen: TMenuItem;
mmFileClose: TMenuItem;
Panel1: TPanel;
mmFileOpenFrm: TMenuItem;
mmFileCloseFrm: TMenuItem;
Report1: TMenuItem;
N1111: TMenuItem;
Panel2: TPanel;
Change1: TMenuItem;
procedure mmFileOpenClick(Sender: TObject);
procedure mmFileCloseClick(Sender: TObject);
procedure FormClose(Sender: TObject; var Action: TCloseAction);
procedure mmFileOpenFrmClick(Sender: TObject);
procedure N1111Click(Sender: TObject);
procedure Change1Click(Sender: TObject);
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
FLibHandle : THandle;
FShowForm : TShowForm;
FActiveForm : TActiveForm;
FCloseForm : TCloseForm;
List : TList;
//FFrm: TForm1;
procedure CallPostMessage(ID:Integer);
procedure BackCallMessage(var Msg: TMessage); message WM_CALLBACK; procedure WMHotKey(var Msg: TWMHotKey); message WM_HOTKEY;
function GetSysFocus: Integer;
public
{ Public declarations }
procedure WMACTIVATEAPP(var Msg: TMessage); message WM_ACTIVATEAPP;
end; var
frmMain: TfrmMain;
FFrm: TForm1;
implementation
const id_SnapShot = 115; //定义热键标识符 {$R *.dfm}
procedure TfrmMain.WMHotKey(var Msg: TWMHotKey); //主要是为了DLL内TAB键可用
var
H: THandle;
begin
if Msg.HotKey = id_SnapShot then
begin
H := GetSysFocus;
while IsWindow(H) and (H <> frmMain.Handle) do
begin
SendMessage(H,WM_NEXTDLGCTL,0,0);
H := GetParent(H);
end;
end;
end; function TfrmMain.GetSysFocus: Integer; //获取光标所在
var
hOtherWin,OtherThreadID,hFocusWin:integer;
begin
hOtherWin:=GetForegroundWindow;
OtherThreadID:=GetWindowThreadProcessID(hOtherWin,nil);
if AttachThreadInput(GetcurrentThreadID,OtherThreadID,True) then
begin
hFocusWin:=GetFocus;
result:=GetFocus;
if HFocusWin <>0 then
try
//
finally
AttachThreadInput(GetcurrentThreadID,OtherThreadID,False);
end;
end
else result:=GetFocus;
end; procedure TfrmMain.WMACTIVATEAPP(var Msg: TMessage); //系统热键
begin
if Boolean(Msg.WParam) then
RegisterHotKey(frmMain.Handle, id_SnapShot, 0, VK_TAB)
else
UnRegisterHotKey(frmMain.Handle, id_SnapShot);
end; procedure CallBackProc(ID:Integer); stdcall;
begin
frmMain.CallPostMessage(ID);
end; procedure TfrmMain.CallPostMessage(ID: Integer);
begin
PostMessage(self.Handle, WM_CALLBACK, ID, 0);
end; procedure TfrmMain.BackCallMessage(var Msg: TMessage);
begin
if Msg.Msg = WM_CALLBACK then
begin
if Msg.WParam = FLibHandle then
begin
FreeLibrary(FLibHandle);
FLibHandle := 0;
end;
end;
end; procedure TfrmMain.mmFileOpenClick(Sender: TObject); //动态调用project2.DLl
var
FarPointer : FarProc;
begin
if FLibHandle = 0 then
begin
try
FLibHandle := LoadLibrary('Project2.dll');
except
FLibHandle := 0;
end;
if FLibHandle <> 0 then
begin
FarPointer := GetProcAddress(FLibHandle, 'ShowForm');
FShowForm := FarPointer;
FarPointer := GetProcAddress(FLibHandle, 'ActiveForm');
FActiveForm := FarPointer;
FarPointer := GetProcAddress(FLibHandle, 'CloseForm');
FCloseForm := FarPointer;
if Assigned(FShowForm) then
//FShowForm(Application, @CallBackProc, FLibHandle, self, panel1.Handle);
List.add(FShowForm(Application, @CallBackProc, FLibHandle, self, panel1.Handle));
end;
end
else
begin
if Assigned(FActiveForm) then
begin
FActiveForm;
end;
end;
end; procedure TfrmMain.mmFileCloseClick(Sender: TObject);
begin
if FLibHandle <> 0 then
FCloseForm; end; procedure TfrmMain.FormClose(Sender: TObject; var Action: TCloseAction);
begin
if FLibHandle <> 0 then
FCloseForm;
if assigned(FFrm) then
FreeAndNil(FFrm);
end; procedure TfrmMain.mmFileOpenFrmClick(Sender: TObject);
begin
if not assigned(FFrm) then
begin
FFrm := TForm1.Create(nil);
with FFrm do
begin
ParentWindow := panel1.Handle;
align := alClient;
BorderStyle := bsNone;
BorderIcons := [];
end;
end;
FFrm.Show;
end; procedure TfrmMain.N1111Click(Sender: TObject);
begin
FFrm.Edit2.Text := 'abc';
end; procedure TfrmMain.Change1Click(Sender: TObject);
begin
if FFrm.ParentWindow = Panel1.handle then
FFrm.ParentWindow := Panel2.handle
else
FFrm.ParentWindow := Panel1.handle
end; procedure TfrmMain.FormCreate(Sender: TObject);
begin
List := TList.Create;
end; end.
//调用窗体End ps:
你如何声明的
myshowform1,
mycloseform1; 这两个方法