4

Since windows 8, WS_EX_LAYERED is available to use on child controls, (so says MSDN) However I've been unable to make it work. In the following code, I'm trying to make a child control semi transparent but when WS_EX_LAYERED is used on the control, nothing draws.

int APIENTRY wWinMain(_In_ HINSTANCE hInst, _In_opt_ HINSTANCE hPrevInst, _In_ LPWSTR lpCmdLine, _In_ int nCmdShow)
{
    WNDCLASSEX wc = {};

    wc.cbSize = sizeof(WNDCLASSEX);
    wc.style = CS_HREDRAW | CS_VREDRAW;
    wc.lpfnWndProc = WndProc;
    wc.hInstance = hInst;
    wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
    wc.lpszClassName = _T("main");
    wc.hCursor = LoadCursor(0, IDC_ARROW);
    RegisterClassEx(&wc);

    HWND MWhwnd = CreateWindowEx(NULL, _T("main"), _T(""),
       WS_OVERLAPPEDWINDOW| WS_CLIPCHILDREN,
       CW_USEDEFAULT, 0, CW_USEDEFAULT,0, NULL, NULL, hInst, NULL);

    wc.lpfnWndProc = WndProcPanel;
    wc.lpszClassName = _T("CPanel");
    wc.style = NULL;
    RegisterClassEx(&wc);

    HWND Panelhwnd = CreateWindowEx(WS_EX_LAYERED, _T("CPanel"), _T(""), 
       WS_VISIBLE | WS_CHILD | WS_CLIPSIBLINGS| WS_CLIPCHILDREN,
       100, 10, 400, 400, MWhwnd, NULL, hInst, NULL);

    COLORREF crefKey = RGB(0, 255, 0);
    SetLayeredWindowAttributes(Panelhwnd, crefKey, 155, LWA_ALPHA);

    ShowWindow(MWhwnd, nCmdShow);   

In this example, I'm using a custom control but I've tried with a WC_BUTTON with same result. The control fails to draw. But I can make the main window transparent without a problem.

Using WINDOWS 10 and VS2015 and plain win32 (no MFC, ATL etc)

poby
  • 1,572
  • 15
  • 39
  • 1
    Consider working from [known-good code](https://github.com/Microsoft/Windows-classic-samples/tree/master/Samples/DirectCompositionLayeredChildWindow) – Hans Passant Mar 03 '17 at 02:32
  • 1
    Passing a color key value to `SetLayeredWindowAttributes` is meaningless, unless you also pass the `LWA_COLORKEY` flag. – IInspectable Mar 03 '17 at 10:27

1 Answers1

9

Thanks to the link @Hans suggested I have found the answer. A manifest entry is required that specifies at least Windows 8 compatibility (child layering support only started with Windows 8). The following should be included as a manifest file for anyone wanting to use layered child windows.

<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
  <compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1"> 
    <application>
      <!--The ID below indicates app support for Windows 8 -->
      <supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"/>
    </application>
  </compatibility>
  <dependency>
    <dependentAssembly>
        <assemblyIdentity
            type="win32"
            name="Microsoft.Windows.Common-Controls"
            version="6.0.0.0"
            processorArchitecture="*"
            publicKeyToken="6595b64144ccf1df"
            language="*"
        />
    </dependentAssembly>
  </dependency>
</assembly>

For the purposes of completeness, I've included the entire file but the relevant tag is the <compatibility> element specifying the GUID for Windows 8.

You may declare compatibility for other OS versions too, as described at the docs page "Targeting your application for Windows".

zett42
  • 25,437
  • 3
  • 35
  • 72
poby
  • 1,572
  • 15
  • 39
  • 1
    FYI, this is [documented behavior](https://learn.microsoft.com/en-us/windows/desktop/winmsg/using-windows#using-layered-windows) on MSDN: "*In order to use layered child windows, the application has to declare itself Windows 8-aware in the manifest.*" – Remy Lebeau Mar 21 '19 at 01:24