DLL操作规范:1、在dll中封装窗体要注意:dll中的Application对象和调用它的应用程序的Application对象是有区别的。对于一般的应用程序来说,Application对象是VCL固定的,一般不需要修改Application对象指针。但是在DLL中,使用窗体或者使用Application对象时,必须使dll的Application和调用程序一样,这样才不至于混淆。如果不修改Application对象,那么应用程序退出的时候,可能会出现错误。
这种错误用如下方法解决:在dll中增加一个过程,过程以应用程序的句柄作为参数,并将此句柄赋值给dll的Application对象的句柄,示例如下:Procedure SynApp(App:THandle);stdcall;
begin
  Application.Handle := App;
end;并且该过程必须首先调用,然后调用dll的显示窗体的过程。(或者将此过程与显示窗体过程结合到一起,不过要先进行Application对象的传递)在应用程序中调dll则应该这样写:
interface
{省略了其他代码}
procedure SynApp(App:THandle);stdcall;external 'TestDll.dll';
procedure ShowForm;stdcall;external 'TestDll.dll';
调用封装在dll中的窗体的代码并添加在按钮的Click事件处理过程中:
Procedure Tfrom1.Button1Click(Sender:TObject);
begin
  SynApp(Appliation.Handle);//首先必须调用这个程序,并且使用Application的句柄作为参数
  ShowForm;
end;2、在dll中声明的外调函数或过程,也即在exports后面声明的函数或过程,在应用程序中声明时是区分大小写的,规则以exports部分声明的为准。3、当dll中有用到ADO或是其他COM控件时,要用CoInitialize(nil)来初始化com对象,程序结束时要用到CoUninitialize; 或者用另外一种方法:在主应用程序里面引用DB, ADODB就不用上面的初始化了。4、DLL中的数据模块放置ADOconnetion控件后,为什么其他窗体上的数据集控件已正确的连接到它,但在程序运行时打开数据集却出现“missing Connection or ConnectionString”的错误?? 
解决方法:当窗体Create时再手动连接一次窗体中数据集的Connection为数据模块中相关的Connection。5、Dll中的子窗体操作:示例如下
library DLL;{ Important note about DLL memory management: ShareMem must be the
  first unit in your library's USES clause AND your project's (select
  Project-View Source) USES clause if your DLL exports any procedures or
  functions that pass strings as parameters or function results. This
  applies to all strings passed to and from your DLL--even those that
  are nested in records and classes. ShareMem is the interface unit to
  the BORLNDMM.DLL shared memory manager, which must be deployed along
  with your DLL. To avoid using BORLNDMM.DLL, pass string information
  using PChar or ShortString parameters. }uses
  ShareMem,//当dll中使用字符串时要引用该单元且放置第一个
  Windows,
  SysUtils,
  forms,
  Classes,
  ActiveX,
  dll_pds_Unit in 'dll_pds_Unit.pas' {pds},
  dll_cache_Unit in 'dll_cache_Unit.pas' {cache: TDataModule},
  m0_Unit in 'm0_Unit.pas' {m0: TDataModule};{$R *.res}
var
  DLLApp: TApplication;
  DLLScr: TScreen;  //两个变量用于记录dll本身的Application和Screen
  当dll创建时,要以主应用程序的上述句柄来代替,当要释放dll时再还原procedure DllEnterPoint(dwReason: DWORD); far; stdcall;{此方法用于来初始化,也即入口函数,可以做一些相关的初始化操作
例如本处用CoInitialize(nil)来初始化com对象,当进程退出时释放
com对象,但有个问题进程进入时该函数可以自动运行,但退出时就不行
当然,也可以把这些初始化操作放到创建dll窗体的时候来做,可自由选择
注意:如果写了此函数,在dll程序的begin与end之间就要加入下面代码:
  DLLProc := @DLLEnterPoint;
  DllEnterPoint(DLL_PROCESS_ATTACH);}begin
  case dwReason of
    DLL_PROCESS_ATTACH: {进程进入时初始化COM对象}
      begin
        CoInitialize(nil);
      end;
    DLL_PROCESS_DETACH: {进程退出时释放COM对象}
      begin
        cache.Free;
        CoUninitialize;
      end;
    DLL_THREAD_ATTACH: ; {线程进入时MessageBeep(0)}
    DLL_THREAD_DETACH: ; {线程退出时MessageBeep(0)}
  end;
end;procedure CreateDll(App: TApplication; Scr: TScreen); stdcall;
begin
  Application := App; {用作初始化DLL的Application对象}
  Screen := Scr;
  cache := Tcache.Create(nil);//数据模块,里面包含ADOconnection组件,主连接组件
  m0 := Tm0.Create(nil);//数据模块,其中的数据集连接到cache数据模块上的ADOconnection组件
  //Application.CreateForm(Tcache, cache);
  pds := Tpds.Create(application);  //此处的pds窗体是一个fsMDIChild类型的子窗体,此处的创建表示pds的拥有者是主应用程序的Application
  pds.Show;
end;procedure ExitDLL(Reason: Integer);
{此函数是当dll退出时还原为原来的句柄,这样是为了主应用程序退出时出错}
begin
  if Reason = DLL_PROCESS_DETACH then
  begin
    Application := DLLApp;
    Screen := DLLScr;
  end;
end;exports
  CreateDll;begin
  DLLApp := Application;
  DLLScr := Screen;
  CoInitialize(nil);  //初始化com对象
  DLLProc := @ExitDLL;
  //DLLProc := @DLLEnterPoint;
  //DllEnterPoint(DLL_PROCESS_ATTACH);
end.6、子窗体菜单隔合到主窗体主菜单中的方法:先设计好相应的菜单,然后设置各自的groupindex属性,不等时,它们会自动融合,相等时子窗体菜单会替换主窗体菜单在最后请求大家帮我解决一个问题:
我的DLL程序都通过上面的方法做了,但是在退出主应用程序时还是出现非法错误,然后有的时候还会出现错误的指针操作的提示!大家有哪位有更好的写DLL程序的经验,共享一下呀!!同时帮我看看这是什么问题,应该还要注意哪里? 多谢,在线等待!!!!