unit iac_call; interface implementation uses windows, messages, commctrl, awkservices, common, wrapper, memini, iac_global, global, m_api, dbsettings, mirutils; {$include i_cnst_call.inc} {$resource iac_call.res} const MaxArgCount = 8; MaxArgNameLen = 32; const API_FUNCTION_FILE:pAnsiChar = 'plugins\services.ini'; namespace = 'Function'; const opt_dllname = 'dllname'; opt_funcname = 'funcname'; opt_argcount = 'argcount'; opt_restype = 'restype'; opt_argf = 'argtype'; opt_argn = 'argname'; opt_argv = 'argvalue'; type tCallAction = class(tBaseAction) private dllname:pAnsiChar; funcname:pAnsiChar; restype:dword; argcount:integer; argf:array [0..MaxArgCount-1] of dword; argv:array [0..MaxArgCount-1] of uint_ptr; argn:array [0..MaxArgCount-1,0..MaxArgNameLen-1] of AnsiChar; public constructor Create(uid:dword); destructor Destroy; override; function DoAction(var WorkData:tWorkData):LRESULT; override; procedure Save(node:pointer;fmt:integer); override; procedure Load(node:pointer;fmt:integer); override; end; var storage:pointer; const ACF_CDECL = $00000001; ACF_CACHE_NOW = $00000002; ACF_CACHE_MACRO = $00000004; type sp0 = function:int_ptr; stdcall; sp1 = function(arg1:int_ptr):int_ptr; stdcall; sp2 = function(arg1,arg2:uint_ptr):int_ptr; stdcall; sp3 = function(arg1,arg2,arg3:uint_ptr):int_ptr; stdcall; sp4 = function(arg1,arg2,arg3,arg4:uint_ptr):int_ptr; stdcall; sp5 = function(arg1,arg2,arg3,arg4,arg5:uint_ptr):int_ptr; stdcall; sp6 = function(arg1,arg2,arg3,arg4,arg5,arg6:uint_ptr):int_ptr; stdcall; sp7 = function(arg1,arg2,arg3,arg4,arg5,arg6,arg7:uint_ptr):int_ptr; stdcall; sp8 = function(arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8:uint_ptr):int_ptr; stdcall; cp0 = function:int_ptr; cdecl; cp1 = function(arg1:uint_ptr):int_ptr; cdecl; cp2 = function(arg1,arg2:uint_ptr):int_ptr; cdecl; cp3 = function(arg1,arg2,arg3:uint_ptr):int_ptr; cdecl; cp4 = function(arg1,arg2,arg3,arg4:uint_ptr):int_ptr; cdecl; cp5 = function(arg1,arg2,arg3,arg4,arg5:uint_ptr):int_ptr; cdecl; cp6 = function(arg1,arg2,arg3,arg4,arg5,arg6:uint_ptr):int_ptr; cdecl; cp7 = function(arg1,arg2,arg3,arg4,arg5,arg6,arg7:uint_ptr):int_ptr; cdecl; cp8 = function(arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8:uint_ptr):int_ptr; cdecl; //----- Support functions ----- //----- Object realization ----- constructor tCallAction.Create(uid:dword); begin inherited Create(uid); restype:=ACF_TYPE_NUMBER; argcount:=0; dllname :=nil; funcname:=nil; end; destructor tCallAction.Destroy; begin mFreeMem(dllname); mFreeMem(funcname); inherited Destroy; end; function tCallAction.DoAction(var WorkData:tWorkData):LRESULT; var hDLL:THANDLE; pp:pointer; subst:tSubstData; res:LRESULT; largv:array [0..MaxArgCount-1] of uint_ptr; i:integer; loaded:bool; begin result:=0; if (dllname =nil) or (dllname^ =#0) or (funcname=nil) or (funcname^=#0) then begin // clear last result? exit; end; loaded:=false; hDLL:=GetModuleHandleA(dllname); if hDLL=0 then begin loaded:=true; hDLL:=LoadLibraryA(dllname); end; // hDLL:=GetDllHandle(dllname); if hDLL<>0 then begin pp:=GetProcAddress(hDLL,funcname); if pp<>nil then begin subst.Parameter :=WorkData.Parameter; subst.LastResult:=WorkData.LastResult; case WorkData.ResultType of rtInt : subst.ResultType:=ACF_TYPE_NUMBER; rtWide: subst.ResultType:=ACF_TYPE_UNICODE; {!! rtAnsi: rtUTF8: } end; for i:=0 to argcount-1 do begin largv[i]:=PrepareParameter(argf[i],LPARAM(argv[i]),subst); end; // call function case argcount of 0: begin if (flags and ACF_CDECL)<>0 then res:=cp0(pp) else res:=sp0(pp); end; 1: begin if (flags and ACF_CDECL)<>0 then res:=cp1(pp)(largv[0]) else res:=sp1(pp)(largv[0]); end; 2: begin if (flags and ACF_CDECL)<>0 then res:=cp2(pp)(largv[0],largv[1]) else res:=sp2(pp)(largv[0],largv[1]); end; 3: begin if (flags and ACF_CDECL)<>0 then res:=cp3(pp)(largv[0],largv[1],largv[2]) else res:=sp3(pp)(largv[0],largv[1],largv[2]); end; 4: begin if (flags and ACF_CDECL)<>0 then res:=cp4(pp)(largv[0],largv[1],largv[2],largv[3]) else res:=sp4(pp)(largv[0],largv[1],largv[2],largv[3]); end; 5: begin if (flags and ACF_CDECL)<>0 then res:=cp5(pp)(largv[0],largv[1],largv[2],largv[3],largv[4]) else res:=sp5(pp)(largv[0],largv[1],largv[2],largv[3],largv[4]); end; 6: begin if (flags and ACF_CDECL)<>0 then res:=cp6(pp)(largv[0],largv[1],largv[2],largv[3],largv[4],largv[5]) else res:=sp6(pp)(largv[0],largv[1],largv[2],largv[3],largv[4],largv[5]); end; 7: begin if (flags and ACF_CDECL)<>0 then res:=cp7(pp)(largv[0],largv[1],largv[2],largv[3],largv[4],largv[5],largv[6]) else res:=sp7(pp)(largv[0],largv[1],largv[2],largv[3],largv[4],largv[5],largv[6]); end; 8: begin if (flags and ACF_CDECL)<>0 then res:=cp8(pp)(largv[0],largv[1],largv[2],largv[3],largv[4],largv[5],largv[6],largv[7]) else res:=sp8(pp)(largv[0],largv[1],largv[2],largv[3],largv[4],largv[5],largv[6],largv[7]); end; else res:=0; end; ClearResult(WorkData); // result type processing case restype and ACF_TYPE_MASK of ACF_TYPE_STRING, ACF_TYPE_UNICODE: begin WorkData.ResultType:=rtWide; if (restype and ACF_TYPE_MASK)=ACF_TYPE_STRING then AnsiToWide(pAnsiChar(res),pWideChar(WorkData.LastResult),MirandaCP) else StrDupW(pWideChar(WorkData.LastResult),pWideChar(res)); if (restype and ACF_FLAG_FREEMEM)<>0 then mir_free(pointer(res)); end; ACF_TYPE_NUMBER: begin WorkData.ResultType:=rtInt; WorkData.LastResult:=res; end; (* ACF_TYPE_STRUCT: begin { PostProcess(flags ,lwparam,WorkData); PostProcess(flags2,llparam,WorkData); } end; *) end; for i:=0 to argcount-1 do begin ReleaseParameter(argf[i],LPARAM(largv[i])); end; end; // FreeDllHandle(hDLL); if loaded then FreeLibrary(hDLL); end; end; procedure LoadParam(section:PAnsiChar;flags:dword; var param:pointer); begin case flags of ACF_TYPE_NUMBER, ACF_TYPE_STRING, ACF_TYPE_UNICODE: param:=DBReadUnicode(0,DBBranch,section,nil); ACF_TYPE_STRUCT : param:=DBReadUTF8 (0,DBBranch,section,nil); end; end; procedure tCallAction.Load(node:pointer;fmt:integer); var section: array [0..127] of AnsiChar; pc,p,pd,ppd:pAnsiChar; i:integer; old:boolean; begin inherited Load(node,fmt); case fmt of 0: begin // if no restype setting, then ConvertRresultFlags and old:=true; pc:=StrCopyE(section,pAnsiChar(node)); StrCopy(pc,opt_restype ); restype :=DBReadDWord (0,DBBranch,section,dword(-1)); old:=restype=dword(-1); if old then begin restype:=ConvertResultFlags(flags); end; StrCopy(pc,opt_dllname ); dllname :=DBReadString(0,DBBranch,section); StrCopy(pc,opt_funcname); funcname:=DBReadString(0,DBBranch,section); StrCopy(pc,opt_argcount); argcount:=DBReadByte (0,DBBranch,section); if argcount>0 then begin pd:=nil; for i:=0 to argcount-1 do begin IntToStr(StrCopyE(pc,opt_argn),i); p:=DBReadString(0,DBBranch,section); if (p=nil) or (p^=#0) then begin if pd=nil then pd:=Translate('Argument'); ppd:=StrCopyE(argn[i],pd); ppd^:=' '; inc(ppd); IntToStr(ppd,i+1); end else StrCopy(argn[i],p); mFreeMem(p); if not old then begin LoadParamValue(argf[i],pointer(argv[i]),DBBranch,section); end else begin IntToStr(StrCopyE(pc,opt_argf),i); argf[i]:=DBReadDWord(0,DBBranch,section); argf[i]:=ConvertParamFlags(argf[i]); IntToStr(StrCopyE(pc,opt_argv),i); LoadParam(section,argf[i] and ACF_TYPE_MASK,pointer(argv[i])); end; end; end; end; { 1: begin end; } end; end; procedure tCallAction.Save(node:pointer;fmt:integer); var section: array [0..127] of AnsiChar; pc:pAnsiChar; i:integer; begin inherited Save(node,fmt); case fmt of 0: begin pc:=StrCopyE(section,pAnsiChar(node)); StrCopy(pc,opt_dllname ); DBWriteString(0,DBBranch,section,dllname); StrCopy(pc,opt_funcname); DBWriteString(0,DBBranch,section,funcname); StrCopy(pc,opt_argcount); DBWriteByte (0,DBBranch,section,argcount); StrCopy(pc,opt_restype ); DBWriteDWord (0,DBBranch,section,restype); if argcount>0 then begin for i:=0 to argcount-1 do begin IntToStr(StrCopyE(pc,opt_argn),i); DBWriteString(0,DBBranch,section,argn[i]); SaveParamValue(argf[i],pointer(argv[i]),DBBranch,section); end; end; end; { 1: begin end; } end; end; //----- Dialog realization ----- { IDC_ARGNUM userdata = current item (argument number) IDC_ARGCOUNT userdata = arguments buffer Dialog userdata = parameter control } type peditvalues = ^teditvalues; teditvalues = record argf:array [0..MaxArgCount-1] of dword; argv:array [0..MaxArgCount-1] of uint_ptr; argn:array [0..MaxArgCount-1,0..MaxArgNameLen-1] of AnsiChar; end; function GetArgumentWindow(Dialog:HWND):HWND; begin result:=GetWindowLongPtrW(GetDlgItem(Dialog,IDC_CLOSE_ARG),GWLP_USERDATA); end; function GetResultWindow(Dialog:HWND):HWND; begin result:=GetWindowLongPtrW(GetDlgItem(Dialog,IDC_CLOSE_RES),GWLP_USERDATA); end; function GetEditValues(Dialog:HWND):pointer; begin result:=pointer(GetWindowLongPtrW(GetDlgItem(Dialog,IDC_ARGCOUNT),GWLP_USERDATA)); end; function ChangeArgNumber(Dialog:HWND;cnt:integer=-1):integer; var wnd,wnd1:HWND; tr:bool; pe:peditvalues; i:integer; begin if cnt<0 then cnt:=GetDlgItemInt(Dialog,IDC_ARGCOUNT,tr,false) // cnt:=CB_GetData(GetDlgItem(Dialog,IDC_ARGCOUNT)) else SendMessage(GetDlgItem(Dialog,IDC_ARGCOUNT),CB_SETCURSEL,cnt,0); wnd :=GetArgumentWindow(Dialog); wnd1:=GetDlgItem(Dialog,IDC_ARGNUM); SendMessage(wnd1,CB_RESETCONTENT,0,0); if cnt=0 then begin ShowWindow(wnd ,SW_HIDE); ShowWindow(wnd1,SW_HIDE); end else begin if IsDlgButtonChecked(Dialog,IDC_CLOSE_ARG)<>BST_UNCHECKED then begin ShowWindow(wnd ,SW_SHOW); ShowWindow(wnd1,SW_SHOW); end; pe:=GetEditValues(Dialog); for i:=0 to cnt-1 do begin InsertString(wnd1,i,@pe^.argn[i]); end; SendMessage(wnd1,CB_SETCURSEL,0,0); end; result:=cnt; end; procedure FillTemplates(fwnd:HWND); var p,pp,pz:pAnsiChar; lptr:pointer; i:integer; begin SendMessage(fwnd,CB_RESETCONTENT,0,0); p:=GetSectionList(storage,namespace); pp:=p; i:=0; while p^<>#0 do begin lptr:=SearchSection(storage,p,namespace); pz:=StrScan(p,'$'); if pz=nil then pz:=p-1; // add function if not found if SendMessageA(fwnd,CB_FINDSTRINGEXACT,-1,LParam(pz+1))=CB_ERR then CB_AddStrData(fwnd,pz+1,int_ptr(lptr){not so required}, i); while p^<>#0 do inc(p); inc(p); inc(i); end; FreeSectionList(pp); if i>0 then begin SendMessage(fwnd,CB_SETCURSEL,0,0); end; end; procedure SearchDllByFName(flist,dlist:HWND;idx:integer=-1); var pc,p,pp,pz:pAnsiChar; lptr:pointer; buf:array [0..31] of AnsiChar; buf1:array [0..63] of AnsiChar; i:integer; begin if idx<0 then pc:=GetDlgText(flist,true) else begin pc:=@buf1; SendMessageA(flist,CB_GETLBTEXT,idx,LParam(@buf1)); end; SendMessage(dlist,CB_RESETCONTENT,0,0); p:=GetSectionList(storage,namespace); pp:=p; i:=0; while p^<>#0 do begin lptr:=SearchSection(storage,p,namespace); pz:=StrScan(p,'$'); if (pz<>nil) and (StrCmp(pz+1,pc)=0) then begin // add dll name StrCopy(buf,p,pz-p); CB_AddStrData(dlist,buf,int_ptr(lptr), i); inc(i); end; while p^<>#0 do inc(p); inc(p); end; FreeSectionList(pp); if idx<0 then mFreeMem(pc); if i>0 then SendMessage(dlist,CB_SETCURSEL,0,0); end; procedure FillByTemplate(Dialog:HWND); var buf:array [0..15] of AnsiChar; fwnd,dwnd:HWND; sect:pointer; pe:peditvalues; pc,pd,ppd:pAnsiChar; sel,cnt,i:integer; begin fwnd:=GetDlgItem(Dialog,IDC_LIST_FUNC); dwnd:=GetDlgItem(Dialog,IDC_LIST_DLL); // right now, without manual typing, by selecting only sect:=nil; sel:=SendMessage(dwnd,CB_GETCURSEL,0,0); if sel=CB_ERR then begin sel:=SendMessage(fwnd,CB_GETCURSEL,0,0); if sel<>CB_ERR then sect:=pointer(CB_GetData(fwnd,sel)); end else sect:=pointer(CB_GetData(dwnd,sel)); if sect=nil then exit; // ClearFields if templated found if StrCmp(GetParamSectionStr(sect,'calltype',nil),'cdecl')=0 then begin CheckDlgButton(Dialog,IDC_CDECL,BST_CHECKED); CheckDlgButton(Dialog,IDC_STDCALL,BST_UNCHECKED); end else begin CheckDlgButton(Dialog,IDC_CDECL,BST_UNCHECKED); CheckDlgButton(Dialog,IDC_STDCALL,BST_CHECKED); end; cnt:=GetParamSectionInt(sect,'argcount'); pe:=GetEditValues(Dialog); pd:=nil; for i:=0 to cnt-1 do begin IntToStr(StrCopyE(buf,opt_argn),i+1); pc:=GetParamSectionStr(sect,buf); if (pc=nil) or (pc^=#0) then begin if pd=nil then pd:=Translate('Argument'); ppd:=StrCopyE(pe^.argn[i],pd); ppd^:=' '; inc(ppd); IntToStr(ppd,i+1); end else StrCopy(pe^.argn[i],pc); IntToStr(StrCopyE(buf,opt_argv),i+1); mFreeMem(pe^.argv[i]); StrDup(pAnsiChar(pe^.argv[i]),GetParamSectionStr(sect,buf,'')); pe^.argf[i]:=ACF_FLAG_TEMPLATE; end; ChangeArgNumber(Dialog,cnt); FillParam(GetArgumentWindow(Dialog),pointer(pe^.argv[0])); end; function FillDllName(Dialog:HWND;idc:integer):boolean; var pw:array [0..1023] of WideChar; ppw:pWideChar; begin // mGetMem(pw,1024*SizeOf(WideChar)); ppw:=GetDlgText(Dialog,idc); result:=ShowDlgW(pw,ppw); if result then begin SetDlgItemTextW(Dialog,idc,pw); end; mFreeMem(ppw); // mFreeMem(pw); end; procedure ShowHideBlock(Dialog:HWND;showarg:boolean); var wnd,wnd1:HWND; rc:TRECT; pt:TPOINT; tr:bool; arg,res:integer; begin wnd1:=GetArgumentWindow(Dialog); if showarg then begin arg:=SW_SHOW; res:=SW_HIDE; wnd:=wnd1; end else begin arg:=SW_HIDE; res:=SW_SHOW; wnd:=GetDlgItem(Dialog,IDC_CLOSE_ARG); end; GetWindowRect(wnd,rc); pt.x:=rc.left; pt.y:=rc.bottom; ScreenToClient(Dialog,pt); SetWindowPos(GetDlgItem(Dialog,IDC_CLOSE_RES), HWND_TOP,1,pt.y+2,0,0,SWP_NOZORDER or SWP_NOSIZE); ShowWindow(GetResultWindow(Dialog),res); ShowWindow(GetDlgItem(Dialog,IDC_ARGSTAT ),arg); ShowWindow(GetDlgItem(Dialog,IDC_ARGCOUNT),arg); if GetDlgItemInt(Dialog,IDC_ARGCOUNT,tr,false)=0 then // if CB_GetData(GetDlgItem(Dialog,IDC_ARGCOUNT))=0 then arg:=SW_HIDE; ShowWindow(GetDlgItem(Dialog,IDC_ARGNUM),arg); ShowWindow(wnd1,arg); end; procedure MakeDLLCacheList(wnd:HWND); begin SendMessage(wnd,CB_RESETCONTENT,0,0); InsertString(wnd,0,'Keep to end'); InsertString(wnd,1,'Close immediately'); InsertString(wnd,2,'Close for macro'); SendMessage(wnd,CB_SETCURSEL,0,0); end; procedure ClearFields(Dialog:HWND); begin CheckDlgButton(Dialog,IDC_CDECL ,BST_UNCHECKED); CheckDlgButton(Dialog,IDC_STDCALL,BST_UNCHECKED); {!! CheckDlgButton(Dialog,IDC_DLL_IMM ,BST_UNCHECKED); CheckDlgButton(Dialog,IDC_DLL_MACRO,BST_UNCHECKED); CheckDlgButton(Dialog,IDC_DLL_END ,BST_UNCHECKED); } ClearParamFields (GetArgumentWindow(Dialog)); ClearResultFields(GetResultWindow (Dialog)); ShowHideBlock(Dialog,true); end; function DlgProc(Dialog:HWND;hMessage:uint;wParam:WPARAM;lParam:LPARAM):LRESULT; stdcall; var wnd,wnd1:HWND; buf:array [0..63] of AnsiChar; pc:pAnsiChar; pe:peditvalues; rc:TRECT; pt:TPOINT; tr:bool; i:integer; begin result:=0; case hMessage of WM_DESTROY: begin pe:=GetEditValues(Dialog); for i:=0 to MaxArgCount-1 do begin //?? depends of copying from edit to action ClearParam(pe.argf[i],pe.argv[i]); end; mFreeMem(pe); CloseStorage(storage); end; WM_INITDIALOG: begin //insert additional dialogs CheckDlgButton(Dialog,IDC_CLOSE_ARG,BST_CHECKED); wnd1:=GetDlgItem(Dialog,IDC_CLOSE_ARG); EnableWindow(wnd1,false); wnd:=GetDlgItem(Dialog,IDC_ARGNUM); // count offset from GetWindowRect(wnd,rc); pt.x:=rc.left; pt.y:=rc.bottom; ScreenToClient(Dialog,pt); GetClientRect(wnd1,rc); SetWindowLongPtrW(wnd1,GWLP_USERDATA,CreateParamBlock(Dialog,0,pt.y+2,rc.right)); CheckDlgButton(Dialog,IDC_CLOSE_RES,BST_UNCHECKED); wnd:=GetDlgItem(Dialog,IDC_CLOSE_RES); // count offset from initial pos GetWindowRect(wnd,rc); EnableWindow(wnd,true); pt.x:=rc.left; pt.y:=rc.bottom; ScreenToClient(Dialog,pt); wnd1:=CreateResultBlock(Dialog,0,pt.y+2,rc.right-rc.left, ACF_BLOCK_NOVISUAL or ACF_BLOCK_NOSTRUCT); SetWindowLongPtrW(wnd,GWLP_USERDATA,wnd1); ShowWindow(wnd1,SW_HIDE); mGetMem(pe,SizeOf(teditvalues)); FillChar(pe^,SizeOf(teditvalues),0); SetWindowLongPtrW(GetDlgItem(Dialog,IDC_ARGCOUNT),GWLP_USERDATA,uint_ptr(pe)); // function argument amount list wnd1:=GetDlgItem(Dialog,IDC_ARGCOUNT); SendMessage(wnd1,CB_RESETCONTENT,0,0); for i:=0 to MaxArgCount do begin InsertString(wnd1,i,IntToStr(buf,i)); end; SendMessage(wnd1,CB_SETCURSEL,0,0); // function templates storage:=OpenStorage(API_FUNCTION_FILE); if storage<>nil then begin wnd :=GetDlgItem(Dialog,IDC_LIST_FUNC); FillTemplates(wnd) end; MakeDLLCacheList(GetDlgItem(Dialog,IDC_DLL_CACHE)); TranslateDialogDefault(Dialog); end; WM_ACT_SETVALUE: begin ClearFields(Dialog); with tCallAction(lParam) do begin // set function SetDlgItemTextA(Dialog,IDC_LIST_FUNC,funcname); // sset dll name (semi-auto) SetDlgItemTextA(Dialog,IDC_LIST_DLL ,dllname); // set call type (auto) if (flags and ACF_CDECL)<>0 then CheckDlgButton(Dialog,IDC_CDECL ,BST_CHECKED) else CheckDlgButton(Dialog,IDC_STDCALL,BST_CHECKED); {!! // set dll cache option if (flags and ACF_CACHE_NOW)<>0 then CheckDlgButton(Dialog,IDC_DLL_IMM,BST_CHECKED) else if (flags and ACF_CACHE_MACRO)<>0 then CheckDlgButton(Dialog,IDC_DLL_MACRO,BST_CHECKED) else CheckDlgButton(Dialog,IDC_DLL_END,BST_CHECKED); } if (flags and ACF_CACHE_NOW)<>0 then i:=1 else if (flags and ACF_CACHE_MACRO)<>0 then i:=2 else i:=0; SendMessage(GetDlgItem(Dialog,IDC_DLL_CACHE),CB_SETCURSEL,i,0); // set argument amount // (auto) ChangeArgNumber(Dialog,argcount); if argcount>0 then begin // copy action values to edit values pe:=GetEditValues(Dialog); // need to clear ALL params before? or keep as is? // depends of enabled or disabled arg amount combo for i:=0 to argcount-1 do begin StrCopy(pe^.argn[i],argn[i]); pe^.argf[i]:=DuplicateParam(argf[i],argv[i],pe^.argv[i]); end; wnd1:=GetDlgItem(Dialog,IDC_ARGNUM); SendMessage(wnd1,CB_RESETCONTENT,0,0); for i:=0 to argcount-1 do begin InsertString(wnd1,i,@pe^.argn[i]); end; SendMessage(wnd1,CB_SETCURSEL,0,0); SetParamValue (GetArgumentWindow(Dialog),argf[0],pointer(argv[0])); SetResultValue(GetResultWindow (Dialog),restype); end; end; end; WM_ACT_RESET: begin ClearFields(Dialog); SetDlgItemTextW(Dialog,IDC_LIST_FUNC,nil); SetDlgItemTextW(Dialog,IDC_LIST_DLL ,nil); SendMessage(GetDlgItem(Dialog,IDC_LIST_DLL),CB_RESETCONTENT,0,0); CheckDlgButton(Dialog,IDC_STDCALL,BST_CHECKED); //!! CheckDlgButton(Dialog,IDC_DLL_END,BST_CHECKED); SendMessage(GetDlgItem(Dialog,IDC_DLL_CACHE),CB_SETCURSEL,0,0); ChangeArgNumber(Dialog,0); pe:=GetEditValues(Dialog); pc:=StrCopyE(buf,Translate('Argument')); pc^:=' '; inc(pc); for i:=0 to MaxArgCount-1 do begin IntToStr(pc,i+1); StrCopy(pe^.argn[i],buf); ClearParam(pe.argf[i],pe.argv[i]); end; end; WM_ACT_SAVE: begin with tCallAction(lParam) do begin argcount:=GetDlgItemInt(Dialog,IDC_ARGCOUNT,tr,false); if argcount>0 then begin pe:=GetEditValues(Dialog); // save current argument i:=GetWindowLongPtrW(GetDlgItem(Dialog,IDC_ARGNUM),GWLP_USERDATA); // current saved // i:=CB_GetData(GetDlgItem(Dialog,IDC_ARGNUM)); // current from data GetParamValue(GetArgumentWindow(Dialog),pe^.argf[i],pointer(pe^.argv[i])); // copy edit values to action values for i:=0 to argcount-1 do begin StrCopy(argn[i],pe^.argn[i]); argf[i]:=DuplicateParam(pe^.argf[i],pe^.argv[i],argv[i]); end; end; restype:=GetResultValue(GetResultWindow(Dialog)); if IsDlgButtonChecked(Dialog,IDC_CDECL)<>BST_UNCHECKED then flags:=flags or ACF_CDECL; {!! if IsDlgButtonChecked(Dialog,IDC_DLL_IMM)<>BST_UNCHECKED then flags:=flags or ACF_CACHE_NOW else if IsDlgButtonChecked(Dialog,IDC_DLL_MACRO)<>BST_UNCHECKED then flags:=flags or ACF_CACHE_MACRO; } case SendMessage(GetDlgItem(Dialog,IDC_DLL_CACHE),CB_GETCURSEL,0,0) of 1: flags:=flags or ACF_CACHE_NOW; 2: flags:=flags or ACF_CACHE_MACRO; end; funcname:=GetDlgText(Dialog,IDC_LIST_FUNC,true); dllname :=GetDlgText(Dialog,IDC_LIST_DLL ,true); end; end; WM_COMMAND: begin case wParam shr 16 of BN_CLICKED: begin case loword(wParam) of IDC_DLL: begin if not FillDllName(Dialog,IDC_LIST_DLL) then exit; end; IDC_CLOSE_RES: begin // close buttons EnableWindow(lParam,false); EnableWindow(GetDlgItem(Dialog,IDC_CLOSE_ARG),true); CheckDlgButton(Dialog,IDC_CLOSE_ARG,BST_UNCHECKED); ShowHideBlock(Dialog,false); exit; end; IDC_CLOSE_ARG: begin // close buttons EnableWindow(lParam,false); EnableWindow(GetDlgItem(Dialog,IDC_CLOSE_RES),true); CheckDlgButton(Dialog,IDC_CLOSE_RES,BST_UNCHECKED); ShowHideBlock(Dialog,true); exit; end; end; SendMessage(GetParent(GetParent(Dialog)),PSM_CHANGED,0,0); end; CBN_EDITCHANGE, EN_CHANGE: begin SendMessage(GetParent(GetParent(Dialog)),PSM_CHANGED,0,0); if loword(wParam)=IDC_LIST_FUNC then begin wnd :=GetDlgItem(Dialog,IDC_LIST_FUNC); wnd1:=GetDlgItem(Dialog,IDC_LIST_DLL); SearchDllByFName(wnd,wnd1); end; end; CBN_SELCHANGE: begin case loword(wParam) of IDC_LIST_FUNC: begin // search in templates SendMessage(GetParent(GetParent(Dialog)),PSM_CHANGED,0,0); wnd :=GetDlgItem(Dialog,IDC_LIST_FUNC); wnd1:=GetDlgItem(Dialog,IDC_LIST_DLL); // search this name as part in all ini templates, // fill IDC_LIST_DLL combobox SearchDllByFName(wnd,wnd1,SendMessage(wnd,CB_GETCURSEL,0,0)); FillByTemplate(Dialog); end; IDC_LIST_DLL: begin SendMessage(GetParent(GetParent(Dialog)),PSM_CHANGED,0,0); FillByTemplate(Dialog); end; IDC_ARGNUM: begin pe:=GetEditValues(Dialog); wnd:=GetArgumentWindow(Dialog); // 1 - save old argument value (save as for dialogs?) i:=GetWindowLongPtrW(lParam,GWLP_USERDATA); GetParamValue(wnd,pe^.argf[i],pointer(pe^.argv[i])); // 2 - set new argument value i:=CB_GetData(lParam); SetParamValue(wnd,pe^.argf[i],pointer(pe^.argv[i])); SetWindowLongPtrW(lParam,GWLP_USERDATA,i); end; IDC_ARGCOUNT: begin ChangeArgNumber(Dialog); SendMessage(GetParent(GetParent(Dialog)),PSM_CHANGED,0,0); end; end; end; end; end; WM_HELP: begin result:=1; end; end; end; //----- Export/interface functions ----- var vc:tActModule; function CreateAction:tBaseAction; begin result:=tCallAction.Create(vc.Hash); end; function CreateDialog(parent:HWND):HWND; begin result:=CreateDialogW(hInstance,'IDD_ACTCALL',parent,@DlgProc); end; procedure Init; begin vc.Next :=ModuleLink; vc.Name :='Function call'; vc.Dialog :=@CreateDialog; vc.Create :=@CreateAction; vc.Icon :='IDI_CALL'; ModuleLink :=@vc; end; begin Init; end.