DirectComposition click through in transparent areas
I have an application with DirectComposition and Direct2D that I do have a window bigger than the drawings to handle somethings like shadows underneath the rectangles. The issue that I'm having is in the transparent areas, the click-through is not working as intended. I've tried to change the WM_NCHITTEST to something like this:
case WM_NCHITTEST: {
POINT pt = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) };
ScreenToClient(hWindow, &pt);
if (!IsPointInRoundedRect(pt.x, pt.y, drawResources.roundedRect)) {
return HTNOWHERE;
}
return HTCLIENT;
}
And even tried to return HTNOWHERE in all cases, but still without success.
void Candlelight_Window::Initialize(WNDPROC windowProc, HINSTANCE hInstance, LPCSTR className, float width, float height, SharedResources *pSharedResources) {
WNDCLASS windowClass = { 0 };
windowClass.style = CS_HREDRAW | CS_VREDRAW;
windowClass.lpfnWndProc = windowProc;
windowClass.cbClsExtra = 0;
windowClass.cbWndExtra = 0;
windowClass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
windowClass.hCursor = LoadCursor(NULL, IDC_ARROW);
windowClass.hbrBackground = NULL;
windowClass.lpszMenuName = NULL;
windowClass.lpszClassName = className;
RegisterClass(&windowClass);
RECT rect;
MONITORINFO monitorInfo;
monitorInfo.cbSize = sizeof(MONITORINFO);
HWND activeWindow = GetForegroundWindow();
HMONITOR activeMonitor = MonitorFromWindow(activeWindow, MONITOR_DEFAULTTONEAREST);
int xPos = CW_USEDEFAULT;
int yPos = CW_USEDEFAULT;
if (GetMonitorInfoA(activeMonitor, &monitorInfo)) { // TODO: Make its own function
xPos = (monitorInfo.rcWork.right - width) / 2;
yPos = (monitorInfo.rcWork.bottom - height) / 2 - 150;
}
hWindow = CreateWindowEx(
WS_EX_NOREDIRECTIONBITMAP,
className,
nullptr, WS_POPUP,
xPos, yPos,
width, height,
nullptr, nullptr,
hInstance,
pSharedResources
);
float dpi = GetDpiForWindow(hWindow);
SetWindowPos( // TODO: Check if needed to still use SetWindowPos
hWindow,
HWND_TOP, 0, 0,
(int)(ceil(width * dpi / 96.f)),
(int)(ceil(height * dpi / 96.f)),
SWP_NOMOVE
);
ShowWindow(hWindow, true);
UpdateWindow(hWindow);
InvalidateRect(hWindow, NULL, TRUE);
}
Below is my Direct2D and DirectComposition setup function:
HRESULT WindowResources::Initialize(HWND hWindow, SharedResources *pSharedResources, D2D1_SIZE_U actualSize) {
HRESULT hResult = S_OK;
if (lastSize.width == actualSize.width && lastSize.height == actualSize.height)
return hResult;
if (pSwapchain) WIN_SAFE_RELEASE(pSwapchain);
if (pDeviceContext) WIN_SAFE_RELEASE(pDeviceContext);
if (pSurface) WIN_SAFE_RELEASE(pSurface);
DXGI_SWAP_CHAIN_DESC1 swapchainDesc = { 0 };
swapchainDesc.Width = actualSize.width;
swapchainDesc.Height = actualSize.height;
swapchainDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
swapchainDesc.SampleDesc.Count = 1;
swapchainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
swapchainDesc.BufferCount = 2;
swapchainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL;
swapchainDesc.AlphaMode = DXGI_ALPHA_MODE_PREMULTIPLIED;
hResult = pSharedResources->pDXGIFactory->CreateSwapChainForComposition(
pSharedResources->pDXGIDevice,
&swapchainDesc,
nullptr,
&pSwapchain
);
if (FAILED(hResult)) return hResult;
hResult = pSharedResources->pD2D1Device->CreateDeviceContext(
D2D1_DEVICE_CONTEXT_OPTIONS_NONE,
&pDeviceContext
);
if (FAILED(hResult)) return hResult;
hResult = pDeviceContext->QueryInterface(__uuidof(ID2D1DeviceContext5), (void**)&pDeviceContext5);
if (FAILED(hResult)) return hResult;
hResult = pSwapchain->GetBuffer(0, __uuidof(pSurface), (void**)&pSurface);
if (FAILED(hResult)) return hResult;
D2D1_BITMAP_PROPERTIES1 bitmapProps = {};
bitmapProps.pixelFormat.alphaMode = D2D1_ALPHA_MODE_PREMULTIPLIED;
bitmapProps.pixelFormat.format = DXGI_FORMAT_B8G8R8A8_UNORM;
bitmapProps.bitmapOptions = D2D1_BITMAP_OPTIONS_TARGET | D2D1_BITMAP_OPTIONS_CANNOT_DRAW;
bitmapProps.dpiX = 96;
bitmapProps.dpiY = 96;
hResult = pDeviceContext->CreateBitmapFromDxgiSurface(pSurface, bitmapProps, &pBitmap);
if (FAILED(hResult)) return hResult;
D2D1_BITMAP_PROPERTIES1 intermediateProps = {};
intermediateProps.pixelFormat = bitmapProps.pixelFormat;
intermediateProps.bitmapOptions = D2D1_BITMAP_OPTIONS_TARGET;
intermediateProps.dpiX = 96;
intermediateProps.dpiY = 96;
hResult = pDeviceContext->CreateBitmap(
actualSize,
nullptr, 0,
&intermediateProps,
&pIntermediateBitmap
);
if (FAILED(hResult)) return hResult;
pDeviceContext->SetTarget(pBitmap);
hResult = pSharedResources->pDCompositionDevice->CreateTargetForHwnd(hWindow, true, &pTarget);
if (FAILED(hResult)) return hResult;
hResult = pSharedResources->pDCompositionDevice->CreateVisual(&pVisual);
if (FAILED(hResult)) return hResult;
hResult = pVisual->SetContent(pSwapchain);
if (FAILED(hResult)) return hResult;
hResult = pTarget->SetRoot(pVisual);
if (FAILED(hResult)) return hResult;
lastSize = actualSize;
return hResult;
}
Is important to note that I've already used things like WS_EX_TRANSPARENT, but I had no success. With this one I even got the inverse behaviour, all my window as acting as transparent, but never got any WM_NCHITTEST event, so became unusable