zoukankan      html  css  js  c++  java
  • 读取外部程序的标题和内容(转)

    http://www.cnblogs.com/findumars/archive/2011/11/05/2236944.html
    很好很强到,所以转了
    Delphi 为我们提供了三个方便的函数:
    GlobalAllocPtr   {简化自 API 的 GlobalAlloc}
    GlobalReAllocPtr {简化自 API 的 GlobalReAlloc}
    GlobalFreePtr    {简化自 API 的 GlobalFree}
    读写本程序以外的数据时可以使用它们, 很方便, 譬如:
    p := GlobalAllocPtr(0, Len);      {分配}
    p := GlobalReAllocPtr(p, Len, 0); {重分配}
    GlobalFreePtr(p);                 {释放}
    注意 GlobalAllocPtr 的第一个参数和 GlobalReAllocPtr 的最后一个参数, 上面给的都是 0;
    这两个参数的意义是一样的, 规范一点应该写成 GMEM_FIXED (表示分配固定内存), 常用的参数还有:
    GMEM_MOVEABLE {分配可移动内存}
    GMEM_ZEROINIT {同时清空内存}
    GHND          {分配可移动内存同时清空}
    GPTR          {分配固定内存同时清空}
    procedure TForm1.Button2Click(Sender: TObject);
    var
      p: Pointer;
      Len: Integer;
    begin
      Len := 6+1;                    {假如想要读出 6 个字符, 要流出结束的空字符}
      p := GlobalAllocPtr(0, Len*2); {分配内存 Len*2 是针对双字节字符}
      SendMessage(Memo1.Handle, WM_GETTEXT, Len, Cardinal(p));
      ShowMessage(PChar(p)); {CodeGe}
    
      {在上一例的基础上继续, 先获取实际长度}
      Len := SendMessage(Memo1.Handle, WM_GETTEXTLENGTH, 0, 0);
      Len := (Len + 1) * 2;
      p := GlobalReAllocPtr(p, Len, GHND); {重新分配内存}
      SendMessage(Memo1.Handle, WM_GETTEXT, Len, Cardinal(p));
      ShowMessage(PChar(p)); {CodeGear Delphi 2009}
      GlobalFreePtr(p);
    end;
    
    
    {获取已打开的所有记事本的标题}
    procedure TForm1.Button1Click(Sender: TObject);
    var
      h: HWnd;
      p: array[0..254] of char;
    begin
      Memo1.Clear;
      h := GetWindow(Handle, GW_HWNDFIRST);
      while h <> 0 do
      begin
        GetClassName(h, p, Length(p));
        if p = 'Notepad' then
        begin
          GetWindowText(h, p, Length(p));
          Memo1.Lines.Add(p);
        end;
        h := GetWindow(h, GW_HWNDNEXT);
      end;
    end;
    --------------- 读取记事本的标题 ----------------------------------
    procedure TForm1.Button1Click(Sender: TObject);
    var
    p: Pointer;
    Len: Integer;
    h:hwnd;
    begin
    h:=findwindow('notepad',nil);
    Len := 6+1; {假如想要读出 6 个字符, 要留出结束的空字符}
    p := GlobalAllocPtr(0, Len*2); {分配内存 Len*2 是针对双字节字符}
    SendMessage(h, WM_GETTEXT, Len, Cardinal(p));
    ShowMessage(PChar(p)); {CodeGe}
    GlobalFreePtr(p);
    end;
    --------------- 读取记事本的内容 ----------------------------------

    procedure TForm1.Button1Click(Sender: TObject);

    var
      h: HWND;
      p: Pointer;
      Len: Integer;
    begin
      h := FindWindow('Notepad', nil);
      if h = 0 then Exit;
      h := GetWindow(h, GW_CHILD);
      if h = 0 then Exit;
      Len := SendMessage(h, WM_GETTEXTLENGTH, 0, 0) + 1;
      p := GlobalAllocPtr(0, Len * SizeOf(Char));
      SendMessage(h, WM_GETTEXT, Len, Cardinal(p));
      ShowMessage(PChar(p));
      GlobalFreePtr(p);
    end;
    
    
    
    //声明:
    GetWindow(
      hWnd: HWND; {指定的窗口句柄}
      uCmd: UINT  {指定的关系选项}
    ): HWND;      {失败返回0; 成功返回符合的窗口句柄}
    
    //uCmd 可选值:
    GW_HWNDFIRST = 0; {同级别第一个}
    GW_HWNDLAST  = 1; {同级别最后一个}
    GW_HWNDNEXT  = 2; {同级别下一个}
    GW_HWNDPREV  = 3; {同级别上一个}
    GW_OWNER     = 4; {属主窗口}
    GW_CHILD     = 5; {子窗口}
    
    
    
    
    
    {要有个 Memo 接受数据}
    procedure TForm1.Button1Click(Sender: TObject);
    var
      h: HWnd;
      p: array[0..254] of char;
    begin
      h := GetWindow(Handle, GW_HWNDFIRST);
      while h <> 0 do
      begin
        if GetWindowText(h, p, 255) > 0 then Memo1.Lines.Add(p);
        h := GetWindow(h, GW_HWNDNEXT);
      end;
    end;

    
    
    {用 API 实现的获取文本容器中选择的文本的函数}
    function GetEditSeleteText(h: HWND): string;
    var
      len,sx,ex: Integer; {文本总长度, 选择的开始位置, 选择的结束位置}
      buf: PChar;         {所有文本}
    begin
      {获取文本总长度}
      len := SendMessage(h, WM_GETTEXTLENGTH, 0, 0) + 1;
      {为接受所有文本的缓冲区分配内存}
      buf := GlobalAllocPtr(0, len); {这里没有使用 GetMem, 因为需要全局的, 不然无法面对其他程序}
      {获取所有文本}
      SendMessage(h, WM_GETTEXT, len, Longint(buf));
      {获取选择的开始位置和结束位置}
      SendMessage(h, EM_GETSEL, Longint(@sx), Longint(@ex));
      {截取选择的文本}
      Result := Copy(buf, sx+1, ex-sx);
      {释放内存}
      GlobalFreePtr(buf);
    end;
    
    {测试 TEdit, 同时与 VCL 的获取方法对比}
    procedure TForm1.Button1Click(Sender: TObject);
    begin
      ShowMessage(GetEditSeleteText(Edit1.Handle) + ' - ' + Edit1.SelText);
    end;
    
    
    
    
    
    var
      h: HWND;
    
    procedure TForm1.Timer1Timer(Sender: TObject);
    var
      pt: TPoint;
      arr: array[0..254] of Char;
    begin
      if GetCursorPos(pt) then             {如果能获取点}
      begin
        h := WindowFromPoint(pt);          {返回句柄}
        GetClassName(h, arr, Length(arr)); {获取该句柄窗口的类名}
        Text := arr;                       {显示在标题}
      end;
    end;
    
    end.

    
    
    
    
    
    //声明:
    GetClassName(
      hWnd: HWND;         {指定窗口句柄}
      lpClassName: PChar; {缓冲区}
      nMaxCount: Integer  {缓冲区大小}
    ): Integer;           {返回类名大小; 失败返回 0}

    //测试1: 新建一个工程, 主窗口的类名默认是 TForm1, 用程序获取一下看看
    var
      ps: array[0..254] of Char;
    begin
      GetClassName(Handle, ps, 255);
      ShowMessage(ps); {TForm1}
    end;

    //测试2: 看看 "计算器" 窗口的类名(先启动计算器)
    var
      h: HWND;
      ps: array[0..254] of Char;
    begin
      h := FindWindow(nil, '计算器'); {这句是获取计算器窗口的句柄}
      GetClassName(h, ps, 255);
      ShowMessage(ps); {SciCalc}
    end;

    //测试3: 看看记事本窗口的类名(先重新启动记事本):
    var
      h: HWND;
      ps: array[0..254] of Char;
    begin
      h := FindWindow(nil, '无标题 - 记事本'); {这句是获取记事本窗口的句柄}
      GetClassName(h, ps, 255);
      ShowMessage(ps); {Notepad}
    end;
    
     
    FindWindow(
      lpClassName,        {窗口的类名}
      lpWindowName: PChar {窗口的标题}
    ): HWND;              {返回窗口的句柄; 失败返回 0}
    
    //FindWindowEx 比 FindWindow 多出两个句柄参数:
    FindWindowEx(
      Parent: HWND;     {要查找子窗口的父窗口句柄}
      Child: HWND;      {子窗口句柄}
      ClassName: PChar; {}
      WindowName: PChar {}
    ): HWND;
    {
    如果 Parent 是 0, 则函数以桌面窗口为父窗口, 查找桌面窗口的所有子窗口;
    如果  是 HWND_MESSAGE, 函数仅查找所有消息窗口;
    子窗口必须是 Parent 窗口的直接子窗口;
    如果 Child 是 0, 查找从 Parent 的第一个子窗口开始;
    如果 Parent 和 Child 同时是 0, 则函数查找所有的顶层窗口及消息窗口.
    }

    //测试1: 试着找找新建程序主窗口的句柄
    var
      h: HWND;
    begin
      {现在我们知道窗口的标题是: Form1、窗口的类名是: TForm1}
      h := FindWindow('TForm1', 'Form1');
      ShowMessage(IntToStr(h));      {656180; 这是随机, 每次启动窗口肯定不一样}
    
      {假如不知道类名}
      h := FindWindow(nil, 'Form1');
      ShowMessage(IntToStr(h));      {656180}
    
      {假如不知道标题名}
      h := FindWindow('TForm1', nil);
      ShowMessage(IntToStr(h));      {656180}
    
      {其实这个窗口的句柄不就是 Self.Handle 吗}
      ShowMessage(IntToStr(Handle)); {656180}
    end;

    //测试2: 找计算器窗口的句柄(先打开计算器)
    var
      h: HWND;
    begin
      {如果不是简体中文系统, 这样可能不灵}
      h := FindWindow(nil, '计算器');
      ShowMessage(IntToStr(h)); {1508334}
    
      {最好这样, 但你得提前知道计算器窗口的类名是: SciCalc}
      h := FindWindow('SciCalc', nil);
      ShowMessage(IntToStr(h)); {1508334}
    end;

    
    
    procedure TForm1.Button1Click(Sender: TObject);
    const
      className = 'IEFrame'; {这是 IE 浏览器的类名}
    var
      h: HWnd;
      buf: array[Byte] of Char;
    begin
      h := GetWindow(Handle, GW_HWNDFIRST);
      while h <> 0 do
      begin
        GetClassName(h, buf, Length(buf));
        if buf = className then {找到咋处理? 显示它的标题吧}
        begin
          GetWindowText(h, buf, Length(buf));
          Memo1.Lines.Add(buf)
        end;
        h := GetWindow(h, GW_HWNDNEXT);
      end;
    end;

    
    

    枚举当前所有的 IE 窗口 

    
    
    procedure TForm1.Button1Click(Sender: TObject);
    const
      className = 'IEFrame'; {这是 IE 浏览器的类名}
    var
      h: HWnd;
      buf: array[Byte] of Char;
    begin
      h := GetWindow(Handle, GW_HWNDFIRST);
      while h <> 0 do
      begin
        GetClassName(h, buf, Length(buf));
        if buf = className then {找到咋处理? 显示它的标题吧}
        begin
          GetWindowText(h, buf, Length(buf));
          Memo1.Lines.Add(buf)
        end;
        h := GetWindow(h, GW_HWNDNEXT);
      end;
    end;
    
    

    如果有个按钮,是disabled那种效果,就是灰掉,不能点的那种,怎么获取这样按钮句柄呢?
    可以从母体中遍历控件找到它. 
    如果是使用鼠标探测的话, 可以通过判断鼠标指针是否在控件范围内来确认.

    怎么判断鼠标指针是否在控件范围内?
    可以通过控件的事件: 
    OnMouseEnter (进入控件范围) 
    OnMouseLeave (离开控件范围) 
    也可以用函数: PtInRect

  • 相关阅读:
    php && 逻辑与运算符使用说明
    php无穷递归算法
    PHP foreach 用法
    centos安装g++
    php 编译中apxs
    shutdown()
    C语言strtok()函数:字符串分割
    细谈select函数(C语言)
    setsockopt的作用
    STL之七:STL各种容器的使用时机详解
  • 原文地址:https://www.cnblogs.com/jadic/p/2410199.html
Copyright © 2011-2022 走看看