请教关于 GetWindowWord() 的问题 ( 积分: 300 )

  • 主题发起人 主题发起人 刘麻子
  • 开始时间 开始时间

刘麻子

Unregistered / Unconfirmed
GUEST, unregistred user!
第一步: 打开SPY++, 从菜单中选出 Find Window 对话框, <br> &nbsp;然后, 用其他窗口查看工具得到 Find Window 对话框 上面 'OK' 按钮 的句柄。<br><br><br>第二步: 新建一个工程,将工程代码改成下面这样。。<br><br>program Project1;<br><br>uses<br> &nbsp;Forms, Windows,<br> &nbsp;Unit1 in 'Unit1.pas' {Form1};<br><br>{$R *.RES}<br><br>begin<br> &nbsp;GetWindowWord(按钮句柄, 0); &nbsp;// 这个地方 :-)<br> &nbsp;Application.Initialize;<br> &nbsp;Application.CreateForm(TForm1, Form1);<br> &nbsp;Application.Run;<br>end.<br><br><br>第三步: 运行程序,报错如下<br>---------------------------<br>Application Error<br>---------------------------<br>Exception EAccessViolation in module user32.dll at 0003DA03.<br>Access violation at address 77D4DA03 in module 'user32.dll'. Read of address 0014DC4C.<br>---------------------------<br>确定 &nbsp; <br>---------------------------<br><br><br>不过,我试了一下,如果在普通事件代码中调用又没有报错,比如:<br><br>procedure TForm1.Button1Click(Sender: TObject);<br>begin<br> &nbsp;GetWindowWord($001C07DE, 0);<br>end;<br><br><br>总而言之, 用 GetWindowWord(x, 0) 取 spy++ 的 findwindow 对话框上的一个按钮的时候出错
 
第一步: 打开SPY++, 从菜单中选出 Find Window 对话框, <br> &nbsp;然后, 用其他窗口查看工具得到 Find Window 对话框 上面 'OK' 按钮 的句柄。<br><br><br>第二步: 新建一个工程,将工程代码改成下面这样。。<br><br>program Project1;<br><br>uses<br> &nbsp;Forms, Windows,<br> &nbsp;Unit1 in 'Unit1.pas' {Form1};<br><br>{$R *.RES}<br><br>begin<br> &nbsp;GetWindowWord(按钮句柄, 0); &nbsp;// 这个地方 :-)<br> &nbsp;Application.Initialize;<br> &nbsp;Application.CreateForm(TForm1, Form1);<br> &nbsp;Application.Run;<br>end.<br><br><br>第三步: 运行程序,报错如下<br>---------------------------<br>Application Error<br>---------------------------<br>Exception EAccessViolation in module user32.dll at 0003DA03.<br>Access violation at address 77D4DA03 in module 'user32.dll'. Read of address 0014DC4C.<br>---------------------------<br>确定 &nbsp; <br>---------------------------<br><br><br>不过,我试了一下,如果在普通事件代码中调用又没有报错,比如:<br><br>procedure TForm1.Button1Click(Sender: TObject);<br>begin<br> &nbsp;GetWindowWord($001C07DE, 0);<br>end;<br><br><br>总而言之, 用 GetWindowWord(x, 0) 取 spy++ 的 findwindow 对话框上的一个按钮的时候出错
 
爽,这么多人看了都不回!<br>不回,不回,打死也不回!
 
这样会有区别吗?<br>begin<br> &nbsp;Application.Initialize;<br> &nbsp;GetWindowWord(按钮句柄, 0); &nbsp;// 这个地方 :-)<br> &nbsp;Application.CreateForm(TForm1, Form1);<br> &nbsp;Application.Run;<br>end.<br>
 
