如何提取外部期货交易程序的文本

hbszlhj 2017-07-10 10:38:12
我想提取外部的期货交易软件的2个红色框中文本,spy++获取句柄只能获取整个二级窗口的,红色框部分无法获取句柄,因为分辨率的关系,所以不能采用识别图片的方式
...全文
199 6 打赏 收藏 转发到动态 举报
写回复
用AI写文章
6 条回复
切换为时间正序
请发表友善的回复…
发表回复
hbszlhj 2017-07-14
  • 打赏
  • 举报
回复
引用 5 楼 kithspan 的回复:
期货CTP开放的.把CTP封装一下就有了
谢谢回复,我是想实现文华的联动功能,就是在文华看什么行情,软件跟随这个代码,随时准备下单,我的软件本来就是用ctp接口做的。
kithspan 2017-07-12
  • 打赏
  • 举报
回复
期货CTP开放的.把CTP封装一下就有了
hongss 2017-07-10
  • 打赏
  • 举报
回复
talip1106 2017-07-10
  • 打赏
  • 举报
回复
以下代码是一个hook api的简单例子,你可以参考一下。

library Hook;

uses
  SysUtils,
  Windows,
  Classes,
  ApiDefine in 'ApiDefine.pas',
  APIHook in 'APIHook.pas';

{$R *.res}
var
  HookHandle: HHook;

function HookProc(code:Integer;wparam:WPARAM;lparam:LPARAM):LRESULT;stdcall;
begin
  Result := CallNextHookEx(HookHandle,code,wparam,lparam);
end;

procedure SetHook;stdcall;
begin
  HookHandle := SetWindowsHookEx(WH_GETMESSAGE,@HookProc,HInstance,0);
end;

procedure StopHook;stdcall;
begin
  UnhookWindowsHookEx(HookHandle);
end;

exports
  SetHook name 'SetHook',
  StopHook name 'StopHook';

{已启动就挂上,修改API函数指向}
begin
  API_Hook;
end.


unit APIHook;

interface

uses
  Windows, SysUtils, Classes;

type
  //引入表入口数据结构
  Image_Import_Entry = packed record
    OriginalFirstThunk:DWORD;
    TimeDateStamp:DWORD;
    ForwarderChain:DWORD;
    Name:DWORD;
    FirstThunk:DWORD;
  end;
  PImage_Import_Entry = ^Image_Import_Entry;
  TImportCode = packed record
    JmpCode: Word;
    AddressOfPFun: PPointer;
  end;
  PImportCode = ^TImportCode;

  function GetFunTrueAddress(Code:Pointer):Pointer;
  function ReplaceFunAddress(oldfun:Pointer;newfun:Pointer):Integer;

implementation

//获得实际地址
function GetFunTrueAddress(Code: Pointer): Pointer;
var
   func: PImportCode;
begin
   Result := Code;
   if Code = nil then exit;
   try
      func := code;
      if (func.JmpCode = $25FF) then
      begin
         Result := func.AddressOfPFun^;
      end;
   except
      Result := nil;
   end;
end;

//替换地址
function ReplaceFunAddress(oldfun:Pointer;newfun:Pointer): Integer;
var
   IsDone: TList;
   function ReplaceAddressInModule(hModule: THandle; OldFunc, NewFunc: Pointer): Integer;
   var
      DosHeader: PImageDosHeader;
      NTHeader: PImageNTHeaders;
      ImportDesc: PImage_Import_Entry;
      RVA: DWORD;
      Func: ^Pointer;
      DLL: string;
      f: Pointer;
      written: DWORD;
   begin
      Result := 0;
      DosHeader := Pointer(hModule);
      //已经找过,则退出
      if IsDone.IndexOf(DosHeader) >= 0 then exit;
      IsDone.Add(DosHeader);

      oldfun := GetFunTrueAddress(OldFunc);

      if IsBadReadPtr(DosHeader, SizeOf(TImageDosHeader)) then exit;
      if DosHeader.e_magic <> IMAGE_DOS_SIGNATURE then exit;
      NTHeader := Pointer(Integer(DosHeader) + DosHeader._lfanew);
      //引入表的虚拟地址
      RVA := NTHeader^.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress;

      if RVA = 0 then exit;
      ImportDesc := pointer(integer(DosHeader) + RVA);
      while (ImportDesc^.Name <> 0) do
      begin
        //引入文件名
         DLL := PChar(Integer(DosHeader) + ImportDesc^.Name);
         //获得该DLL的句柄,然后递归查找
         ReplaceAddressInModule(GetModuleHandle(PChar(DLL)), oldfun, newfun);
         //引入函数入口
         Func := Pointer(Integer(DOSHeader) + ImportDesc.FirstThunk);
         //如果函数指针不为空
         while Func^ <> nil do
         begin
           //取得真是地址
            f := GetFunTrueAddress(Func^);
            //如果和我们要拦截的Api函数地址一样
            if f = oldfun then
            begin
              //替换成我们自己的Api地址
               WriteProcessMemory(GetCurrentProcess, Func, @NewFunc, 4, written);
               if Written > 0 then Inc(Result);
            end;
            //继续找
            Inc(Func);
         end;
         Inc(ImportDesc);
      end;
   end;

