2

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

程序必须假设目标窗口可能已经有洞需要保留,所以在它调用之前SetWindowRgn,它调用GetWindowRgn以获取当前区域,然后将当前区域与新区域组合并调用SetWindowRgn

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

这在 XP 中运行良好,但在 Vista 中调用GetWindowRgn失败。我尝试关闭 Aero 并将线程的权限提升到SE_DEBUG_NAMEwith AdjustTokenPrivileges,但都没有帮助。

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

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

4

4 回答 4

12

你确定你的窗口一个区域吗?XP中的大多数顶级窗口都这样做,仅仅是因为默认主题将它们用于圆角......但这仍然是一个不好的假设,一旦你进入Vista,很可能不会成立。

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

于 2008-09-28T00:28:08.273 回答
2

在 Vista 下,为了让一个不以管理员身份运行的进程以另一个进程的窗口为目标,它必须:

  • 嵌入带有 uiAccess="true" 的清单文件(下面的示例)
  • 对应用程序进行数字签名
  • 从“安全”的地方安装并执行它,例如“程序文件”

这是一个示例清单:

<?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>
于 2008-09-28T18:19:36.997 回答
1

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

于 2008-09-28T00:52:30.820 回答
1

我对 Windows API 函数 ::GetWindowRgn(...) 的回答(根据我的经验)

此函数在 Vista 和 Windows 7 中失败,即返回 ERROR。

但此功能在 Windows XP 中运行良好。

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

请在上面标记为<...>的地方使用相应的代码

谢谢你的热情。


于 2011-08-25T03:15:06.903 回答