加在Initialize后面也不行,刚才大富翁进不来,在CSDN发了帖子,现在拷贝几处补充说明过来:<br><br>SPY++ 下载地址 &nbsp; &nbsp; http://www.axdisk.cn/vip/liumazi/Temp/Spy++.rar<br>Voyeur例程下载地址 &nbsp; &nbsp; http://www.axdisk.cn/vip/liumazi/Temp/Voyeur.rar<br><br>主要是Voyeur里面的这部分代码出错:<br><br> &nbsp;// 向szBuf尾部添加字符串形式的额外内存各字节数值<br>procedure VoyHelp_AppendExtraBytes(szBuf: PChar; hWndSubject: HWND;<br> &nbsp;nExtraBytesID: Integer);<br>var<br> &nbsp;nExtraByteNum, nExtraBytes: Integer;<br> &nbsp;bByte: DWORD;<br> &nbsp;pfnGetWord: function(hWnd: HWND; nIndex: Integer): Word; stdcall;<br> &nbsp;List: array[0..1] of Integer; // wvsprintf()转换列表<br>begin<br> &nbsp;if (nExtraBytesID = GCL_CBCLSEXTRA) then<br> &nbsp;begin<br> &nbsp; &nbsp;pfnGetWord := @GetClassWord;<br> &nbsp; &nbsp;List[0] := Integer(PChar('Class'));<br> &nbsp;end else<br> &nbsp;begin<br> &nbsp; &nbsp;pfnGetWord := @GetWindowWord;<br> &nbsp; &nbsp;List[0] := Integer(PChar('Windows'));<br> &nbsp;end;<br> &nbsp; &nbsp;<br> &nbsp;nExtraBytes := GetClassLong(hWndSubject, nExtraBytesID); // 额外内存字节数<br> &nbsp;List[1] := nExtraBytes;<br><br> &nbsp;wvsprintf(SearchEnd(szBuf), '%s extra bytes:'#9'%u (', @List[0]); // 开始<br><br> &nbsp;nExtraByteNum := 0;<br> &nbsp;while (nExtraByteNum &amp;lt; nExtraBytes) do // 遍历各字节<br> &nbsp;begin<br> &nbsp; &nbsp;if (nExtraByteNum = 0) then<br> &nbsp; &nbsp; &nbsp;bByte := LoByte(pfnGetWord(hWndSubject, nExtraByteNum)) // 内存 $ABCD 等于 $CDAB<br> &nbsp; &nbsp;else begin<br> &nbsp; &nbsp; &nbsp;lstrcat(szBuf, ' '); // 不是第一个字节, 则先添加分隔符<br> &nbsp; &nbsp; &nbsp;bByte := HiByte(pfnGetWord(hWndSubject, nExtraByteNum - 1)); // 第nExtraByteNum字节<br> &nbsp; &nbsp;end;<br> &nbsp; &nbsp;wvsprintf(SearchEnd(szBuf), '0x%02x', @bByte); // IntToStr()<br> &nbsp; &nbsp;Inc(nExtraByteNum);<br> &nbsp;end;<br><br> &nbsp;if (nExtraByteNum = 0) then lstrcat(szBuf, 'none'); // 无额外空间<br> &nbsp;lstrcat(szBuf, ')'#13#10); // 结尾 &nbsp;}<br>end;<br><br>后来分析,发现就是 GetWindowWord(x, 0) 导致的出错 。。我就开了一个新的工程,开头就调用了 GetWindowWord(x, 0), 结果也出错。不过如果在普通事件过程里面调用又不会出错,不知道怎么搞的,很奇怪。<br><br>GetWindowWord(x, 1); 不出错,GetWindowLong(x, 0)不出错,不过按照书上的思路,应该考虑空间少于4个字节的情况,所以用 GetWindowLong()不知道是否合适,书中例子代码中是用GetWindowWord()来取各个字节的。<br><br>另: 这个Voyeur是《Windows 95 程式设计指南》里面一个例子,取其他窗体信息的,调用GetWindowWord()的目的是依次取出目标窗体实例额外空间内存中每个字节的数值并转换成字符串形式。<br><br>后来还找了好几位朋友帮忙试了一下,害得他们忙了半天,有的出错,有的不出错,:(<br><br>简而言之,调用 GetWindowWord(h, 0), 有的时候会出错, 特别是, 当h是其他程序中, 由资源生成的对话框上的按钮的时候。 比如 SPY++ 里面的 Find Window 对话框上的按钮。
 
