为什么GetWindowRgn在Vista上失败?

时间:2008-09-27 23:46:01

标签: winapi windows-vista

我正在编写一个程序,使用SetWindowRgn在属于另一个进程的窗口中创建透明孔。 (仅当用户明确请求时才会这样做。)

程序必须假设目标窗口可能已经有需要保留的漏洞,因此在调用SetWindowRgn之前,它会调用GetWindowRgn来获取当前区域,然后组合当前区域使用新的并致电SetWindowRgn

HRGN rgnOld = CreateRectRgn ( 0, 0, 0, 0 );
int regionType = GetWindowRgn ( hwnd, rgnOld ); 

这在XP中运行良好,但是对GetWindowRgn的调用在Vista中失败了。我已经尝试关闭Aero并使用AdjustTokenPrivileges将我的帖子的权限提升为SE_DEBUG_NAME,但都没有帮助。

GetLastError()似乎没有返回GetWindowRgn的有效值 - 它在一台机器上返回0,在另一台机器上返回5(拒绝访问)。

有谁能告诉我我做错了什么或提出了不同的方法?

4 个答案:

答案 0 :(得分:12)

您确定您的窗口区域吗? XP中的大多数顶级窗口都是这样做的,因为默认主题将它们用于圆角...但这仍然是一个不好的假设,并且一旦你到达Vista就可能无法保持。

如果你还没有设置区域,并且调用失败,请使用合理的默认值(窗口rect)并且不要让它破坏你的生活。现在,如果SetWindowRgn()失败......

答案 1 :(得分:2)

在Vista下,为了使一个不以管理员身份运行的进程从另一个进程中定位一个窗口,它必须:

  • 使用uiAccess =“true”(下面的示例)
  • 嵌入清单文件
  • 对应用程序进行数字签名
  • 从“安全”位置安装并执行它,例如“Program Files”

以下是示例清单:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
  <assemblyIdentity version="1.0.0.0" processorArchitecture="X86" name="yourAssemblyNameWithoutExtension" type="win32"/>
  <trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
    <security>
      <requestedPrivileges>
        <requestedExecutionLevel level="asInvoker" uiAccess="true" />
      </requestedPrivileges>
    </security>
  </trustInfo>
</assembly>

答案 2 :(得分:1)

您提到您正试图获取另一个进程的窗口区域。 Vista加强了许多跨进程Win32调用的安全性。我无法以GetWindowRgn()的方式找到任何文档,但您可以对其进行足够的测试。制作一个设置自己区域的简单项目,并尝试使用原始应用来获取简单应用的区域。如果它有效,那么它就会变得烦人,人们无法在任何事情上使用你的应用程序。如果它不起作用,您的应用程序可能无法在Vista上运行。

答案 3 :(得分:1)


关于Windows API函数的答案(根据我的经验):: GetWindowRgn(...)

此功能在Vista和Windows 7中失败,也就是说,它返回ERROR。

但是这个功能在Windows XP中运行良好。

因此,我会建议以下非复杂的解决方案:   如果在预期运行的应用程序中使用此功能   在不同的Windows下,提供如下测试:     int nResultOfRgnOperation = :: GetWindowRegion(...);     if(nResultOfRgnOperation!= ERROR)       &LT;进一步使用由该功能确定的整个窗口区域&gt;     其他       &LT;找到整个窗口的边界矩形并使用         进一步的是边界矩形而不是窗口的区域。         在需要时,您可以创建一个代表的矩形区域         边界矩形。 &GT;

请在上面标记为“&lt; ...&gt;

的地方使用相应的代码

感谢您的热情。