除了 SetWindowCompositionAttribute 调用外,window 的模糊要求是什么?

What are the requirements for window to be blurred, except SetWindowCompositionAttribute call?

我有一个处理 windows 的 dll 库:您可以简单地创建 windows、绘制图形等。此外,该库还为您提供了为 Win7 和Win10.

我有两个几乎相同的库版本 - 一个没有源代码的旧版本,一个有源代码的新版本。

我正在 Win10 中编写一些应用程序并且一直在使用旧库,但现在决定编译新版本。正如我所说,它的工作原理几乎相同,除了模糊 - 它不起作用。这是客户端代码:

HWND hwnd; // here stored window created by library function

struct ACCENTPOLICY
{
  int na;
  int nf;
  int nc;
  int nA;
};
struct WINCOMPATTRDATA
{
  int na;
  PVOID pd;
  ULONG ul;
};

const HINSTANCE hm = LoadLibrary(L"user32.dll");
if (hm)
{
  typedef BOOL(WINAPI*pSetWindowCompositionAttribute)(HWND, WINCOMPATTRDATA*);

  const pSetWindowCompositionAttribute SetWindowCompositionAttribute = (pSetWindowCompositionAttribute)GetProcAddress(hm, "SetWindowCompositionAttribute");
  if (SetWindowCompositionAttribute)
  {
    ACCENTPOLICY policy = { 3, 0, 0, 0 }; // and even works 4,0,155,0 (Acrylic blur)
    WINCOMPATTRDATA data = { 19, &policy,sizeof(ACCENTPOLICY) };
    SetWindowCompositionAttribute(hwnd, &data);
  }
  FreeLibrary(hm);
}

它在旧库中完全有效,在新库中不起作用 - window 根本不透明,因此没有模糊。

详情

我正在调用我的库中的函数,它创建 window、returns hwnd,然后使用 alfa 设置背景颜色,然后是上面的 运行 代码。没有别的。

在我的资源中,window 创建为 CreateWindowEx 而没有 WS_EX_LAYERED。我尝试添加此标志,添加 DwmBlurBehindWindow 调用,添加 SetLayeredWindowAttributeLWA_ALPHALWA_COLORKEY,但我得到的唯一结果 - 透明,没有任何模糊。

这是来自 WM_PAINT 的一些代码:

hdc = BeginPaint(hwnd, &ps);
hdcc = CreateCompatibleDC(hdc);
BITMAPINFO bmi;
LPBYTE bits;

ZeroMemory(&bmi, sizeof(bmi));

bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bmi.bmiHeader.biWidth = ps.rcPaint.right - ps.rcPaint.left;
bmi.bmiHeader.biHeight = ps.rcPaint.bottom - ps.rcPaint.top;
bmi.bmiHeader.biPlanes = 1;
bmi.bmiHeader.biBitCount = 32;
bmi.bmiHeader.biCompression = BI_RGB;

bm = CreateDIBSection(hdcc, &bmi, DIB_RGB_COLORS, (void**)&bits, NULL, 0);

//All draws here. The first one is Gdi+ background draw with alfa brush

SetStretchBltMode(hdc, COLORONCOLOR);
SetStretchBltMode(hdcc, COLORONCOLOR);

StretchBlt(hdc, ps.rcPaint.left, ps.rcPaint.top, ps.rcPaint.right - ps.rcPaint.left, ps.rcPaint.bottom - ps.rcPaint.top, hdcc, 0, 0, ps.rcPaint.right - ps.rcPaint.left, ps.rcPaint.bottom - ps.rcPaint.top, SRCCOPY);
EndPaint(hwnd,&ps);

我错过了什么?


旧库,客户端中的相同代码:

新建库​​,DwmBlurBehindWindow调用,设置WS_EX_LAYEREDSetLayeredWindowAttribute调用没有任何效果,客户端代码相同:

新库,没有 DwmBlurBehindWindow,客户端中的相同代码:

我不太明白我做了什么,但现在可以了。

首先,我应该说,该库提供的不仅仅是功能,还有一个接口——抽象 class。

第二个-创建window的HWND实际上没有returns,因为创建window的函数是无效的。我通过 FindWindow().

找到了 window

GetLastError()SetWindowCompositionAttribute() 返回 6 之后,但是现在,如果它工作时 returns 10 - ERROR_BAD_ENVIRONMENT 10 (0xA) 环境不对。

此外,我在尝试调用 MessageBox() 以显示错误代码时遇到崩溃。即使我只是检查 hwnd 是否等于 NULL,程序也会崩溃。

总结

正如我在问题中提到的,我决定制作新版本,因为我想要一些新功能。 看起来,当前新dll 中的抽象接口class 与客户端中的不一样,但旧的dll 中是。我觉得问题出在这里。