哇,有300分阿……至少给我一分吧……
 
DoubleWood大哥 下午帮我试了好久 怎么可能才一分呢。 :-)
 
写了个测试例子,下面这个程序的窗体,类空间和窗体空间都是3字节,分别被初始化为1 2 3 和 4 5 6, 然后用两个工具去查看, SPY 无法读出信息, 而我们的 Voyeur 程序却可以读出正确数值。 SPY 虽然读不出来,但是它至少可以保证不出错。是不是写 SPY 的同志, 知道 GetWindowWord() 可能会出错, 所以放弃了呢? &nbsp;:-)<br><br>program Test;<br><br>uses Windows, Messages;<br><br>function WindowProc(HWin, MsgID, WParam, LParam: DWORD): DWORD; stdcall;<br>begin<br> &nbsp;Result := DefWindowProc(HWin, MsgID, WParam, LParam);<br><br> &nbsp;case MsgID of<br> &nbsp; &nbsp;WM_CREATE:<br> &nbsp; &nbsp; &nbsp;begin<br> &nbsp; &nbsp; &nbsp; // 类额外空间设为 1 2 3<br> &nbsp; &nbsp; &nbsp; &nbsp;SetClassWord(HWin, 0, $0201);<br> &nbsp; &nbsp; &nbsp; &nbsp;SetClassWord(HWin, 1, $0302);<br> &nbsp; &nbsp; &nbsp; // 窗体额外空间设为 4 5 6<br> &nbsp; &nbsp; &nbsp; &nbsp;SetWindowWord(HWin, 0, $0504);<br> &nbsp; &nbsp; &nbsp; &nbsp;SetWindowWord(HWin, 1, $0605);<br> &nbsp; &nbsp; &nbsp;end;<br><br> &nbsp; &nbsp;WM_DESTROY:<br> &nbsp; &nbsp; &nbsp;begin<br> &nbsp; &nbsp; &nbsp; &nbsp;PostQuitMessage(0);<br> &nbsp; &nbsp; &nbsp;end;<br> &nbsp;end;<br>end;<br><br>var<br> &nbsp;WndClass: TWndClass;<br> &nbsp;ThreadMsg: TMsg;<br>begin<br> &nbsp;WndClass.Style := CS_HREDRAW or CS_VREDRAW;<br> &nbsp;WndClass.lpfnWndProc := @WindowProc;<br> &nbsp;WndClass.cbClsExtra := 3; // 类空间<br> &nbsp;WndClass.cbWndExtra := 3; // 窗体空间<br> &nbsp;WndClass.hInstance := hInstance;<br> &nbsp;WndClass.hIcon := LoadIcon(hInstance, 'cool');<br> &nbsp;WndClass.hCursor := &nbsp;LoadCursor(0, IDC_ARROW);<br> &nbsp;WndClass.hbrBackground := COLOR_WINDOW + 1;<br> &nbsp;WndClass.lpszMenuName := nil;<br> &nbsp;WndClass.lpszClassName := 'Test';<br><br> &nbsp;RegisterClass(WndClass);<br><br> &nbsp;CreateWindowEx(0, 'Test', 'Test',<br> &nbsp; &nbsp;WS_TILED or WS_VISIBLE or WS_SYSMENU, <br> &nbsp; &nbsp;100, 100, 100, 70, 0, 0, hInstance, nil);<br><br> &nbsp;while GetMessage(ThreadMsg, 0, 0, 0) do<br> &nbsp;begin<br> &nbsp; &nbsp;TranslateMessage(ThreadMsg);<br> &nbsp; &nbsp;DispatchMessage(ThreadMsg);<br> &nbsp;end;<br>end.
 
MSDN:<br>The GetWindowWord function is obsolete. The GWW_ values are not supported. Win32-based applications should use the GetWindowLong function
 