begin
   IsDone := TList.Create;
   try
     //GetModuleHandle,参数nil,为获取自身的模块句柄
      Result := ReplaceAddressInModule(GetModuleHandle(nil), oldfun, newfun);
   finally
      IsDone.Free;
   end;
end;
end.

unit ApiDefine;

interface

uses
  Windows, SysUtils, Classes,Messages,APIHook,ShellAPI;

  procedure API_Hook;
  procedure API_UnHook;

implementation

//自定义Api的类型
type
  TMsgA = function(hwn: hwnd; lptext: pchar; lpcapion: pchar; utype: cardinal):integer; stdcall;
  TShellExc = function(hwn: HWND;lpoperate: PChar;lpfilename: PChar; lpparam: PChar; lpdir:PChar;cmd:Integer):Integer;stdcall;
  TTextOut = function(DC:HDC;X:Integer;Y:Integer;options:Integer;rect:PRect;str:PAnsiChar;count:Integer;dx:PInteger):Boolean;stdcall;
var
  oldMsgA : TMsgA;
  oldShellExc : TShellExc;
  oldTextOut : TTextOut;

//自定义Api的实现
function NewMsgA(hwn: hwnd; lptext: pchar; lpcaption: pchar; utype: cardinal):integer; stdcall;
begin
  Result := oldMsgA(hwn,'成功拦截MessageBoxA','哈哈',utype);
end;  

function NewShellExc(hwn: HWND;lpoperate: PChar;lpfilename: PChar; lpparam: PChar; lpdir:PChar;cmd:Integer):Integer;stdcall;
begin
  Result := oldShellExc(hwn,lpoperate,'c:/2.txt',lpfilename,lpdir,cmd);
end;

{TextOut调用的是ExtTextOut}
function NewTextOut(DC:HDC;X:Integer;Y:Integer;options:Integer;rect:PRect;str:PAnsiChar;count:Integer;dx:PInteger):Boolean;stdcall;
begin
  {这个rect也是可以修改的,以便容纳更多的字符显示}
  Result := oldTextOut(DC,50,50,options,rect,'中国',count,dx);
end;

procedure API_Hook;
begin
  if @oldMsgA = nil then
    @oldMsgA := GetFunTrueAddress(@MessageBoxA);
  if @oldShellExc = nil then
    @oldShellExc := GetFunTrueAddress(@ShellExecute);
  if @oldTextOut = nil then
    @oldTextOut := GetFunTrueAddress(@ExtTextOut);
  //替换  
  ReplaceFunAddress(@oldMsgA,@NewMsgA);
  ReplaceFunAddress(@oldShellExc,@NewShellExc);
  ReplaceFunAddress(@oldTextOut,@NewTextOut);
end;

procedure API_UnHook;
begin
  if @oldMsgA <> nil then
    ReplaceFunAddress(@NewMsgA,@oldMsgA);
  if @oldShellExc <> nil then
    ReplaceFunAddress(@NewShellExc,@oldShellExc);
  if @oldTextOut <> nil then
    ReplaceFunAddress(@NewTextOut,@oldTextOut);
end;

initialization
//结束时恢复原Api地址
finalization
  API_UnHook;

end.
hbszlhj 2017-07-10
  • 打赏
  • 举报
回复
引用 1 楼 artor112 的回复:
获取文本的话,可以用hook api来截获textout,drawtext。。。等输出文本函数来获取。
有没有相关的代码,比如获取其他程序中的文本!
talip1106 2017-07-10
  • 打赏
  • 举报
回复
获取文本的话,可以用hook api来截获textout,drawtext。。。等输出文本函数来获取。

1,183

社区成员

发帖
与我相关
我的任务
社区描述
Delphi Windows SDK/API
社区管理员
  • Windows SDK/API社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