我需要从文件中读取相应的配置信息,在客户端程序中自动创建我想要的界面,当然了,界面上放置了许多控件,读取文件自动生成没有问题,可是我怎么把生成控件的动作(事件)绑定到相应的函数呢,也就是说我的事件不在客户端写,客户端程序不改动。能不能把相应的函数放到类似ini文件中,需要的时候读取出来直接赋给自动创建控件的事件呢?   我做的项目是通讯电源监控的,系统需要纳入多种不同设备,为了避免接入新设备就更改客户端程序,所以想让用户定制界面写入配置文件,让客户端调用生成相应的图形界面。这样就不必要老是修改程序了。先谢了!

解决方案 »

  1.   

    先读配置文件。然后根据配置文件动态创建控件, var   button : tbutton ;
     begin
         button := tbutton.create ;
         button.onclick := myproc;
    end;
    procedure myproc(sender:object);
    begin
      .....
    end;
      

  2.   

    unit Unit1;interfaceuses
      Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,stdCtrls;type
      TForm1 = class(TForm)
        procedure FormShow(Sender: TObject);
      private
        { Private declarations }
        procedure myClick(sender:Tobject);
      public
        { Public declarations }
      end;var
      Form1: TForm1;implementation{$R *.DFM}procedure TForm1.FormShow(Sender: TObject);
    var
    btn1:TButton;
    begin
        btn1:=TButton.create(self);//动态生成button控件
        btn1.Parent:=self;
        btn1.OnClick:=myClick;//动态生成button的事件代码。
    end;procedure TForm1.myClick(sender:Tobject);
    begin
        ShowMessage('124');
    end;end.
      

  3.   

    拿楼上所述的例子来说,我可以定义myClick函数,但是这个函数的要做的工作是不同的,可以改变的。我想不在客户端改,修改函数的时候在其他地方修改,这样才能保证客户端程序不会随着用户需求的改变而改变
     tw_cshn(一无所有):能告诉实现方法吗?代码谢在哪里?肯定的是不在客户端了
      

  4.   

    看下面的内容。
    运行期间生成代码的动态执行程序要执行首先要分配内存,在Win32下每个进程的内存地址空间都是虚拟的,其内存地址不是实际的物理地址,所以使用VirtualAlloc来完成虚拟内存的分配!  LPVOID VirtualAlloc(
        LPVOID lpAddress,
        SIZE_T dwSize,
        DWORD flAllocationType,
        DWORD flProtect
      );lpAddress 为申请的内存的起始地址,在Win32中你可以自己指定申请内存的地址范围!Win32中每个进程的地址空间为4GB,从0X00000000到0XFFFFFFFF。那是否可以在这个范围内任意分配内存?答案是否定的!在这其中只有一部分是可以供Win32应用使用的。使用GetSystemInfo获取系统信息,其中的lpMinimumApplicationAddress、lpMaximumApplicationAddress分别是可以使用的最小地址和最大地址。当然这里可以简单的设其值为Null,套用MSDN中的一句话:“If this parameter is NULL, the system determines where to allocate the region.”,直接将其交给系统去处理!dwSize 为申请内存大小,以字节为单位,但如果其大小不为页的整数倍,系统将会加大内存达到页的整数倍。所以尽量按页来申请。同样可以用GetSystemInfo来获取dwPageSize。如Win9X下一页为4K,即4096字节。flAllocationType 指定申请方式,flProtect 指定内存的保护方式,具体信息可查看MSDN:
    http://msdn.microsoft.com/library/default.asp?url=/library/en-us/memory/base/virtualalloc.asp这里根据需要将两参数设为MEM_COMMIT(提交已经申请的内存)、PAGE_EXECUTE_READWRITE(执行和读写) 完成了内存分配的工作后,下面就是将待执行的代码保存到内存中。机器语言指令是多字节指令,所以接下来要做的就是将一串具体数字按字节写入内存中。下面的代码完成了一段子程序的生成:var
      Code:PByte;
      Str:String;
      Data:Longint;
      num:integer;  procedure AddCode(const CodeByte:Byte);//将数据赋给指针指向的位置
      begin
        Code^:=CodeByte;
        Inc(Code);
        Inc(num);
      end;begin
      num:=0;
      Code:=VirtualAlloc(nil, 4096, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
      AddCode($50);//PUSH EAX
      AddCode($B8);//MOV EAX
      Str:='Hello World!';
      Data:=Longint(Pointer(PChar(Str)));//取字符串地址
      AddCode(Data and $FF);
      AddCode(Data and $FF00 shr 8);
      AddCode(Data and $FF0000 shr 16);
      AddCode(Data and $FF000000 shr 24);
      AddCode($E8);//CALL
      Data:=Longint(@ShowMessage) - Longint(Code) - 4;//计算Showmessage的相对地址
      AddCode(Data and $FF);
      AddCode(Data and $FF00 shr 8);
      AddCode(Data and $FF0000 shr 16);
      AddCode(Data and $FF000000 shr 24);
      AddCode($58);//POP EAX
      AddCode($C3);//RET
      Dec(Code,num);//指针移动,返回首地址
    end;也许可以通过相应技术手册来查询相应指令的含义,但在Win32下其实有种简单的理解方法。其实只要对任意一个Win32程序进行反编译,即可获得相应指令和汇编助记符的对应关系。用汇编代码表述其意义为:PUSH EAX
    MOV EAX,[字符串地址]
    CALL ShowMessage
    POP EAX
    RET接下来,通过嵌入ASM代码:
    asm
      Call Code
    end;
    就完成了上面代码的动态调用执行。
      

  5.   

    老天,汇编语言都上阵了 zzh26(瞌睡) 所说的
    我还真的不知道所有的函数的功能,因为如果系统纳入了一种新设备那么通信协议是不定的,各种电源的功能也是不一样的,我不可能预先知道所有的函数怎么写
    这个方法我也考虑过,但是觉得不是特别好
    我还考虑是不是用回调函数,只是觉得太麻烦了,想看看有没有更好的办法
      

  6.   

    建议将你的动态代码用Dll来实现,这样需要改的时候修改Dll再发给客户就可以了,
      

  7.   

    wooden954(wooden) 好:
    是不是在使用的时候利用回调函数来调用dll实现啊
      

  8.   

    建议你使用组件(COM)技术,对于系统扩展来说是最简单,成本最低也最安全的
      

  9.   

    我觉得用DLL应该可以的。思路:所有自定义的按钮调用同一事件。所有的DLL的导出函数的参数想同。根据不同的按钮所设定的参数来Load不同的DLL,调用指定的Function.