您的位置:首页 > 其它

用AlphaControls皮肤控件来美化用Dll制作的MDI子窗体程序

2014-01-03 15:58 656 查看
AlphaControls控件是目前效果比较好的皮肤控件,专业和细致。

有朋友咨询用Dll制作的MDI子窗体程序被调用后,没有被美化,如何处理?

其实即使正常的窗体被放在dll中,再用主程序来调用,按正常的程序也无法美化dll中的窗体。要想美化,就用包的形式即可。

 

我们制作非常简单的程序,主窗体为一MDI主窗体,在主窗体上放AlphaControls的TsSkinManager控件并设置其相关属性。

另建立一个dll工程,内建MDIChild子窗体,放TsSkinProvider于上。

如下图:

     主程序:


        

DLL中的子窗体:



    

上面其它的控件没什么用,只是看下其它的美化如何而已。

 

我们以静态调用的方式来做例。以下为制作过程:

 一、制作dll

        dll和exe在运行时它们都有自己的application。因此在调用dll时要把主程序的Application传给dll中,即这个application属于dll的Owner,在dll卸载时要把原来dll的Application还原给dll,让dll继续它原来的处理,否则你在调用 时会出问题。

        另把MDI子窗体封装在dll中,dll中的application并没有MDI主窗体,这样在调用时因为没有主窗体就不可以产生子窗体,这样就会出现找不到子窗体的错误提示信息了。因此就需要把应用程序的Application传到dll中才行。

       我们用delphi建立dll时,有一个dll入口,即C++中的DLLMain()函数入口。 在delphi中dll的初始化工作是在工程文件最后的begin end中间。

       我们先在工程文件中建立全局变量用于保存dll的application,,等dll退出时再还原dll的application即可。 dll的入口函数自己写,主要有四个参数,表示dll在加载或卸载时要进行的处理动作:

             DLL_PROCESS_ATTACH:   <进程中加载DLL时>

             DLL_THREAD_ATTACH:      <线程中加载DLL时>

             DLL_THREAD_DETACH:      <在线程中卸载Dll时>

             DLL_PROCESS_DETACH:    <在进程中卸载Dll时>

       我们在程序调用dll时把dll的application保存到全局变量中,在退出时再还原,因此我们要把这些功能代码放到dll工程的begin..end之间。

        另DllProc是全局变量用来指向dll的入口函数地址,即dll的调用和卸载都是从这个地址开始的,因为我们把这些处理过程全放在一个函数中,在dll的入口处把DllProc指向这个处理函数即可。

       工程文件的源代码:
library Prodll;

{ 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
System.SysUtils,
System.Classes,
Vcl.Forms,
Winapi.Windows,
Vcl.Dialogs,
USecond in 'USecond.pas' {UFrmSecond};

{$R *.res}
var
DllApp:TApplication; //保存原dll的Application

//Dll的入口函数
procedure DLLEntry(Reason:DWORD);
begin
case Reason of
DLL_PROCESS_ATTACH:Application.MessageBox('DLL_PROCESS_ATTACH','ok')  ;
DLL_THREAD_ATTACH:
begin
DllApp:=Application;
Application.MessageBox('DLL_THREAD_ATTACH','ok');
end;

DLL_THREAD_DETACH:  Application.MessageBox('DLL_THREAD_DETACH','ok');
DLL_PROCESS_DETACH:
begin
Application:=DllApp;
Application.MessageBox('DLL_PROCESS_DETACH','ok');
end;

end;
end;

exports
showme;

begin
//Dll被调用时初始化
//DLLApp:=Application; //也可以用前面这句话,此时可以把DLL_THREAD_ATTACH去掉即可。
DllProc:=@DLLEntry;
end.


  我们在子窗体中做一个公共函数用于导出调用:
unit USecond;

interface

uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants,
System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.ExtCtrls, sBevel, Vcl.StdCtrls,
Vcl.Buttons, sBitBtn, sPanel, sSkinProvider, cxGraphics, cxControls,
cxLookAndFeels, cxLookAndFeelPainters, cxStyles, dxSkinsCore,
dxSkinXmas2008Blue, dxSkinscxPCPainter, cxCustomData, cxFilter, cxData,
cxDataStorage, cxEdit, DB, cxDBData, cxContainer, cxDropDownEdit, cxTextEdit,
cxMaskEdit, cxCalendar, cxProgressBar, cxGridLevel, cxClasses,
cxGridCustomView, cxGridCustomTableView, cxGridTableView, cxGridDBTableView,
cxGrid;

type
TUFrmSecond = class(TForm)
sPanel1: TsPanel;
sBitBtn1: TsBitBtn;
sBevel1: TsBevel;
sSkinProvider1: TsSkinProvider;
Edit1: TEdit;
Button1: TButton;
cxGrid1DBTableView1: TcxGridDBTableView;
cxGrid1Level1: TcxGridLevel;
cxGrid1: TcxGrid;
cxProgressBar1: TcxProgressBar;
cxDateEdit1: TcxDateEdit;
cxComboBox1: TcxComboBox;
procedure FormClose(Sender: TObject; var Action: TCloseAction);
private
{ Private declarations }
public
{ Public declarations }
end;

procedure showme(var App: TApplication; ptitle: PChar; ParentForm: TForm); stdcall;

var
UFrmSecond: TUFrmSecond;

implementation

{$R *.dfm}

procedure TUFrmSecond.FormClose(Sender: TObject; var Action: TCloseAction);
begin
Action := caFree;
end;
//传入应用程序的application及主窗体
procedure showme(var App: TApplication; ptitle: PChar; ParentForm: TForm);
var
i: integer;
frm: TCustomForm;
begin
Application:=App;
frm := nil;
for i := 0 to ParentForm.MDIChildCount - 1 do
begin
if (Application.MainForm.MDIChildren[i] is TUFrmSecond) then
frm := TUFrmSecond(Application.MainForm.MDIChildren[i]);
end;

if not  Assigned(frm) then
begin
frm := TUFrmSecond.Create(ParentForm);
end;
//TForm(frm).FormStyle := fsMDIChild;//因在设计时设置了窗体样式,所以注销了。
frm.Caption:=StrPas(ptitle);
frm.Show;
end;

end.


记得传入的application是传址哦。    

 

二、建立主应用程序
unit UMain;

interface

uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.Menus, sSkinProvider, sSkinManager;

type
TFrmMain = class(TForm)
MainMenu1: TMainMenu;
N1: TMenuItem;
sSkinManager1: TsSkinManager;
procedure N1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
procedureshowme(var App:TApplication; ptitle:PChar;ParentForm:TForm);stdcall; external 'Prodll.dll';
var
FrmMain: TFrmMain;

implementation

{$R *.dfm}

procedure TFrmMain.N1Click(Sender: TObject);
begin
showme(Application,'子窗体',FrmMain);

end;

end.


以下为窗体运行界面:

   主窗体:

 

  

     调用后显示照片:

     

 


记着:dll和主程序一定要用打包的方式才能美化子窗体,否则不能美化。如果不放置TsSkinProvider,则只能美化AlphaControls的控件,其它的不能美化。

 

 不当之处请指正。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: