注意:目标是创建一个带有丙烯酸背景的窗口,可以由 OpenGL 绘制。欢迎任何可以实现这一目标的方法。
我已经能够按照本教程成功创建一个合成器。并打算根据本文档中给出的示例代码添加高斯模糊
在这篇文章之后,我从 Nuget 安装了 Win2D 并将文件复制Generated Files/winrt
到包含目录。(也尝试cppwinrt.exe
在.winmd
文件上运行。找不到答案中提到的“Win2D dll”)
这是我目前正在运行的代码:
void CompositionHost::BlurBackground() {
if (m_target.Root()) {
GaussianBlurEffect blurEffect{};
blurEffect.Name(L"Blur");
blurEffect.BlurAmount(1.0f);
blurEffect.BorderMode(EffectBorderMode::Hard);
blurEffect.Optimization(EffectOptimization::Balanced);
CompositionEffectSourceParameter sourceParameter = CompositionEffectSourceParameter(L"source");
blurEffect.Source(sourceParameter);
CompositionEffectFactory blurEffectFactory = m_compositor.CreateEffectFactory(blurEffect);
CompositionEffectBrush blurBrush = blurEffectFactory.CreateBrush();
CompositionBackdropBrush backDropBrush = m_compositor.CreateBackdropBrush();
blurBrush.SetSourceParameter(L"source", backDropBrush);
auto visuals = m_target.Root().as<ContainerVisual>().Children();
auto visual = m_compositor.CreateSpriteVisual();
auto element = m_compositor.CreateSpriteVisual();
element.Brush(blurBrush);
visuals.InsertAtTop(element);
visuals.InsertAtTop(visual);
}
}
执行时的错误GaussianBlurEffect blurEffect{};
:
Microsoft C++ exception: winrt::hresult_class_not_registered at memory location 0x00000076EEF8E248.
调用堆栈
> Project2.exe!winrt::throw_hresult(const winrt::hresult result) Line 4941 C++
Project2.exe!winrt::check_hresult(const winrt::hresult result) Line 5038 C++
Project2.exe!winrt::get_activation_factory<winrt::Windows::Foundation::IActivationFactory>(const winrt::param::hstring & name) Line 6078 C++
Project2.exe!winrt::impl::factory_cache_entry<winrt::Microsoft::Graphics::Canvas::Effects::GaussianBlurEffect,winrt::Windows::Foundation::IActivationFactory>::call<winrt::Microsoft::Graphics::Canvas::Effects::GaussianBlurEffect (__cdecl*)(winrt::Windows::Foundation::IActivationFactory const &)>(winrt::Microsoft::Graphics::Canvas::Effects::GaussianBlurEffect(*)(const winrt::Windows::Foundation::IActivationFactory &) && callback) Line 6308 C++
Project2.exe!winrt::impl::call_factory_cast<winrt::Microsoft::Graphics::Canvas::Effects::GaussianBlurEffect (__cdecl*)(winrt::Windows::Foundation::IActivationFactory const &),winrt::Microsoft::Graphics::Canvas::Effects::GaussianBlurEffect,winrt::Windows::Foundation::IActivationFactory,winrt::Microsoft::Graphics::Canvas::Effects::GaussianBlurEffect <lambda>(const winrt::Windows::Foundation::IActivationFactory &)>(winrt::Microsoft::Graphics::Canvas::Effects::GaussianBlurEffect::winrt::Microsoft::Graphics::Canvas::Effects::GaussianBlurEffect <lambda>(const winrt::Windows::Foundation::IActivationFactory &) && callback) Line 6369 C++
Project2.exe!winrt::Microsoft::Graphics::Canvas::Effects::GaussianBlurEffect::GaussianBlurEffect() Line 9041 C++
完整代码:
#pragma once
#ifndef UNICODE
#define UNICODE
#endif
#define BTN_ADD 1000
#include <SDKDDKVer.h>
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
//#include <D2d1_1.h>
//#include <D3d11_4.h>
//#include <Dwrite.h>
#include <Windows.Graphics.DirectX.Direct3D11.interop.h>
#include <Windows.ui.composition.interop.h>
#include <unknwn.h>
#include <DispatcherQueue.h>
#include <stdlib.h>
#include <malloc.h>
#include <memory.h>
#include <tchar.h>
#include <winrt/base.h>
#include <winrt/Windows.ApplicationModel.Core.h>
//#include <winrt/Windows.Foundation.h>
//#include <winrt/Windows.Graphics.h>
//#include <winrt/Windows.Graphics.DirectX.h>
#include <winrt/Windows.Graphics.DirectX.Direct3D11.h>
#include <winrt/Windows.UI.Composition.Desktop.h>
//#include <winrt/Windows.UI.Core.h>
//#include <winrt/Windows.UI.Input.h>
#include <winrt/Windows.Graphics.Effects.h>
#include <winrt/Microsoft.Graphics.Canvas.Effects.h>
#include <winrt/Windows.Graphics.Effects.h>
using namespace winrt;
//using namespace winrt::Windows::ApplicationModel::Core;
using namespace winrt::Windows::Foundation;
using namespace winrt::Windows::Foundation::Numerics;
//using namespace winrt::Windows::Graphics::DirectX;
//using namespace winrt::Windows::Graphics::DirectX::Direct3D11;
using namespace winrt::Windows::UI;
using namespace winrt::Windows::UI::Composition;
using namespace winrt::Windows::UI::Composition::Desktop;
using namespace winrt::Windows::UI::Core;
using namespace winrt::Windows::System;
using namespace winrt::Microsoft::Graphics::Canvas::Effects;
namespace abi
{
using namespace ABI::Windows::Foundation;
using namespace ABI::Windows::Graphics::DirectX;
using namespace ABI::Windows::UI::Composition;
}
class CompositionHost
{
public:
~CompositionHost();
static CompositionHost* GetInstance();
void Initialize(HWND hwnd);
void AddElement(float size, float x, float y);
void BlurBackground();
private:
CompositionHost();
void EnsureDispatcherQueue();
void CreateDesktopWindowTarget(HWND window);
void CreateCompositionRoot();
winrt::Windows::UI::Composition::Compositor m_compositor{ nullptr };
winrt::Windows::System::DispatcherQueueController m_dispatcherQueueController{ nullptr };
winrt::Windows::UI::Composition::Desktop::DesktopWindowTarget m_target{ nullptr };
};
CompositionHost* CompositionHost::GetInstance()
{
static CompositionHost instance;
return &instance;
}
void CompositionHost::Initialize(HWND hwnd)
{
EnsureDispatcherQueue();
m_compositor = Compositor();
CreateDesktopWindowTarget(hwnd);
CreateCompositionRoot();
}
void CompositionHost::EnsureDispatcherQueue()
{
namespace abi = ABI::Windows::System;
//if (m_dispatcherQueueController == nullptr)
{
DispatcherQueueOptions options
{
sizeof(DispatcherQueueOptions), /* dwSize */
DQTYPE_THREAD_CURRENT, /* threadType */
DQTAT_COM_ASTA /* apartmentType */
};
winrt::Windows::System::DispatcherQueueController controller{ nullptr };
//auto test1 = &m_dispatcherQueueController;
//int t = CreateDispatcherQueueController(options, (abi::IDispatcherQueueController **)&test1);
int t = CreateDispatcherQueueController(options, reinterpret_cast<abi::IDispatcherQueueController**>(put_abi(controller)));
m_dispatcherQueueController = controller;
int p = 1;
}
}
void CompositionHost::CreateDesktopWindowTarget(HWND window)
{
namespace abi = ABI::Windows::UI::Composition::Desktop;
auto interop = m_compositor.as<abi::ICompositorDesktopInterop>();
DesktopWindowTarget target{ nullptr };
check_hresult(interop->CreateDesktopWindowTarget(window, false, reinterpret_cast<abi::IDesktopWindowTarget**>(put_abi(target))));
m_target = target;
}
void CompositionHost::CreateCompositionRoot()
{
auto root = m_compositor.CreateContainerVisual();
root.RelativeSizeAdjustment({ 1.0f, 1.0f });
root.Offset({ 124, 12, 0 });
m_target.Root(root);
}
void CompositionHost::AddElement(float size, float x, float y)
{
if (m_target.Root())
{
auto visuals = m_target.Root().as<ContainerVisual>().Children();
auto visual = m_compositor.CreateSpriteVisual();
auto element = m_compositor.CreateSpriteVisual();
uint8_t r = (double)(double)(rand() % 255);;
uint8_t g = (double)(double)(rand() % 255);;
uint8_t b = (double)(double)(rand() % 255);;
element.Brush(m_compositor.CreateColorBrush({ 255, r, g, b }));
element.Size({ size, size });
element.Offset({ x, y, 0.0f, });
auto animation = m_compositor.CreateVector3KeyFrameAnimation();
auto bottom = (float)600 - element.Size().y;
animation.InsertKeyFrame(1, { element.Offset().x, bottom, 0 });
using timeSpan = std::chrono::duration<int, std::ratio<1, 1>>;
std::chrono::seconds duration(2);
std::chrono::seconds delay(3);
animation.Duration(timeSpan(duration));
animation.DelayTime(timeSpan(delay));
element.StartAnimation(L"Offset", animation);
visuals.InsertAtTop(element);
visuals.InsertAtTop(visual);
}
}
void CompositionHost::BlurBackground() {
if (m_target.Root()) {
GaussianBlurEffect blurEffect;
winrt::hstring blurStr = winrt::hstring(L"Blur");
blurEffect.Name(blurStr);
blurEffect.BlurAmount(1.0f);
blurEffect.BorderMode(EffectBorderMode::Hard);
blurEffect.Optimization(EffectOptimization::Balanced);
CompositionEffectSourceParameter sourceParameter = CompositionEffectSourceParameter(L"source");
blurEffect.Source(sourceParameter);
CompositionEffectFactory blurEffectFactory = m_compositor.CreateEffectFactory(blurEffect);
CompositionEffectBrush blurBrush = blurEffectFactory.CreateBrush();
CompositionBackdropBrush backDropBrush = m_compositor.CreateBackdropBrush();
blurBrush.SetSourceParameter(L"source", backDropBrush);
auto visuals = m_target.Root().as<ContainerVisual>().Children();
auto visual = m_compositor.CreateSpriteVisual();
auto element = m_compositor.CreateSpriteVisual();
element.Brush(blurBrush);
visuals.InsertAtTop(element);
visuals.InsertAtTop(visual);
}
}
CompositionHost::CompositionHost()
{
}
CompositionHost::~CompositionHost()
{
}
CompositionHost* compHost = CompositionHost::GetInstance();
HWND hwnd;
LRESULT CALLBACK WindowProc(HWND, UINT, WPARAM, LPARAM);
int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PWSTR pCmdLine, int nCmdShow)
{
// Register the window class.
const wchar_t CLASS_NAME[] = L"Sample Window Class";
WNDCLASS wc = { };
{
wc.lpfnWndProc = WindowProc;
wc.hInstance = hInstance;
wc.lpszClassName = CLASS_NAME;
RegisterClass(&wc);
// Create the window.
hwnd = CreateWindowEx(
WS_EX_NOREDIRECTIONBITMAP, // Optional window styles.
CLASS_NAME, // Window class
L"Learn to Program Windows", // Window text
WS_OVERLAPPEDWINDOW, // Window style
// Size and position
CW_USEDEFAULT, CW_USEDEFAULT, 900, 672,
NULL, // Parent window
NULL, // Menu
hInstance, // Instance handle
NULL // Additional application data
);
if (hwnd == NULL)
{
return 0;
}
ShowWindow(hwnd, nCmdShow);
UpdateWindow(hwnd);
}
compHost = CompositionHost::GetInstance();
MSG msg = { };
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return 0;
}
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
case WM_CREATE:
{
compHost->Initialize(hwnd);
srand(time(nullptr));
CreateWindow(TEXT("button"), TEXT("Add element"),
WS_VISIBLE | WS_CHILD | BS_PUSHBUTTON,
12, 12, 100, 50,
hwnd, (HMENU)BTN_ADD, nullptr, nullptr);
}
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
case WM_PAINT:
{
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hwnd, &ps);
//FillRect(hdc, &ps.rcPaint, (HBRUSH) (COLOR_WINDOW+1));
EndPaint(hwnd, &ps);
}
break;
case WM_COMMAND: // on Button click
{
//double size = (double)(rand() % 150 + 50);
//double x = (double)(rand() % 600);
//double y = (double)(rand() % 200);
//compHost->AddElement(size, x, y);
compHost->BlurBackground();
break;
}
}
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}