在DLL中开辟一段内存,主程序运行后将你的DLL要调用的过程和函数地址保存到该内存中.然后DLL
根据这些过程和函数地址进行调用.

解决方案 »

  1.   

    delhpi  的 DLL机制不是很稳定,用内存管理的方法非常容易产生内存冲突,我不明白你为什么要在DLL 中调用主调程序的东西,,如果必要将被调用部分写成DLL,
      

  2.   

    同意skypeople说的。完全可以把两者都要调用的东西再做成一个DLL,这样原来的Main与DLL都可以调用了。
      

  3.   


    1、设置回调函数,函数指针作为参数(进程内);2、建立COM对象,添加EventSink处理(对于Delphi 5 创建派遣接口的回调事件将自动维护该方法)(推荐方法)。3、建立COM接口以及调用程序的回调接口(进程内/进程外均可,工作量大,但可全盘控制)。
      

  4.   

    我也想把调用部分写成dll的,但是这块部分用了动态加载控件,还用了hook,所以不方便写成dll,下面是主程序的原代码,我主要调用procedure info2ctrl 和沟子部分,怎样才能解决呢?我现在暂时给20分,有人解决 就会给高分的!!
    unit ufrmExecute;interfaceuses
      Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, CommCtrl,
      StdCtrls, ShellApi, extctrls, ScktComp, zlclass, inifiles, ComCtrls, Grids, Math, Buttons;const
      WM_ItemInsert = WM_App + 1;                               //ListView中新增加item
      WM_ItemSetItem = WM_App + 2;                              //ListView中Item赋值
      WM_ItemSetItemText = WM_App + 3;                          //ListView中Item赋值
      WM_TEXTHOOK_EXCEPTION = WM_USER + $201;
    type
      TfrmExecute = class(TForm)
        tmConnect: TTimer;
        Label9: TLabel;
        sgrdXcuting: TStringGrid;
        Label2: TLabel;
        sgrdTask: TStringGrid;
        btnDelTask: TButton;
        aniDigital: TAnimate;
        btnStartUp: TButton;
        btnSetup: TButton;
        btnExit: TButton;
        btnStop: TButton;
        Bevel1: TBevel;
        lblCnn: TLabel;
        aniGlobal: TAnimate;
        lblTerminalID: TLabel;
        Bevel2: TBevel;
        lblRet: TLabel;
        lstRet: TListBox;
        lblGet: TLabel;
        lstGet: TListBox;
        lblFlex: TLabel;
        procedure btnExitClick(Sender: TObject);
        procedure FormCreate(Sender: TObject);
        procedure btnSetupClick(Sender: TObject);
        procedure btnStartUpClick(Sender: TObject);
    procedure CreateSocketConnection();
        procedure ClientSocketConnect(Sender: TObject; Socket: TCustomWinSocket);
        procedure ClientSocketRead(Sender: TObject; Socket: TCustomWinSocket);
        procedure ClientSocketError(Sender: TObject; Socket: TCustomWinSocket;
          ErrorEvent: TErrorEvent; var ErrorCode: Integer);
        procedure btnLogKeyDown(Sender: TObject; var Key: Word;
          Shift: TShiftState);
        procedure sgrdTaskDrawCell(Sender: TObject; ACol, ARow: Integer;
          Rect: TRect; State: TGridDrawState);
        procedure FormClose(Sender: TObject; var Action: TCloseAction);
    //    procedure btnLogClick(Sender: TObject);
        procedure btnDelTaskClick(Sender: TObject);
        procedure sgrdTaskSelectCell(Sender: TObject; ACol, ARow: Integer;
          var CanSelect: Boolean);
        procedure FormDestroy(Sender: TObject);
        procedure tmConnectTimer(Sender: TObject);
        procedure FormKeyDown(Sender: TObject; var Key: Word;
          Shift: TShiftState);
        procedure btnStopClick(Sender: TObject);
        procedure Info2Ctrlr(sCode, sAcctName, sStatus, sCnttCode, sNum, sPrice: string);    //信息发送到控制端
    private
      nPriorTime: DWORD;                                      //上一指令执行时的计数值
      zlPrior: TZLRecord;                                     //上一条执行的指令
    //    procedure StopQuery; //收到停止查询指令后,从指令缓存表中将所有未执行的余额、余股查询指令删除
      procedure UpdateConnectionIndicator(bConnected: boolean);
    public
      bProbeInstalled: Boolean; //TextOut 函数的钩子安装了与否
      procedure BeginProbe(TargetHandle: THandle); //对目标窗口安装TextOut及ExtTextOut函数钩子
      procedure EndProbe; //卸载TextOut及ExtTextOut函数钩子
        ////以下是为获取ListView内容所用的各过程/////////////////////////   remove
      function InstallListviewHook: boolean;                  //安装钩子,执行端启动时安装
      function UninstallListviewHook: boolean;                //卸载钩子,执行端关闭时卸载  procedure OnItemInsert(var Msg: TMessage); message WM_ItemInsert;
      procedure OnItemSetItem(var Msg: TMessage); message WM_ItemSetItem;
      procedure OnItemSetItemText(var Msg: TMessage); message WM_ItemSetItemText;  procedure MsgExtTextout(var msg: TMessage); message WM_TEXTHOOK_EXCEPTION + 1;
      procedure MsgTextout(var msg: TMessage); message WM_TEXTHOOK_EXCEPTION + 2;
      procedure MsgCMPDC(var msg: TMessage); message WM_TEXTHOOK_EXCEPTION + 3;  procedure ShowProberText(nCols: integer);
      procedure ShowReturnText();
      procedure ShowFlexHandle(sFlexHandle: string);end;
     { 交易系统模块输出函数类型}
    type  TIsStartUpSuccess     = function(zl: TZLRecord): Boolean; stdcall;
      TCloseSystem          = procedure;                        stdcall;
      TTradeBuyFunc         = function(zl: TZLRecord): Boolean; stdcall;      //买函数
      TTradeSellFunc        = function(zl: TZLRecord): Boolean; stdcall;      //卖函数
      TTradeChedanFunc      = function(zl: TZLRecord): Boolean; stdcall;      //撤单函数
      TTradeQueryFundsFunc  = function(zl: TZLRecord): Boolean; stdcall;      //查询余额函数
      TTradeQueryStockFunc  = function(zl: TZLRecord): Boolean; stdcall;      //查询余股函数
      TTradeQueryOrderFunc  = function(zl: TZLRecord): Boolean; stdcall;      //成交查询函数
    //////定义当前交易系统类型记录////////////////////
    TCurrSys=  record
      hCurr                  : THandle;
      SysName                : string;
      IsStartUpSuccess       : TIsStartUpSuccess;
      CloseSystem            : TCloseSystem;
      TradeBuyFunc           : TTradeBuyFunc;
      TradeSellFunc          : TTradeSellFunc;
      TradeChedanFunc        : TTradeChedanFunc;
      TradeQueryFundsFunc    : TTradeQueryFundsFunc;
      TradeQueryStockFunc    : TTradeQueryStockFunc;
      TradeQueryOrderFunc    : TTradeQueryOrderFunc;
     end;var
      frmExecute: TfrmExecute;
      CurrSys:    TCurrSys;
      sIPAddrCtrl      : String;//控制端IP地址
      g_sTrmnID  : String;//本执行端序号{$IFDEF Debug}
      LogFile: TextFile;
    {$ENDIF}//  g_sck: TClientSocket;
      ZLTable: TZLData;                                         //指令缓存表
      ZxTable: TPerformTable;                                   //指令执行纪录表
      WaitForCount: DWORD;                                      //内部网络断开计时
      MsgStruct: ^CWPSTRUCT;
      bCloseProgram: boolean;                                   //是否关闭应用程序  bPriorZlSuccess: boolean;                                 //上一条指令执行成功与否
      sLVContent: array of array of string;                     //所取到的ListView的内容,每一行的内容为List中的一行值,
                                    //在取ListView内容之前,须将它清空
      str: string;
      slTextOut, slXTextOut: TStringList;           //TextOut、ExtTextOut函数钩子得到的字符串
      function ListviewHookProc(iCode: Integer; WParam: WPARAM; lParam: LPARAM): LRESULT; stdcall; far;  //主程序用
      ///////////////////////////////////////////////////////////////////////
    //procedure CloseAll;                                         //关闭所有系统
    procedure ParseCommand(sCommand: string);           //分解命令字符串的各部分,并分析其有效性
    implementationuses SysSetup, GridClass, Dll16, unitGlobal, unitWinFunc;
    {$R *.DFM}//////////////////////////沟子过程开始//////////////////////////////////////
    procedure TfrmExecute.BeginProbe(TargetHandle: THandle); //对目标窗口安装TextOut及ExtTextOut函数钩子
    begin
      slXTextOut.Clear;
      slTextOut.Clear;
      if bProbeInstalled then EndProbe;
      SetDlgHandle16(Self.Handle);
      SetTargetHandle16(TargetHandle);
      if not bProbeInstalled then begin
        InstallProbe16;
        bProbeInstalled := True;
      end;end;procedure TfrmExecute.EndProbe; //卸载TextOut及ExtTextOut函数钩子
    begin
      if bProbeInstalled then UNInstallProbe16;
      bProbeInstalled := False;
    end;procedure TfrmExecute.MsgExtTextout(var msg: TMessage);
    begin
      if msg.WParam = 0 then Str := '';
      if msg.LParam = 0 then slXTextOut.Add(str)
      else str := str + chr(Byte(msg.LParam));
    end;procedure TfrmExecute.MsgTextout(var msg: TMessage);
    begin
      if msg.WParam = 0 then Str := '';
      if msg.LParam = 0 then slTextOut.Add(str)
      else  str := str + chr(Byte(msg.LParam));
    end;function CMPDC(DC1, DC2: HWND): Boolean;
    var
      C1: HDC;
    begin
      C1 := WOWHandle32(DC1, 4);
      Result := WindowFromDC(C1) = DC2;
    end;
    procedure TfrmExecute.MsgCMPDC(var msg: TMessage);
    var
      a: Boolean;
    begin
      a := CMPDC(msg.wParam, msg.lParam);
      msg.Result := Integer(a);
    end;
    //安装钩子,执行端启动时安装////////////////////////////////////
    function TfrmExecute.InstallListviewHook: boolean;
    begin
      Result := False;
      if g_hHookProc <> 0 then Exit;                            //如果钩子已安装则退出
      g_hHookProc := SetWindowsHookEx(WH_CALLWNDPROC, @ListviewHookProc, g_hinstApp, 0); //装钩子
      Result := g_hHookProc <> 0;                               //返回钩子是否安装成功
    end;//卸载钩子,执行端关闭时卸载//////////////////////////
    function TfrmExecute.UninstallListviewHook: boolean;
    begin
      if g_hHookProc <> 0 then
        if UnhookWindowshookEx(g_hHookProc) then g_hHookProc := 0; //卸载钩子
      Result := g_hHookProc = 0;
    end;////钩子处理过程/////////////////////
    function ListviewHookProc(iCode: Integer; WParam: WPARAM; lParam: LPARAM): LRESULT; stdcall;
    var
      h: HWND;
    begin
      if iCode >= 0 then begin
        MsgStruct := pointer(lParam);
        h := Windows.FindWindow('TfrmExecute', '交易代理');
        case MsgStruct^.message of
          LVM_INSERTITEM: begin                                 //如果是ListView中增加一个Item,则
              SendMessage(h, WM_ItemInsert, MsgStruct^.wParam, MsgStruct^.lParam); //发送WM_ItemInsert消息
            end;
          LVM_SETITEM: begin                                    //如果是给ListView中某一子Item赋值,则
              SendMessage(h, WM_ItemSetItem, MsgStruct^.wParam, MsgStruct^.lParam); //发送WM_ItemSetItem消息
            end;
          LVM_SETITEMTEXT: begin                                //如果是给ListView中某一子Item赋值,则
              SendMessage(h, WM_ItemSetItemText, MsgStruct^.wParam, MsgStruct^.lParam); //发送WM_ItemSetItemText消息
            end;
        end;
      end;
      Result := CallNextHookEx(g_hHookProc, iCode, wParam, lParam);
    end;///处理WM_ItemInsert消息//////////////////////////////
    procedure TfrmExecute.OnItemInsert(var Msg: TMessage);
    var
      meminfo: MEMORY_BASIC_INFORMATION;
      dwPro: DWORD;
      dwOldProtect, dwOldProtect2: DWord;
      aitem: LV_ITEM;
      aCount: Cardinal;
      tmpItemText: array[0..254] of Char;                       //临时保存ListView的item的值
      hProc: THandle;                                           //包含ListView的进程的句柄
    begin
      if g_hProcessId = 0 then exit;
      hProc := OpenProcess(PROCESS_ALL_ACCESS, true, g_hProcessId); //得到进程句柄,其中ProcessId在启动盛润或精信时赋值
      Fillchar(memInfo, sizeof(MEMORY_BASIC_INFORMATION), $0);  //置初值
      dwPro := VirtualQueryEx(hProc, pointer(Msg.LParam), memInfo, sizeof(MEMORY_BASIC_INFORMATION));
      if dwPro <> sizeof(MEMORY_BASIC_INFORMATION) then exit;
      if not VirtualProtectEx(hProc, pointer(Msg.LParam), sizeof(LV_ITEM), PAGE_EXECUTE_READ, @dwOldProtect) then exit;
      if not ReadProcessMemory(hProc, pointer(Msg.LParam), @aitem, sizeof(LV_ITEM), aCount) then exit;
      if not VirtualProtectEx(hProc, pointer(Msg.LParam), sizeof(LV_ITEM), dwOldProtect, @dwOldProtect2) then exit;
      dwPro := VirtualQueryEx(hProc, (aitem.pszText), memInfo, sizeof(MEMORY_BASIC_INFORMATION));
      if dwPro <> sizeof(MEMORY_BASIC_INFORMATION) then exit;
      if not VirtualProtectEx(hProc, (aitem.pszText), 255, PAGE_EXECUTE_READ, @dwOldProtect) then exit;
      if not ReadProcessMemory(hProc, (aitem.pszText), @tmpItemText, 255, aCount) then exit;
      if Length(sLVContent) <= 0 then                           //如果接受数组长度小于等于0(表示要增加的是ListView中的第一个Item),则
        SetLength(sLVContent, 1)                                //给接受数组设长度1
      else if aitem.iItem > Length(sLVContent) - 1 then         //如果要增加的Item的索引值大于接受数组的长度,则
        SetLength(sLVContent, aitem.iItem + 1);                 //接受数组长度加1
      SetLength(sLVContent[aitem.iItem], 1);
      sLVContent[aitem.iItem, 0] := tmpItemText;                //将Item的文本值保存下来
      VirtualProtectEx(hProc, (aitem.pszText), 255, dwOldProtect, @dwOldProtect2);
    end;///处理WM_ItemSetItem消息//////////////////////////////
    procedure TfrmExecute.OnItemSetItem(var Msg: TMessage);
    var
      meminfo: MEMORY_BASIC_INFORMATION;
      dwPro: DWORD;
      dwOldProtect, dwOldProtect2: DWord;
      aitem: LV_ITEM;
      tmp1, tmp2, tmp3: integer;
      aCount: Cardinal;
      tmpItemText: array[0..254] of Char;                       //临时保存ListView的item的值
      hProc: THandle;                                           //包含ListView的进程的句柄
    begin
      if g_hProcessId = 0 then exit;
      hProc := OpenProcess(PROCESS_ALL_ACCESS, true, g_hProcessId); //得到进程句柄,其中ProcessId在启动盛润或精信时赋值
      Fillchar(memInfo, sizeof(MEMORY_BASIC_INFORMATION), $0);  //置初值
      dwPro := VirtualQueryEx(hProc, pointer(Msg.LParam), memInfo, sizeof(MEMORY_BASIC_INFORMATION));
      if dwPro <> sizeof(MEMORY_BASIC_INFORMATION) then exit;
      if not VirtualProtectEx(hProc, pointer(Msg.LParam), sizeof(LV_ITEM), PAGE_EXECUTE_READ, @dwOldProtect) then exit;
      if not ReadProcessMemory(hProc, pointer(Msg.LParam), @aitem, sizeof(LV_ITEM), aCount) then exit;
      if not VirtualProtectEx(hProc, pointer(Msg.LParam), sizeof(LV_ITEM), dwOldProtect, @dwOldProtect2) then exit;
      dwPro := VirtualQueryEx(hProc, (aitem.pszText), memInfo, sizeof(MEMORY_BASIC_INFORMATION));
      if dwPro <> sizeof(MEMORY_BASIC_INFORMATION) then exit;
      if not VirtualProtectEx(hProc, (aitem.pszText), 255, PAGE_EXECUTE_READ, @dwOldProtect) then exit;
      if not ReadProcessMemory(hProc, (aitem.pszText), @tmpItemText, 255, aCount) then exit;
      tmp1 := aitem.iSubItem;
      tmp2 := aitem.iItem;
      tmp3 := Length(sLVContent[tmp2]) - 1;
      if tmp1 > tmp3 then                                       //如果要赋值的子项的索引值大于接受数组中第几行的长度,则
        SetLength(sLVContent[tmp2], tmp1 + 1);                  //按受数组该行的长度加1
      sLVContent[tmp2, tmp1] := tmpItemText;                    //保存该子项的文本值
      VirtualProtectEx(hProc, (aitem.pszText), 255, dwOldProtect, @dwOldProtect2);
    end;///处理WM_ItemSetItemText消息//////////////////////////////
    procedure TfrmExecute.OnItemSetItemText(var Msg: TMessage);
    var
      meminfo: MEMORY_BASIC_INFORMATION;
      dwPro: DWORD;
      dwOldProtect, dwOldProtect2: DWord;
      aitem: LV_ITEM;
      ItemIndex: integer;
      tmp1, tmp2, tmp3: integer;
      aCount: Cardinal;
      tmpItemText: array[0..254] of Char;                       //临时保存ListView的item的值
      hProc: THandle;                                           //包含ListView的进程的句柄
    begin
      if g_hProcessId = 0 then exit;
      ItemIndex := Msg.WParam;
      hProc := OpenProcess(PROCESS_ALL_ACCESS, true, g_hProcessId); //得到进程句柄,其中ProcessId在启动盛润或精信时赋值
      Fillchar(memInfo, sizeof(MEMORY_BASIC_INFORMATION), $0);  //置初值
      dwPro := VirtualQueryEx(hProc, pointer(Msg.LParam), memInfo, sizeof(MEMORY_BASIC_INFORMATION));
      if dwPro <> sizeof(MEMORY_BASIC_INFORMATION) then exit;
      if not VirtualProtectEx(hProc, pointer(Msg.LParam), sizeof(LV_ITEM), PAGE_EXECUTE_READ, @dwOldProtect) then exit;
      if not ReadProcessMemory(hProc, pointer(Msg.LParam), @aitem, sizeof(LV_ITEM), aCount) then exit;
      if not VirtualProtectEx(hProc, pointer(Msg.LParam), sizeof(LV_ITEM), dwOldProtect, @dwOldProtect2) then exit;
      dwPro := VirtualQueryEx(hProc, (aitem.pszText), memInfo, sizeof(MEMORY_BASIC_INFORMATION));
      if dwPro <> sizeof(MEMORY_BASIC_INFORMATION) then exit;
      if not VirtualProtectEx(hProc, (aitem.pszText), 255, PAGE_EXECUTE_READ, @dwOldProtect) then exit;
      if not ReadProcessMemory(hProc, (aitem.pszText), @tmpItemText, 255, aCount) then exit;
      tmp1 := aitem.iSubItem;
      tmp2 := ItemIndex;
      tmp3 := Length(sLVContent[tmp2]) - 1;
      if tmp1 > tmp3 then                                       //如果要赋值的子项的索引值大于接受数组中第几行的长度,则
        SetLength(sLVContent[tmp2], tmp1 + 1);                  //按受数组该行的长度加1
      sLVContent[ItemIndex, tmp1] := tmpItemText;               //保存该子项的文本值
      VirtualProtectEx(hProc, (aitem.pszText), 255, dwOldProtect, @dwOldProtect2);
    end;
    ///////////////////////////////////////沟子过程尾///////////////////////////////////返回控制端过程
    procedure TfrmExecute.Info2Ctrlr(sCode, sAcctName, sStatus, sCnttCode, sNum, sPrice: string);
    var
      s: string;
    begin
      s := g_sTrmnID + '@@' + sCode + '@@' + sAcctName + '@@' + sStatus + '@@' +
       sCnttCode + '@@' + sNum + '@@' + sPrice;
    if not (sAcctName = ' ') then g_slRet2Ctrl.Add(s);
      s := 'start' + s + 'end';
      if Assigned(g_sck) and g_sck.Active then g_sck.Socket.SendText(s);
    end;procedure TfrmExecute.UpdateConnectionIndicator(bConnected: boolean);
    begin
    if bConnected then begin
        lblCnn.Caption := '已连通';
        lblCnn.Color := clBlack;
        lblCnn.Font.Color := clRed;
        aniGlobal.Active := True;
       end
      else begin
        lblCnn.Caption := '未连通';
        lblCnn.Font.Color := clBlue;
        lblCnn.Color := clRed;
        aniGlobal.Active := False;
      end;
    end;procedure TfrmExecute.ClientSocketError(Sender: TObject;
      Socket: TCustomWinSocket; ErrorEvent: TErrorEvent; var ErrorCode: Integer);
    begin
      ErrorCode := 0;
    end;procedure TfrmExecute.CreateSocketConnection();
    begin
    try
      if Assigned(g_sck) and g_sck.Active then Exit;
      g_sck.Free;
      g_sck := nil;
      g_sck := TClientSocket.Create(Application);
      g_sck.Port := 23658;
      g_sck.OnConnect := ClientSocketConnect;
      g_sck.OnRead := ClientSocketRead;
      g_sck.OnError := ClientSocketError;
      g_sck.Address := sIPAddrCtrl;
      g_sck.Active := True;
    finally
    end;
    end;procedure TfrmExecute.ClientSocketConnect(Sender: TObject; Socket: TCustomWinSocket);
    begin
      //如果内部网络断开,当Socket再次连上时,发送连通消息,以正确反映执行端的连接状态
      Info2Ctrlr(_, _, 'report', _, _, _);
    end;procedure TfrmExecute.tmConnectTimer(Sender: TObject);
    begin
      if g_nNoAnswerCounter > 6 then begin
       CreateSocketConnection();
        g_bNetConnected := False;
    end;
    UpdateConnectionIndicator(g_bNetConnected);
      Inc(g_nNoAnswerCounter);
    try
    Info2Ctrlr(_, _, 'connect', 'adsl', _, _);
    finally
    end;
    end;procedure TfrmExecute.ClientSocketRead(Sender: TObject; Socket: TCustomWinSocket);
    var
      s: string;                                       //控制端传来的操作命令字符串
    begin
      s := Socket.ReceiveText;                         //接收控制端传来的操作命令字符串
      if s = 'answer' then begin                      //如果收到的是对询问的回应信息,则
        g_nNoAnswerCounter := 0;
       g_bNetConnected := true;
        exit;                                                   //退出
      end;
      if s = 'exit' then begin                         //如果收到的是'退出'指令,则
        bCloseProgram := True;
        Application.Terminate;                                  //终止执行端程序
        exit;                                                   //退出
      end;
      ParseCommand(s);                              //对指令串进行解析
    end;//分解命令字符串的各部分,并分析其有效性
    procedure ParseCommand(sCommand: string);
    const
      nNUM_DELI = 13 + 1;                                       //命令字符串中'@@'的个数
    var
      i, nDeli, len, nCommand: Integer;
      StartPos, EndPos: Integer;
      sCmdArray: array of string;
      sCmd, sTmpCmd: string;
      sZLCode, sOpNumber, sSystemNo, sClientNo: string;
      tmpZhName: string;
      nLocDeli: array[1..nNUM_DELI] of Integer;
      zlRcvStatement: TZLRecord;
    begin
      sTmpCmd := Trim(sCommand);
      SetLength(sCmdArray, 0);
      while True do begin
        StartPos := Pos('start', sTmpCmd);
        if StartPos <= 0 then break;                            //对该指令串不作处理
        EndPos := Pos('end', sTmpCmd);
        if EndPos <= 0 then break;                              //对该指令串不作处理
        if EndPos <= StartPos then break;                       //对该指令串不作处理
        SetLength(sCmdArray, Length(sCmdArray) + 1);
        sCmdArray[Length(sCmdArray) - 1] := Copy(sTmpCmd, StartPos + 5, EndPos - StartPos - 5);
        Delete(sTmpCmd, 1, EndPos + 2);
      end;
      for nCommand := 0 to Length(sCmdArray) - 1 do begin
        sCmd := sCmdArray[nCommand];
        len := Length(sCmd);
        nDeli := 0;
        //取得命令字串中分隔符的位置及个数
        i := 1;
        while i <= len do begin
          if (sCmd[i] = '@') and (sCmd[i + 1] = '@') then begin
            inc(nDeli);
            if nDeli <= nNUM_DELI then nLocDeli[nDeli] := i;
            inc(i);
          end;
          inc(i);
        end;
        if nDeli <> nNUM_DELI then begin                   //如果分隔符个数不等于指定数,则
          frmExecute.Info2Ctrlr(sCmd, _, 'invalid', _, _, _);
          Continue;
        end;
        sZLCode := LowerCase(Trim(Copy(sCmd, 1, nLocDeli[1] - 1)));
        //从命令字串中截取指令编码部分
        if sZLCode = '' then sZLCode := ' ';
        sSystemNo := LowerCase(Trim(Copy(sCmd, nLocDeli[2] + 2, nLocDeli[3] - nLocDeli[2] - 2))); //从命令字串中截取系统编号部分
        sClientNo := Trim(Copy(sCmd, nLocDeli[5] + 2, nLocDeli[6] - nLocDeli[5] - 2));
        tmpZhName := Trim(Copy(sCmd, nLocDeli[12] + 2, nLocDeli[13] - nLocDeli[12] - 2)); //取得帐户名
        if (sSystemNo <> 'jingxin') and (sSystemNo <> 'guotong')
          and (sSystemNo <> 'julin') and (sSystemNo <> 'pa18') and (sSystemNo <> 'minfa')
          and (sSystemNo <> 'gtja') and (sSystemNo <> 'feihu') and (sSystemNo <> 'tqzq')
          and (sSystemNo <> 'haitong') and (sSystemNo <> 'guangfa') and (sSystemNo <> 'guoxin')
          and (sSystemNo <> 'feihu') then begin
          //qj  待定                                //如果命令字串中要求的交易系统软件终端未安装则
          frmExecute.Info2Ctrlr(sZLCode, tmpZhName, 'invalid', _, _, _);
          Continue;
        end;
        sOpNumber := LowerCase(Trim(Copy(sCmd, nLocDeli[7] + 2, nLocDeli[8] - nLocDeli[7] - 2))); //从命令字串中截取操作编号部分    //对命令字串中的操作编码分析,判断是否为已定义的操作编码之一
        if (sOpNumber <> 'buy') and (sOpNumber <> 'sell') and (sOpNumber <> 'chedan')
          and (sOpNumber <> 'yecx') and (sOpNumber <> 'ygcx') and (sOpNumber <> 'cjcx') then begin //如果不是已定义的操作编码则退出
          frmExecute.Info2Ctrlr(sZLCode, tmpZhName, 'invalid', _, _, _);
          Continue;
        end;
        frmExecute.Info2Ctrlr(sZLCode, tmpZhName, 'valid', _, _, _);
        //向控制端发送合法信息    //指令串合法,将各部分分解出来,赋予指令纪录,并写入指令缓存表
        with zlRcvStatement do begin
          StrPCopy(ZLCode, sZLCode);
          try
            Priority := strtoint(Trim(Copy(sCmd, nLocDeli[1] + 2, nLocDeli[2] - nLocDeli[1] - 2)));
          except
            Priority := 3;                                      //默认3
          end;
          StrPCopy(SystemNo, sSystemNo);
          StrPCopy(YuanJianNo, Trim(Copy(sCmd, nLocDeli[3] + 2, nLocDeli[4] - nLocDeli[3] - 2)));
          StrPCopy(YuanJianPassword, Trim(Copy(sCmd, nLocDeli[4] + 2, nLocDeli[5] - nLocDeli[4] - 2)));      StrPCopy(GuDongCode, sClientNo);
          ///////////盛润金地营业部的深市股东代码长度为10位,需要在传过来的股东代码前加'02'/////////////////////
          if (StockJobber = '国泰金地') and (Length(StrPas(GuDongCode)) = 8) then
            StrPCopy(GuDongCode, '02' + StrPas(GuDongCode));      StrPCopy(GuDongPassword, Trim(Copy(sCmd, nLocDeli[6] + 2, nLocDeli[7] - nLocDeli[6] - 2)));
          StrPCopy(CaoZuoNo, sOpNumber);
          StrPCopy(StockCode, Trim(Copy(sCmd, nLocDeli[8] + 2, nLocDeli[9] - nLocDeli[8] - 2)));
          StrPCopy(StockCount, Trim(Copy(sCmd, nLocDeli[9] + 2, nLocDeli[10] - nLocDeli[9] - 2)));
          StrPCopy(StockPrice, Trim(Copy(sCmd, nLocDeli[10] + 2, nLocDeli[11] - nLocDeli[10] - 2)));
          StrPCopy(StockJobber, Trim(Copy(sCmd, nLocDeli[11] + 2, nLocDeli[12] - nLocDeli[11] - 2)));
          StrPCopy(AccountName, tmpZhName);      //////////////////////////////////////////////////////////////////////////////////////////////////////
          PerformTime := Time + StrToInt(Trim(Copy(sCmd, nLocDeli[13] + 2, nLocDeli[14] - nLocDeli[13] - 2))) / (24 * 60 * 60);
          StrPCopy(StockKind, Trim(Copy(sCmd, nLocDeli[14] + 2, Length(sCmd) - nLocDeli[13] - 1)));
        end;
        ZLTable.AppendNewRecord(zlRcvStatement);                //写入指令缓存表
        with frmExecute.sgrdTask, zlRcvStatement do begin
          if Cells[5, 1] <> '' then RowCount := RowCount + 1;
          Cells[0, RowCount - 1] := StrPas(ZLCode);
          Cells[1, RowCount - 1] := inttostr(Priority);
          Cells[2, RowCount - 1] := StrPas(SystemNo);
          Cells[3, RowCount - 1] := StrPas(AccountName);
          Cells[4, RowCount - 1] := StrPas(GuDongCode);
          Cells[5, RowCount - 1] := StrPas(CaoZuoNo);
          Cells[6, RowCount - 1] := StrPas(StockCode);
          Cells[7, RowCount - 1] := StrPas(StockCount);
          Cells[8, RowCount - 1] := StrPas(StockPrice);
          Cells[9, RowCount - 1] := StrPas(StockJobber);
          Cells[10, RowCount - 1] := TimeToStr(Time);
        end;
      end;
    end;
    //在创建窗体的时候,初始化系统参数//////////////////////////////////////
    procedure TfrmExecute.FormCreate(Sender: TObject);
    var
      GridTable: TGridClass;
      SetupIni: TIniFile;
      GridSetup: ReturnRecord;
      i: integer;
      FilePath: string;
      zlRcv: TZLRecord;
    begin
    btnStop.Enabled := False;
      btnStartUp.Enabled := True;
      btnExit.Enabled := True;
      btnSetup.Enabled := True;
      g_bNetConnected := false;  lblFlex.Caption := '';
    frmExecute.Caption := '交易代理';{$IFDEF Debug}
    AssignFile(LogFile, 'Debug.log');
    {$ENDIF}  SetupIni := TIniFile.Create(ExtractFilePath(Application.ExeName) + '\' + 'syssetup.ini');
    //  ShenYunAppname := SetupIni.ReadString('AppPath', 'ShenYunAppname', '');
    //  JingXinAppname := SetupIni.ReadString('AppPath', 'JingXinAppname', '');
     // Feihu :=SetupIni.ReadString('AppPath' , 'Feihu' ,'');                         //qj
      //GuoTong := SetupIni.ReadString('AppPath', 'GuoTong', '');
     // JuLin := SetupIni.ReadString('AppPath', 'JuLin', '');
     // MinFa := SetupIni.ReadString('AppPath', 'MinFa', '');
    //  PingAnAppname := SetupIni.ReadString('AppPath', 'PingAnAppname', '');
    //  GuangFaAppname := SetupIni.ReadString('AppPath', 'GuangFaAppname', '');
     // sGFa := SetupIni.ReadString('AppPath', 'GFa', '');
     // sHait := SetupIni.ReadString('AppPath', 'Hait', '');
     // guoxin := SetupIni.ReadString('AppPath', 'guoxin', '');
     // sPA18 := SetupIni.ReadString('AppPath', 'PA18', '');
     // sTequzq := SetupIni.ReadString('AppPath', 'Tequzq', '');  sIPAddrCtrl := SetupIni.ReadString('WinSocket', 'IPAddrCtrl', '127.0.0.1');
      g_sTrmnID := SetupIni.ReadString('WinSocket', 'TrmnID', '1'); //如未设置,则默认为第一执行端
      SetupIni.Free;
      lblTerminalID.Caption := g_sTrmnID;  //变量赋初始值
      bCloseProgram := False;
      g_hProcessId := 0;
      //SetLength(sLVContent, 0);  //对保存接收指令和已执行完指令的StringGrid初始化
      GridTable := TGridClass.Create(ExtractFilePath(Application.ExeName) + '\' + 'GridSetup.dat');
      GridTable.ReadColWidth(0, GridSetup);
      if GridSetup.ColsRead > 0 then
        with sgrdTask do begin
          for i := 0 to Min(GridSetup.ColsRead, ColCount) - 1 do ColWidths[i] := GridSetup.ColsWidth[i];
        end;
      GridTable.ReadColWidth(1, GridSetup);
      GridTable.ReadColWidth(2, GridSetup);
      if GridSetup.ColsRead > 0 then
        with sgrdXcuting do begin
          for i := 0 to Min(GridSetup.ColsRead, ColCount) - 1 do ColWidths[i] := GridSetup.ColsWidth[i];
        end;
      GridTable.ReadColWidth(3, GridSetup);
      GridTable.Free;  with sgrdTask do begin
        Cells[0, 0] := '指令编码';
        Cells[1, 0] := '优先权';
        Cells[2, 0] := '系统编号';
        Cells[3, 0] := '帐户名称';
        Cells[4, 0] := '股东代码';
        Cells[5, 0] := '操作类型';
        Cells[6, 0] := '股票代码';
        Cells[7, 0] := '委托股数';
        Cells[8, 0] := '委托价格';
        Cells[9, 0] := '证券公司';
        Cells[10, 0] := '到达时间';
      end;  with sgrdXcuting do begin
        Cells[0, 0] := '指令编码';
        Cells[1, 0] := '优先权';
        Cells[2, 0] := '系统编号';
        Cells[3, 0] := '帐户名称';
        Cells[4, 0] := '股东代码';
        Cells[5, 0] := '操作类型';
        Cells[6, 0] := '股票代码';
        Cells[7, 0] := '委托股数';
        Cells[8, 0] := '委托价格';
        Cells[9, 0] := '证券公司';
      end;//  DisplayZxRecord;//显示指令执行纪录
      nPriorTime := 0;
      ZLTable := TZLData.Create(ExtractFilePath(Application.ExeName), 'ZLTable.dat'); //初始化指令缓存表类
      ZxTable := TPerformTable.Create(ExtractFilePath(Application.ExeName), 'ZXTable.dat'); //初始化指令执行纪录表
      //将指令表中现有纪录显示出来
      with ZLTable, sgrdTask do begin
        for i := 0 to RecordCount - 1 do begin
          GetOneRecord(i, zlRcv);
          if Cells[5, 1] <> '' then RowCount := RowCount + 1;
          Cells[0, RowCount - 1] := StrPas(zlRcv.ZLCode);
          Cells[1, RowCount - 1] := inttostr(zlRcv.Priority);
          Cells[2, RowCount - 1] := StrPas(zlRcv.SystemNo);
          Cells[3, RowCount - 1] := StrPas(zlRcv.AccountName);
          Cells[4, RowCount - 1] := StrPas(zlRcv.GuDongCode);
          Cells[5, RowCount - 1] := StrPas(zlRcv.CaoZuoNo);
          Cells[6, RowCount - 1] := StrPas(zlRcv.StockCode);
          Cells[7, RowCount - 1] := StrPas(zlRcv.StockCount);
          Cells[8, RowCount - 1] := StrPas(zlRcv.StockPrice);
          Cells[9, RowCount - 1] := StrPas(zlRcv.StockJobber);
          Cells[10, RowCount - 1] := '';
        end;
        if RecordCount > 0 then btnDelTask.Enabled := True;
      end;//  g_RetMsg := TReturnMsg.Create(ExtractFilePath(Application.ExeName), 'ReturnMsg.dat'); //初始化指令缓存表类
      //三个Animate载入文件
      FilePath := ExtractFilePath(Application.ExeName);
      aniDigital.FileName := FilePath + '\' + 'Count24.avi';
      aniGlobal.FileName := FilePath + '\' + 'globe.avi';  LoadDll16;
      bProbeInstalled := False;
      slTextOut := TStringList.Create;
      slXTextOut := TStringList.Create;
    end;procedure TfrmExecute.btnStartUpClick(Sender: TObject);
    var
      zl: TZLRecord;                                            //将要执行的指令
      i, nSec, nOpCode: integer;
      rec: TPerformRecord;
    begin
    lstRet.Clear;
      lstGet.Clear;
      lblFlex.Caption := '';
    tmConnect.Enabled := True;
      btnSetup.Enabled := false;
      btnStartUp.Enabled := False;
      btnStartUp.default := False;
      btnStop.Enabled := True;
      btnStop.default := True;
      g_bNetConnected := true;
      g_bButtonPushed := True;  CreateSocketConnection();
      bCloseProgram := False;
      while not bCloseProgram do begin
      UpdateConnectionIndicator(g_bNetConnected);
        if g_bCurrTaskDeleted then begin
          with sgrdTask do begin
            for i := 2 to RowCount - 1 do Rows[i - 1] := Rows[i];
            if RowCount > 2 then RowCount := RowCount - 1
            else Rows[1].Clear;
          end;
        end;
        Application.HandleMessage;
        if nPriorTime > 0 then begin
          nSec := Ceil((GetTickCount - nPriorTime) / 1000);     //得到上一指令执行的秒数      nOpCode := 0;
          if (zlPrior.CaoZuoNo = 'buy') then nOpCode := 1
          else if (zlPrior.CaoZuoNo = 'sell') then nOpCode := 2
          else if (zlPrior.CaoZuoNo = 'chedan') then nOpCode := 3
          else if (zlPrior.CaoZuoNo = 'cjcx') then nOpCode := 4
          else if (zlPrior.CaoZuoNo = 'yecx') then nOpCode := 5
          else if (zlPrior.CaoZuoNo = 'ygcx') then nOpCode := 6;
          if nOpCode > 0 then begin
            g_slRet2Ctrl.Clear;
            ShowReturnText();
            rec.Date := Date;
            rec.SystemNo := zlPrior.SystemNo;
            rec.CaoZuoCode := nOpCode;
            rec.CaoZuoName := sOPR_NAME[nOpCode];
            rec.SuccessFail := bPriorZlSuccess;
            rec.HaoShi := nSec;
            ZxTable.AppendRecord(rec);
            ZxTable.Post;
          end;
        end;
        if ZLTable.RecordCount > 0 then begin
          ZLTable.GetFirstTask(zl);                             //得到优先权最高的那条指令
          g_bCurrTaskDeleted := false;
        end;
        if (ZLTable.RecordCount <= 0) or (zl.PerformTime > Time) then begin //如果指令缓存表为空,则不作处理,开始下一次循环
          with sgrdXcuting do begin                             //如果显示正在执行的指令的网格不为空,则清空
            if Cells[5, 1] <> '' then for i := 0 to ColCount - 1 do Cells[i, 1] := '';
          end;
          if aniDigital.Active then aniDigital.Active := False;     //停止转动显示牌
          zlPrior.CaoZuoNo := '';
          nPriorTime := 0;
          Continue;
        end;
        Application.HandleMessage;
        with sgrdXcuting do begin
          Cells[0, 1] := StrPas(zl.ZLCode);
          Cells[1, 1] := inttostr(zl.Priority);
          Cells[2, 1] := StrPas(zl.SystemNo);
          Cells[3, 1] := StrPas(zl.AccountName);
          Cells[4, 1] := StrPas(zl.GuDongCode);
          Cells[5, 1] := StrPas(zl.CaoZuoNo);
          Cells[6, 1] := StrPas(zl.StockCode);
          Cells[7, 1] := StrPas(zl.StockCount);
          Cells[8, 1] := StrPas(zl.StockPrice);
          Cells[9, 1] := StrPas(zl.StockJobber);
        end;
        nPriorTime := GetTickCount;
        bPriorZlSuccess := False;
        if not aniDigital.Active then aniDigital.Active := True;
        zlPrior := zl;
      /////////////调用Dll///////////////
      { Load the DLL and get all the procedure addresses. }  if CurrSys.SysName <>zl.SystemNo   then
        begin
        if Assigned(CurrSys.CloseSystem) then
          CurrSys.CloseSystem;
        FreeLibrary (CurrSys.hCurr);
        CurrSys.SysName:=zl.SystemNo ;
        CurrSys.hCurr := LoadLibrary(PChar('C:\DLLS\'+CurrSys.SysName+'.'+'dll'));
        CurrSys.IsStartUpSuccess:=(GetProcAddress(CurrSys.hCurr,'IsStartUpSuccess'));
        CurrSys.TradeBuyFunc:= (GetProcAddress(CurrSys.hCurr, 'TradeBuyFunc'));
        CurrSys.TradeSellFunc:=(GetProcAddress(CurrSys.hCurr, 'TradeSellFunc'));
        CurrSys.TradeChedanFunc:=(GetProcAddress(CurrSys.hCurr, 'TradeChedanFunc'));
        CurrSys.TradeQueryStockFunc:=(GetProcAddress(CurrSys.hCurr, 'TradeQueryStockFunc'));
        CurrSys.TradeQueryFundsFunc:=(GetProcAddress(CurrSys.hCurr, Pointer(3)));
        CurrSys.TradeQueryOrderFunc:=(GetProcAddress(CurrSys.hCurr, 'TradeQueryOrderFunc'));
        end;
        CurrSys.IsStartUpSuccess(zl) ;
        if zl.CaoZuoNo ='buy' then begin
        if zl.SystemNo =CurrSys.SysName then
          CurrSys.TradeBuyFunc(zl);
          end
        else if zl.CaoZuoNO='sell' then begin
        if zl.SystemNo =CurrSys.SysName then
          CurrSys.TradeSellFunc(zl);
          end
        else if zl.CaoZuoNo='chedan' then begin
        if zl.SystemNo =CurrSys.SysName then
          CurrSys.TradeChedanFunc(zl);
          end
        else if zl.CaoZuoNo='yecx' then begin
        if zl.SystemNo =CurrSys.SysName then
          CurrSys.TradeQueryFundsFunc(zl);
          end
        else if zl.CaoZuoNo='ygcx' then begin
        if zl.SystemNo =CurrSys.SysName then
          CurrSys.TradeQueryStockFunc(zl);
          end
        else if zl.CaoZuoNo='cjcx' then begin
        if zl.SystemNo =CurrSys.SysName then
          CurrSys.TradeQueryOrderFunc(zl);
          end;
        end;  /////////////////////////////////////////////////////////////////////// {   if (zl.CaoZuoNo = 'buy')  then begin
          if zl.SystemNo = 'HEXIN_FEIHU.DLL' then hexinFeihu.TradeBuyFunc(zl);    end    else if zl.CaoZuoNo = 'sell' then begin
          if zl.SystemNo ='HEXIN_FEIHU.DLL' then hexinFeihu.TradeSellFunc(zl);
        end
        else if zl.CaoZuoNo = 'chedan' then begin
    if zl.SystemNo = 'HEXIN_FEIHU.DLL' then hexinFeihu.TradeChedanFunc(zl);    end
        else if zl.CaoZuoNo = 'yecx' then begin
          if zl.SystemNo = 'HEXIN_FEIHU.DLL' then hexinFeihu.TradeQueryFundsFunc(zl);    end
        else if zl.CaoZuoNo = 'ygcx' then begin
          if zl.SystemNo = 'HEXIN_FEIHU.DLL' then  hexinFeihu.TradeQueryStockFunc(zl);    end
        else if zl.CaoZuoNo = 'cjcx' then begin
          if zl.SystemNo = 'HEXIN_FEIHU.DLL' then hexinFeihu.TradeQueryOrderFunc(zl);    end
        else
          if not g_bCurrTaskDeleted then g_bCurrTaskDeleted := ZLTable.DelFirstTask;   frmExecute.ShowReturnText();
      end; }
    end;/////////调用系统设置界面////////////////////////////
    procedure TfrmExecute.btnSetupClick(Sender: TObject);
    begin
      frmSysSetup := TfrmSysSetup.Create(Application);
      frmSysSetup.ShowModal;
      frmSysSetup.Free;
    end;procedure TfrmExecute.btnLogKeyDown(Sender: TObject; var Key: Word;
      Shift: TShiftState);
    begin
      if Key = vk_F1 then
        Application.HelpContext(2);
    end;
    procedure TfrmExecute.sgrdTaskDrawCell(Sender: TObject; ACol, ARow: Integer;
      Rect: TRect; State: TGridDrawState);
    var
      tmpLeft, tmpTop: integer;
      tmpWidth: integer;
      TextToOut: string;
    begin
      with Sender as TStringGrid do begin
        if gdFixed in State then
          Canvas.Brush.Color := clBtnFace                       //设固定行底色
        else if (Sender = sgrdTask) and (ARow = Row) and (btnDelTask.Enabled) then
          Canvas.Brush.Color := clAqua
        else
          Canvas.Brush.Color := Color;
        Canvas.FillRect(Rect);
        Canvas.Font := Font;
        if ARow > 0 then
          Canvas.Font.Name := 'MS Sans Serif';
        TextToOut := Cells[ACol, ARow];
        tmpWidth := Canvas.TextWidth(TextToOut);
        while tmpWidth > (Rect.Right - Rect.Left) do begin
          Delete(TextToOut, Length(TextToOut) - 1, 2);
          tmpWidth := Canvas.TextWidth(TextToOut);
        end;
        tmpLeft := (((Rect.Right - Rect.Left) - tmpWidth) div 2) + Rect.Left;
        tmpTop := (((Rect.Bottom - Rect.Top) - Canvas.TextHeight(Cells[ACol, ARow])) div 2) + Rect.Top;
        Canvas.TextOut(tmpLeft, tmpTop, TextToOut);
      end;
    end;procedure TfrmExecute.FormClose(Sender: TObject; var Action: TCloseAction);
    var
      GridTable: TGridClass;
      WidthToSave: array[0..128] of Word;
      i: integer;
    begin
      bCloseProgram := True;
      tmConnect.Enabled := False;  GridTable := TGridClass.Create(ExtractFilePath(Application.ExeName) + '\' + 'GridSetup.dat');
      with sgrdTask do begin
        for i := 0 to ColCount - 1 do WidthToSave[i] := ColWidths[i];
        GridTable.SaveColWidth(0, WidthToSave, ColCount);
      end;
      with sgrdXcuting do begin
        for i := 0 to ColCount - 1 do WidthToSave[i] := ColWidths[i];
        GridTable.SaveColWidth(2, WidthToSave, ColCount);
      end;  GridTable.Free;
     // if g_bHookInstalled then g_bHookInstalled := not UninstallListviewHook; //卸载钩子
    end;{
    procedure TfrmExecute.btnLogClick(Sender: TObject);
    begin
      frmZxRecordEdit := TfrmZxRecordEdit.Create(Application);
      frmZxRecordEdit.ShowModal;
      frmZxRecordEdit.Free;
    end;
    }procedure TfrmExecute.btnDelTaskClick(Sender: TObject);
    var
      i: integer;
    begin
      ZLTable.DeleteOneRecord(sgrdTask.Row - 1);
      with sgrdTask do begin
        for i := 2 to RowCount - 1 do Rows[i - 1] := Rows[i];
        if RowCount > 2 then RowCount := RowCount - 1
        else Rows[1].Clear;
      end;
      if sgrdTask.Cells[5, 1] = '' then begin
        btnDelTask.Enabled := False;
        sgrdTask.Repaint;
      end;
    end;procedure TfrmExecute.sgrdTaskSelectCell(Sender: TObject; ACol,
      ARow: Integer; var CanSelect: Boolean);
    var
      co: Integer;
    begin
      with TStringGrid(Sender) do
        for co := 0 to ColCount - 1 do begin
          Cells[co, Row] := Cells[co, Row];
          Cells[co, ARow] := Cells[co, ARow];
        end;
    end;
    procedure TfrmExecute.FormDestroy(Sender: TObject);
    begin
      if Assigned(ZxTable) then ZxTable.Free;
      if Assigned(ZlTable) then ZLTable.Free;
    end;procedure TfrmExecute.btnExitClick(Sender: TObject);
    begin
      Close;
      Application.Terminate;
    end;procedure TfrmExecute.FormKeyDown(Sender: TObject; var Key: Word;
      Shift: TShiftState);
    begin
    if Key = VK_escape then Close;
    end;procedure TfrmExecute.btnStopClick(Sender: TObject);
    begin
      Info2Ctrlr(_, _, 'disconnect', _, _, _);
      g_bButtonPushed := False;
      g_bNetConnected := false;
      tmConnect.Enabled := False;
      bCloseProgram := True;
      btnSetup.Enabled := True;
      btnStartUp.Enabled := True;
      btnStartUp.Default := True;
      btnStop.Enabled := False;
      btnStop.Default := False;
      aniDigital.Active := False;     //停止转动显示牌
      aniGlobal.Active := False;
     // if g_bHookInstalled then g_bHookInstalled := not UninstallListviewHook; //卸载钩子
      if sgrdTask.Cells[5, 1] <> '' then btnDelTask.Enabled := True;
      UpdateConnectionIndicator(g_bNetConnected);
      if not Assigned(g_sck) then Exit;
      g_sck.Free;
      g_sck := nil;
    end;procedure TfrmExecute.ShowReturnText();
    var
    i: Integer;
    begin
    for i := 0 to g_slRet2Ctrl.Count - 1 do
       lstRet.Items.Add(g_slRet2Ctrl.Strings[i]);
    end;procedure TfrmExecute.ShowProberText(nCols: integer);
    var
    i, j, nRows: Integer;
      s: string;
    begin
    lstGet.Clear;
    nRows := g_slProberGet.Count div nCols;
    for i := 0 to nRows - 1 do begin
       s := '';
       for j := 0 to nCols - 2 do begin
          s := s + g_slProberGet.Strings[i * ncols + j] + ' ';
        end;
        lstGet.Items.Add(s);
      end;
    end;procedure TfrmExecute.ShowFlexHandle(sFlexHandle: string);
    begin
      lblFlex.Caption := 'FlexGrid句柄:' + sFlexHandle;
    end;end.
      

  5.   

    我有一个dLL和EXE相互调用(EXE调用DLL的procedure时被调用的DLL的procedure调用EXE的procedure)的源代码,要的话可以发邮件到[email protected]
      

  6.   

    給我也發一分:
     [email protected]
    在此先谢谢 了! 
      

  7.   

    用interface,做回调
    参考COM