2017-08-31 125 views
0

我正在编写一个库,使窗口客户区域中的颜色不可见。SetLayeredWindowAttributes无法在Windows 8 +(C++)上工作

在应用程序的一半中,首先调用window_fix_transparent_color()使窗口分层。然后我使用window_set_transparent_color()使客户区域中的颜色不可见。

这里是我的库代码:

#define _WIN32_WINNT 0x0501 
#include <windows.h> 

extern "C" 
{ 
    void window_fix_transparent_color(double window_handle) 
    { 
     // sets the window flags to support RGB color transparency. 
     SetWindowLong((HWND)(DWORD)window_handle,GWL_EXSTYLE, 
      GetWindowLong((HWND)(DWORD)window_handle,GWL_EXSTYLE)|WS_EX_LAYERED); 
    } 

    void window_set_transparent_color(double window_handle,double red,double green,double blue) 
    { 
     // sets the RGB color to be transparent for the specified window. 
     SetLayeredWindowAttributes((HWND)(DWORD)window_handle,RGB(red,green,blue),255,LWA_COLORKEY); 
    } 
} 

我使用的包装用最新的代码MinGW的版本::块作为我的编译器。它适用于Windows 7,但不适用于Windows 8,8.1或10 ...

任何想法,为什么这是什么?此外,值得注意的一个奇怪的事情 - 它曾经在Windows 8/8.1/10上工作,这导致我相信这些平台的某个Windows更新可能会破坏我的代码。自从在Windows 7平台上停止工作以来,我没有对代码进行任何更改。

谢谢!

+0

像Winforms这样的GUI库在窗体的不透明度或者窗体的不透明度时执行[this code](https://referencesource.microsoft.com/#System.Windows.Forms/winforms/Managed/System/WinForms/Control.cs,2895b1373643ef53) TransparencyKey属性已更改。请注意对SetWindowPos()的调用。 –

+0

@HansPassant我不确定我明白你的意思。 –

+0

你用C++标记了这个问题,然后把所有的代码放在extern“C”中,如果你问我的话很奇怪... – Anders

回答

2

你为什么使用奇怪的类型和强制转换?如果必须的话,您不应该将句柄类型投射到DWORD,使用INT_PTRUINT_PTR。 A double在32位应用程序中实际上大于HWND,所以除了让自己变得更难以操作之外,实际上它们正在浪费空间。 A double不能用于在64位应用程序中存储句柄!

您也没有检查SetLayeredWindowAttributes的返回值,所以不可能知道问题究竟是什么。

重写与正确的类型和错误处理功能:

void display_error(DWORD error) 
{ 
    char buf[100]; 
    wsprintfA(buf, "Error %u!", error); 
    MessageBoxA(NULL, buf, 0, 0); // Ideally you would pass a window handle here but I don't know if your handle is actually valid 
} 

void window_fix_transparent_color(HWND window_handle) 
{ 
    DWORD error; 

    // get the window flags to see if RGB color transparency is supported. 
    SetLastError(0); 
    LONG_PTR ExStyle = GetWindowLongPtr(window_handle, GWL_EXSTYLE); 
    if (ExStyle == 0) 
    { 
     error = GetLastError(); 
     if (error != 0) 
     { 
      display_error(error); 
      return; 
     } 
    } 

    if ((ExStyle & WS_EX_LAYERED) == 0) 
    { 
     // set the window flags to support RGB color transparency. 
     SetLastError(0); 
     if (!SetWindowLongPtr(window_handle, GWL_EXSTYLE, ExStyle | WS_EX_LAYERED)) 
     { 
      error = GetLastError(); 
      if (error != 0) 
       display_error(error); 
     } 
    } 
} 

void window_set_transparent_color(HWND window_handle, BYTE red, BYTE green, BYTE blue) 
{ 
    // sets the RGB color to be transparent for the specified window. 
    if (!SetLayeredWindowAttributes(window_handle, RGB(red, green, blue), 255, LWA_COLORKEY)) 
    { 
     display_error(GetLastError()); 
    } 
} 

... 

HWND mywindow = CreateWindowEx(...); 
window_fix_transparent_color(mywindow); 
window_set_transparent_color(mywindow, ...); 
+0

即使在Windows 8+上颜色不透明,SetLayeredWindowAttributes也会返回true。如前所述,在Windows 7上它工作。 –

+0

非常感谢您尽力帮忙,因为我很感激。 :) –

+0

'HWND'从不使用他们范围的上半部分。这是安全的(即使混淆),以'双'存储窗口句柄。请参见[32位和64位应用程序之间的进程间通信](https://msdn.microsoft.com/en-us/library/windows/desktop/aa384203.aspx)以供参考。 – IInspectable

1

我的猜测是,你正在使用的“基本”或“经典”主题的Windows 7虽然 无证,它激活的Windows XP的兼容性模式为桌面窗口 管理器,并更改分层窗口的工作方式。这在后来的 版本的Windows中不会发生。

+0

我最近发现我的代码也在某些Windows 10计算机上工作。这真的很奇怪,对我来说毫无意义。有些Windows 10电脑可以工作,其他电脑则不能。我打算接受你的回答,因为它听起来很有希望,但后来我发现了这一点。 :( –

相关问题