为什么GetWindowRgn在Vista上失败?

时间:2020-03-06 14:50:07  来源:igfitidea点击:

我正在编写一个使用SetWindowRgn的程序,该程序在属于另一个进程的窗口中制作透明孔。 (只有在用户明确要求时才执行此操作。)

该程序必须假设目标窗口可能已经有需要保留的孔,因此在调用SetWindowRgn之前,它先调用GetWindowRgn来获取当前区域,然后将当前区域与新区域合并,然后调用SetWindowRgn

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

在XP中可以正常工作,但是在Vista中对GetWindowRgn的调用失败。我曾尝试关闭Aero并通过AdjustTokenPrivileges将线程的特权提升为SE_DEBUG_NAME,但都无济于事。

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

谁能告诉我我做错了什么,或者建议其他方法?

解决方案

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

如果我们尚未设置区域,但呼叫失败,请使用合理的默认值(窗口矩形),不要让它破坏生活。现在,如果SetWindowRgn()失败了...

我们提到我们正在尝试获取另一个进程的窗口区域。 Vista加强了许多跨进程Win32调用的安全性。我找不到任何一种文档来获取GetWindowRgn()的一种方法,但是我们可以对其进行足够简单的测试。创建一个简单的项目来设置其自己的区域,然后尝试使用原始应用程序来获取简单应用程序的区域。如果它能正常工作,那将很烦人,人们将无法在任何事物上使用应用程序。如果它不起作用,则可能是应用程序在Vista上根本无法工作。

在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>