这个应该是说 &quot;GWW_XXX 常量不被支持了,应 改用 GetWindowLong(GWL_XXX)了&quot; 吧?<br><br> 读额外空间的话应该还是可以用GetWindowWord()的吧,普通窗体也的确可以读的,<br> 另外, 如果空间只有3个字节, 可以用 GetWindowLong() 吗?
 
不过我没用过GetWindowWord,我一直是用GetWindowLong的,呵呵
 
呵呵, 试了一下, 3字节空间的时候调用GetWindowLong()失败, 返回0, :-)
 
我的也是如此,Delphi5,7都会(不过这和delphi的版本应该没关系吧^_^),既然有的人不会出错,那也有可能和操作系统有关啊,每次错误提示都是:'Access violation at address 77E24948 in module 'user32.dll',这个地址都一样,反汇编一下user32.dll看看,或许...[:D][:D].
 
to 刘麻子:<br> &nbsp; &nbsp; &nbsp; &nbsp;SetClassWord(HWin, 0, $0201); &nbsp;//这里是4个字节<br> &nbsp; &nbsp; &nbsp; &nbsp;SetClassWord(HWin, 1, $0302); &nbsp;//这里是4个字节<br> &nbsp; &nbsp; &nbsp; // 窗体额外空间设为 4 5 6<br> &nbsp; &nbsp; &nbsp; &nbsp;SetWindowWord(HWin, 0, $0504); //这里是4个字节<br> &nbsp; &nbsp; &nbsp; &nbsp;SetWindowWord(HWin, 1, $0605); //这里是4个字节<br>改为:<br> &nbsp; &nbsp; &nbsp; &nbsp;SetClassWord(HWin, 0, Byte(1));<br> &nbsp; &nbsp; &nbsp; &nbsp;SetClassWord(HWin, 1, Byte(2));<br> &nbsp; &nbsp; &nbsp; &nbsp;SetClassWord(HWin, 2, Byte(3));<br> &nbsp;<br> &nbsp; &nbsp; &nbsp; &nbsp;SetWindowWord(HWin, 0, Byte(4));<br> &nbsp; &nbsp; &nbsp; &nbsp;SetWindowWord(HWin, 1, Byte(5));<br> &nbsp; &nbsp; &nbsp; &nbsp;SetWindowWord(HWin, 2, Byte(6));<br><br>
 
谢谢llfirst,,我的问题是调用 GetWindowWord() 出错,<br>SetWindowWord()是另一个被用来测试的程序,并没有错。<br>另外,$0201是4字节吗?1位16进制对应的是4位2进制吧?
 
