第一步: 打开SPY++, 从菜单中选出 Find Window 对话框, 
  然后, 用其他窗口查看工具得到 Find Window 对话框 上面 'OK' 按钮 的句柄。
第二步: 新建一个工程,将工程代码改成下面这样。。program Project1;uses
  Forms, Windows,
  Unit1 in 'Unit1.pas' {Form1};{$R *.RES}begin
  GetWindowWord(按钮句柄, 0);  // 这个地方 :-)
  Application.Initialize;
  Application.CreateForm(TForm1, Form1);
  Application.Run;
end.
第三步: 运行程序,报错如下
---------------------------
Application Error
---------------------------
Exception EAccessViolation in module user32.dll at 0003DA03.
Access violation at address 77D4DA03 in module 'user32.dll'. Read of address 0014DC4C.
---------------------------
确定   
---------------------------
不过,我试了一下,如果在普通事件代码中调用又没有报错,比如:procedure TForm1.Button1Click(Sender: TObject);
begin
  GetWindowWord($001C07DE, 0);
end;
总而言之, 用 GetWindowWord(x, 0) 取 spy++ 的 findwindow 对话框上的一个按钮的时候出错

解决方案 »

  1.   

    SPY++ 下载地址    http://www.axdisk.cn/vip/liumazi/Temp/Spy++.rar
    Voyeur例程下载地址      http://www.axdisk.cn/vip/liumazi/Temp/Voyeur.rar
      

  2.   

    主要是Voyeur里面的这部分代码出错:  // 向szBuf尾部添加字符串形式的额外内存各字节数值
    procedure VoyHelp_AppendExtraBytes(szBuf: PChar; hWndSubject: HWND;
      nExtraBytesID: Integer);
    var
      nExtraByteNum, nExtraBytes: Integer;
      bByte: DWORD;
      pfnGetWord: function(hWnd: HWND; nIndex: Integer): Word; stdcall;
      List: array[0..1] of Integer; // wvsprintf()转换列表
    begin
      if (nExtraBytesID = GCL_CBCLSEXTRA) then
      begin
        pfnGetWord := @GetClassWord;
        List[0] := Integer(PChar('Class'));
      end else
      begin
        pfnGetWord := @GetWindowWord;
        List[0] := Integer(PChar('Windows'));
      end;
        
      nExtraBytes := GetClassLong(hWndSubject, nExtraBytesID); // 额外内存字节数
      List[1] := nExtraBytes;  wvsprintf(SearchEnd(szBuf), '%s extra bytes:'#9'%u (', @List[0]); // 开始  nExtraByteNum := 0;
      while (nExtraByteNum < nExtraBytes) do // 遍历各字节
      begin
        if (nExtraByteNum = 0) then
          bByte := LoByte(pfnGetWord(hWndSubject, nExtraByteNum)) // 内存 $ABCD 等于 $CDAB
        else begin
          lstrcat(szBuf, ' '); // 不是第一个字节, 则先添加分隔符
          bByte := HiByte(pfnGetWord(hWndSubject, nExtraByteNum - 1)); // 第nExtraByteNum字节
        end;
        wvsprintf(SearchEnd(szBuf), '0x%02x', @bByte); // IntToStr()
        Inc(nExtraByteNum);
      end;  if (nExtraByteNum = 0) then lstrcat(szBuf, 'none'); // 无额外空间
      lstrcat(szBuf, ')'#13#10); // 结尾  }
    end;后来分析,发现就是 GetWindowWord(x, 0) 导致的出错 GetWindowWord(x, 1); 不出错, GetWindowLong(x, 0)不出错,
    不过按照书上的思路,应该考虑如空间只有三个字节的情况,
    所以用 GetWindowLong()恐怕不太合适,例子中就是用GetWindowWord取各个字节的
    另: 这个 Voyeur 是 《Windows 95 程式设计指南》 里面一个类似于 SPY++ 雏形的例子,取其他窗体信息
      

  3.   

    同意“梦里有云,心中有天地”的说法,你试一下在Application.Initialize;语句后调用的情形如何!
      

  4.   

    begin
      GetWindowWord(按钮句柄, 0);  // 这个地方 :-) 按钮还没有创建呢。肯定错
      Application.Initialize;
      Application.CreateForm(TForm1, Form1);
      //放到这里才对。不过,每次运行按钮的句柄应该不一样啊,呵呵
      Application.Run;
    end.
      

  5.   

    你的代碼其它地方有問題, GetWindowWord($001C07DE, 0);
      Application.Initialize;
      Application.CreateForm(TForm1, Form1);
      Application.Run;這樣寫, 應該是沒有問題
      

  6.   

    这是一个空的工程,只添加了GetWindowWord($001C07DE, 0);这一句代码,$001C07DE是用其他窗口查看根据得到的SPY++的Find Window对话框上的按钮的句柄。
      

  7.   

    $001C07DE是用其他窗口查看工具得到的 SPY++ 的 Find Window 对话框上的按钮的句柄。
      

  8.   

    SPY++ 窗口不出错 , 它的 Find Window 对话框也不出错,
     就是 Find Window 对话框上的按钮出错。
    另外,放在Application.Initialize;后面也不行 :(
      

  9.   

    up
    不分场合,不分地点,不分时间 大家宣传一下:
    一组数据,日本对中国的依赖程度现排最前,特别是对中国市场的依赖,
    如果中国人1个月不买日货,日本将有数千家企业面临破产。
    如果中国人6个月不买日货,日本将有一半人失业。
    如果中国人1年不买日货,日本经济结构彻底瓦解,日本还能这样嚣张吗!
    你如果是中国人,不用你上战场当炮灰,
    你要做的事很简单,就是不买日货。 
    抵制日货网络签名处:http://www.dzrhlm.com/book/
    抵制日货网络签名处:http://www.dzrhlm.com/book/
    抵制日货网络签名处:http://www.dzrhlm.com/book/
    抵制日货网络签名处:http://www.dzrhlm.com/book/
    抵制日货网络签名处:http://www.dzrhlm.com/book/
    抵制日货网络签名处:http://www.dzrhlm.com/book/
    抵制日货网络签名处:http://www.dzrhlm.com/book/
    抵制日货网络签名处:http://www.dzrhlm.com/book/
      

  10.   


     GetWindowWord(按钮句柄, 0);  // 这个地方 :-) 按钮还没有创建呢。肯定错-------我说的按钮是SPY++的Find Window对话框上的按钮,不是自己程序的按钮。 :)刚才又找了几位朋友试了一下,有的出错,有的不出错,啦啦啦。
    我用的是VC 6.0带的SPY++,出错,另一位网友用的是vs 2003的,就没错。。看来是SPY程序的问题?我的操作系统是 XP SP1
      

  11.   

    woding,woding,woding,wo ding ding ding
      

  12.   

    写了个测试例子,下面这个程序的窗体,类空间和窗体空间都是3字节,分别被初始化为1 2 3 和 4 5 6, 然后用两个工具去查看, SPY 无法读出信息, 而我们的 Voyeur 程序却可以读出正确数值。 SPY 虽然读不出来,但是它至少可以保证不出错。是不是写 SPY 的同志, 知道 GetWindowWord() 可能会出错, 所以放弃了呢?  :-)program Test;uses Windows, Messages;function WindowProc(HWin, MsgID, WParam, LParam: DWORD): DWORD; stdcall;
    begin
      Result := DefWindowProc(HWin, MsgID, WParam, LParam);  case MsgID of
        WM_CREATE:
          begin
           // 类额外空间设为 1 2 3
            SetClassWord(HWin, 0, $0201);
            SetClassWord(HWin, 1, $0302);
           // 窗体额外空间设为 4 5 6
            SetWindowWord(HWin, 0, $0504);
            SetWindowWord(HWin, 1, $0605);
          end;    WM_DESTROY:
          begin
            PostQuitMessage(0);
          end;
      end;
    end;var
      WndClass: TWndClass;
      ThreadMsg: TMsg;
    begin
      WndClass.Style := CS_HREDRAW or CS_VREDRAW;
      WndClass.lpfnWndProc := @WindowProc;
      WndClass.cbClsExtra := 3; // 类空间
      WndClass.cbWndExtra := 3; // 窗体空间
      WndClass.hInstance := hInstance;
      WndClass.hIcon := LoadIcon(hInstance, 'cool');
      WndClass.hCursor :=  LoadCursor(0, IDC_ARROW);
      WndClass.hbrBackground := COLOR_WINDOW + 1;
      WndClass.lpszMenuName := nil;
      WndClass.lpszClassName := 'Test';  RegisterClass(WndClass);  CreateWindowEx(0, 'Test', 'Test',
        WS_TILED or WS_VISIBLE or WS_SYSMENU, 
        100, 100, 100, 70, 0, 0, hInstance, nil);  while GetMessage(ThreadMsg, 0, 0, 0) do
      begin
        TranslateMessage(ThreadMsg);
        DispatchMessage(ThreadMsg);
      end;
    end.  
      

  13.   

    呵呵, 3字节空间的时候调用GetWindowLong()失败, 返回0, :-)