program Test;<br><br>uses Windows, Messages;<br><br>function WindowProc(HWin, MsgID, WParam, LParam: DWORD): DWORD; stdcall;<br>var<br> &nbsp;B:array[0..5] of Byte;<br><br>begin<br> &nbsp;Result := DefWindowProc(HWin, MsgID, WParam, LParam);<br><br> &nbsp;case MsgID of<br> &nbsp; &nbsp;WM_CREATE:<br> &nbsp; &nbsp; &nbsp;begin<br> &nbsp; &nbsp; &nbsp; &nbsp;SetClassWord(HWin, 0, Byte(1));<br> &nbsp; &nbsp; &nbsp; &nbsp;SetClassWord(HWin, 1, Byte(2));<br> &nbsp; &nbsp; &nbsp; &nbsp;SetClassWord(HWin, 2, Byte(3));<br> &nbsp;<br> &nbsp; &nbsp; &nbsp; &nbsp;SetWindowWord(HWin, 0, Byte(4));<br> &nbsp; &nbsp; &nbsp; &nbsp;SetWindowWord(HWin, 1, Byte(5));<br> &nbsp; &nbsp; &nbsp; &nbsp;SetWindowWord(HWin, 2, Byte(6));<br><br> &nbsp; &nbsp; &nbsp; &nbsp;B[0]:=GetClassWord(HWin, 0 );<br> &nbsp; &nbsp; &nbsp; &nbsp;B[1]:=GetClassWord(HWin, 1 );<br> &nbsp; &nbsp; &nbsp; &nbsp;B[2]:=GetClassWord(HWin, 2 );<br><br> &nbsp; &nbsp; &nbsp; &nbsp;B[3]:=GetWindowWord(HWin, 0 );<br> &nbsp; &nbsp; &nbsp; &nbsp;B[4]:=GetWindowWord(HWin, 1 );<br> &nbsp; &nbsp; &nbsp; &nbsp;B[5]:=GetWindowWord(HWin, 2 );<br>//没有任何错误,Windows 2003 + Delphi 7.0 通过<br> &nbsp; &nbsp; &nbsp;end;<br><br> &nbsp; &nbsp;WM_DESTROY:<br> &nbsp; &nbsp; &nbsp;begin<br> &nbsp; &nbsp; &nbsp; &nbsp;PostQuitMessage(0);<br> &nbsp; &nbsp; &nbsp;end;<br> &nbsp;end;<br>end;<br><br>var<br> &nbsp;WndClass: TWndClass;<br> &nbsp;ThreadMsg: TMsg;<br>begin<br> &nbsp;WndClass.Style := CS_HREDRAW or CS_VREDRAW;<br> &nbsp;WndClass.lpfnWndProc := @WindowProc;<br> &nbsp;WndClass.cbClsExtra := 3; // 类空间<br> &nbsp;WndClass.cbWndExtra := 3; // 窗体空间<br> &nbsp;WndClass.hInstance := hInstance;<br> &nbsp;WndClass.hIcon := LoadIcon(hInstance, 'cool');<br> &nbsp;WndClass.hCursor := &nbsp;LoadCursor(0, IDC_ARROW);<br> &nbsp;WndClass.hbrBackground := COLOR_WINDOW + 1;<br> &nbsp;WndClass.lpszMenuName := nil;<br> &nbsp;WndClass.lpszClassName := 'Test';<br><br> &nbsp;RegisterClass(WndClass);<br><br> &nbsp;CreateWindowEx(0, 'Test', 'Test',<br> &nbsp; &nbsp;WS_TILED or WS_VISIBLE or WS_SYSMENU, <br> &nbsp; &nbsp;100, 100, 100, 70, 0, 0, hInstance, nil);<br><br> &nbsp;while GetMessage(ThreadMsg, 0, 0, 0) do<br> &nbsp;begin<br> &nbsp; &nbsp;TranslateMessage(ThreadMsg);<br> &nbsp; &nbsp;DispatchMessage(ThreadMsg);<br> &nbsp;end;<br>end. &nbsp;<br>
 
老兄,看贴不会帖固然不好,回帖不看贴就也不对啊。请注意,我贴这代码之前的一段话:<br><br>“写了个测试例子,下面这个程序的窗体,类空间和窗体空间都是3字节,分别被初始化为1 2 3 和 4 5 6, 然后用两个工具去查看, SPY 无法读出信息, 而我们的 Voyeur 程序却可以读出正确数值。”<br><br>我就是说读这个额外内存为3字节的被测试例子没出错,可以正确读出,而SPY++却读不出来。<br><br>但是,在读某些对话框上的按钮的时候,Voyeur 会出错,但是 SPY++ 却不出错 。。。。<br><br>那么,这是否间接说明 SPY++ 没有调用GetWindowWord(), 或许调用的是GetWindowLong()?
 
还有,经过这样的调用: SetClassWord(HWin, 0, $0201); SetClassWord(HWin, 1, $0302); 内存中3个字节就是依次为 1、2、3,至于为什么,自己好好想想。 而象你那个 SetClassWord(HWin, 2, Byte(3));,逻辑上就是错的,总共只有3个字节,难道你要去写第 3、4 两个字节?当然,你愿意花时间来讨论这本身是好的,还是要感谢你,不过说话之前应该多考虑考虑,看清楚了,想明白了,再开口。谢谢!
 
多人接受答案了。
 

Similar threads

S
回复
0
查看
3K
SUNSTONE的Delphi笔记
S
S
回复
0
查看
2K
SUNSTONE的Delphi笔记
S
I
回复
0
查看
546
import
I
I
回复
0
查看
747
import
I
后退
顶部