Created
June 18, 2021 11:46
-
-
Save ADeltaX/c0e565a50d2cedb62dab5c13674cb8b5 to your computer and use it in GitHub Desktop.
DWM Thumbnail/VirtualDesktop USING Windows.UI.Composition
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <Unknwn.h> | |
#include <Windows.h> | |
#include <wrl\implements.h> | |
#include <comutil.h> | |
#include <dcomp.h> | |
#include <dwmapi.h> | |
#include <dxgi1_3.h> | |
#include <d3d11_2.h> | |
#include <d2d1_2.h> | |
#include <d2d1_2helper.h> | |
//For this part you need C++/WinRT extension | |
#include <winrt/Windows.Foundation.h> | |
#include <winrt/Windows.Foundation.Collections.h> | |
#include <winrt/Windows.UI.h> | |
#include <winrt/Windows.UI.Core.h> | |
#include <winrt/Windows.UI.Composition.h> | |
#include <winrt/Windows.UI.Composition.Desktop.h> | |
//This is for ABI | |
#include <windows.ui.composition.interop.h> | |
//Either use this or add in your linker configuration | |
#pragma comment(lib, "dxgi") | |
#pragma comment(lib, "d3d11") | |
#pragma comment(lib, "d2d1") | |
#pragma comment(lib, "dcomp") | |
#pragma comment(lib, "dwmapi") | |
#pragma comment(lib, "ole32") | |
//using namespace | |
using namespace winrt; | |
using namespace winrt::Windows::UI; | |
using namespace winrt::Windows::UI::Composition; | |
using namespace winrt::Windows::UI::Composition::Desktop; | |
using namespace winrt::Windows::UI::Core; | |
//-------------------- Definitions | |
enum THUMBNAIL_TYPE | |
{ | |
TT_DEFAULT = 0x0, | |
TT_SNAPSHOT = 0x1, | |
TT_ICONIC = 0x2, | |
TT_BITMAPPENDING = 0x3, | |
TT_BITMAP = 0x4 | |
}; | |
typedef HRESULT(WINAPI* DwmpCreateSharedThumbnailVisual)( | |
IN HWND hwndDestination, | |
IN HWND hwndSource, | |
IN DWORD dwThumbnailFlags, | |
IN DWM_THUMBNAIL_PROPERTIES* pThumbnailProperties, | |
IN VOID* pDCompDevice, | |
OUT VOID** ppVisual, | |
OUT PHTHUMBNAIL phThumbnailId); | |
typedef HRESULT(WINAPI* DwmpQueryWindowThumbnailSourceSize)( | |
IN HWND hwndSource, | |
IN BOOL fSourceClientAreaOnly, | |
OUT SIZE* pSize); | |
typedef HRESULT(WINAPI* DwmpQueryThumbnailType)( | |
IN HTHUMBNAIL hThumbnailId, | |
OUT THUMBNAIL_TYPE* thumbType); | |
//pre-cobalt/pre-iron | |
typedef HRESULT(WINAPI* DwmpCreateSharedVirtualDesktopVisual)( | |
IN HWND hwndDestination, | |
IN VOID* pDCompDevice, | |
OUT VOID** ppVisual, | |
OUT PHTHUMBNAIL phThumbnailId); | |
//cobalt/iron (20xxx+) | |
//No changes except for the function name. | |
typedef HRESULT(WINAPI* DwmpCreateSharedMultiWindowVisual)( | |
IN HWND hwndDestination, | |
IN VOID* pDCompDevice, | |
OUT VOID** ppVisual, | |
OUT PHTHUMBNAIL phThumbnailId); | |
//pre-cobalt/pre-iron | |
typedef HRESULT(WINAPI* DwmpUpdateSharedVirtualDesktopVisual)( | |
IN HTHUMBNAIL hThumbnailId, | |
IN HWND* phwndsInclude, | |
IN DWORD chwndsInclude, | |
IN HWND* phwndsExclude, | |
IN DWORD chwndsExclude, | |
OUT RECT* prcSource, | |
OUT SIZE* pDestinationSize); | |
//cobalt/iron (20xxx+) | |
//Change: function name + new DWORD parameter. | |
//Pass "1" in dwFlags. Feel free to explore other flags. | |
typedef HRESULT(WINAPI* DwmpUpdateSharedMultiWindowVisual)( | |
IN HTHUMBNAIL hThumbnailId, | |
IN HWND* phwndsInclude, | |
IN DWORD chwndsInclude, | |
IN HWND* phwndsExclude, | |
IN DWORD chwndsExclude, | |
OUT RECT* prcSource, | |
OUT SIZE* pDestinationSize, | |
IN DWORD dwFlags); | |
#define DWM_TNP_FREEZE 0x100000 | |
#define DWM_TNP_ENABLE3D 0x4000000 | |
#define DWM_TNP_DISABLE3D 0x8000000 | |
#define DWM_TNP_FORCECVI 0x40000000 | |
#define DWM_TNP_DISABLEFORCECVI 0x80000000 | |
//-------- CoreDispatcher | |
//Windows::UI::Core::IInternalCoreDispatcherStatic (14393+) | |
DECLARE_INTERFACE_IID_(IInternalCoreDispatcherStatic, IInspectable, "4B4D0861-D718-4F7C-BEC7-735C065F7C73") | |
{ | |
STDMETHOD(GetForCurrentThread)( | |
winrt::Windows::UI::Core::CoreDispatcher* ppDispatcher | |
) PURE; | |
STDMETHOD(GetOrCreateForCurrentThread)( | |
winrt::Windows::UI::Core::CoreDispatcher* ppDispatcher | |
) PURE; | |
}; | |
//-------- Interop Composition interfaces | |
//Windows::UI::Composition::HwndTarget (14393-15063) | |
DECLARE_INTERFACE_IID_(HwndTarget, IUnknown, "6677DA68-C80C-407A-A4D2-3AA118AD7C46") | |
{ | |
STDMETHOD(GetRoot)(THIS_ | |
OUT ABI::Windows::UI::Composition::IVisual** value) PURE; | |
STDMETHOD(SetRoot)(THIS_ | |
IN ABI::Windows::UI::Composition::IVisual * value) PURE; | |
}; | |
//Windows::UI::Composition::InteropCompositorTarget | |
DECLARE_INTERFACE_IID_(InteropCompositionTarget, IUnknown, "EACDD04C-117E-4E17-88F4-D1B12B0E3D89") | |
{ | |
STDMETHOD(SetRoot)(THIS_ | |
IN IDCompositionVisual * visual) PURE; | |
}; | |
//Windows::UI::Composition::IInteropCompositorPartner | |
DECLARE_INTERFACE_IID_(IInteropCompositorPartner, IUnknown, "e7894c70-af56-4f52-b382-4b3cd263dc6f") | |
{ | |
STDMETHOD(MarkDirty)(THIS_) PURE; | |
STDMETHOD(ClearCallback)(THIS_) PURE; | |
STDMETHOD(CreateManipulationTransform)(THIS_ | |
IN IDCompositionTransform * transform, | |
IN REFIID iid, | |
OUT VOID * *result) PURE; | |
STDMETHOD(RealClose)(THIS_) PURE; | |
}; | |
//Windows.UI.Composition.IInteropCompositorPartnerCallback | |
DECLARE_INTERFACE_IID_(IInteropCompositorPartnerCallback, IUnknown, "9bb59fc9-3326-4c32-bf06-d6b415ac2bc5") | |
{ | |
STDMETHOD(NotifyDirty)(THIS_) PURE; | |
STDMETHOD(NotifyDeferralState)(THIS_ | |
bool deferRequested) PURE; | |
}; | |
//Windows::UI::Composition::IInteropCompositorFactoryPartner | |
DECLARE_INTERFACE_IID_(IInteropCompositorFactoryPartner, IInspectable, "22118adf-23f1-4801-bcfa-66cbf48cc51b") | |
{ | |
STDMETHOD(CreateInteropCompositor)(THIS_ | |
IN IUnknown* renderingDevice, | |
IN IInteropCompositorPartnerCallback* callback, | |
IN REFIID iid, | |
OUT VOID** instance | |
) PURE; | |
STDMETHOD(CheckEnabled)(THIS_ | |
OUT bool* enableInteropCompositor, | |
OUT bool* enableExposeVisual | |
) PURE; | |
}; | |
//We also need these if you want to use MultiWindow/VirtualDesktop. | |
enum WINDOWCOMPOSITIONATTRIB | |
{ | |
WCA_UNDEFINED = 0x0, | |
WCA_NCRENDERING_ENABLED = 0x1, | |
WCA_NCRENDERING_POLICY = 0x2, | |
WCA_TRANSITIONS_FORCEDISABLED = 0x3, | |
WCA_ALLOW_NCPAINT = 0x4, | |
WCA_CAPTION_BUTTON_BOUNDS = 0x5, | |
WCA_NONCLIENT_RTL_LAYOUT = 0x6, | |
WCA_FORCE_ICONIC_REPRESENTATION = 0x7, | |
WCA_EXTENDED_FRAME_BOUNDS = 0x8, | |
WCA_HAS_ICONIC_BITMAP = 0x9, | |
WCA_THEME_ATTRIBUTES = 0xA, | |
WCA_NCRENDERING_EXILED = 0xB, | |
WCA_NCADORNMENTINFO = 0xC, | |
WCA_EXCLUDED_FROM_LIVEPREVIEW = 0xD, | |
WCA_VIDEO_OVERLAY_ACTIVE = 0xE, | |
WCA_FORCE_ACTIVEWINDOW_APPEARANCE = 0xF, | |
WCA_DISALLOW_PEEK = 0x10, | |
WCA_CLOAK = 0x11, | |
WCA_CLOAKED = 0x12, | |
WCA_ACCENT_POLICY = 0x13, | |
WCA_FREEZE_REPRESENTATION = 0x14, | |
WCA_EVER_UNCLOAKED = 0x15, | |
WCA_VISUAL_OWNER = 0x16, | |
WCA_HOLOGRAPHIC = 0x17, | |
WCA_EXCLUDED_FROM_DDA = 0x18, | |
WCA_PASSIVEUPDATEMODE = 0x19, | |
WCA_LAST = 0x1A, | |
}; | |
typedef struct WINDOWCOMPOSITIONATTRIBDATA | |
{ | |
WINDOWCOMPOSITIONATTRIB Attrib; | |
void* pvData; | |
DWORD cbData; | |
}; | |
typedef BOOL(WINAPI* SetWindowCompositionAttribute)( | |
IN HWND hwnd, | |
IN WINDOWCOMPOSITIONATTRIBDATA* pwcad); | |
//------------------------- Getting functions | |
DwmpQueryThumbnailType lDwmpQueryThumbnailType; | |
DwmpCreateSharedThumbnailVisual lDwmpCreateSharedThumbnailVisual; | |
DwmpQueryWindowThumbnailSourceSize lDwmpQueryWindowThumbnailSourceSize; | |
//PRE-IRON | |
DwmpCreateSharedVirtualDesktopVisual lDwmpCreateSharedVirtualDesktopVisual; | |
DwmpUpdateSharedVirtualDesktopVisual lDwmpUpdateSharedVirtualDesktopVisual; | |
//20xxx+ | |
DwmpCreateSharedMultiWindowVisual lDwmpCreateSharedMultiWindowVisual; | |
DwmpUpdateSharedMultiWindowVisual lDwmpUpdateSharedMultiWindowVisual; | |
SetWindowCompositionAttribute lSetWindowCompositionAttribute; | |
bool InitPrivateDwmAPIs() | |
{ | |
auto dwmapiLib = LoadLibrary(L"dwmapi.dll"); | |
if (!dwmapiLib) | |
return false; | |
lDwmpQueryThumbnailType = (DwmpQueryThumbnailType)GetProcAddress(dwmapiLib, MAKEINTRESOURCEA(114)); | |
lDwmpCreateSharedThumbnailVisual = (DwmpCreateSharedThumbnailVisual)GetProcAddress(dwmapiLib, MAKEINTRESOURCEA(147)); | |
lDwmpQueryWindowThumbnailSourceSize = (DwmpQueryWindowThumbnailSourceSize)GetProcAddress(dwmapiLib, MAKEINTRESOURCEA(162)); | |
//PRE-IRON | |
lDwmpCreateSharedVirtualDesktopVisual = (DwmpCreateSharedVirtualDesktopVisual)GetProcAddress(dwmapiLib, MAKEINTRESOURCEA(163)); | |
lDwmpUpdateSharedVirtualDesktopVisual = (DwmpUpdateSharedVirtualDesktopVisual)GetProcAddress(dwmapiLib, MAKEINTRESOURCEA(164)); | |
//20xxx+ | |
lDwmpCreateSharedMultiWindowVisual = (DwmpCreateSharedMultiWindowVisual)GetProcAddress(dwmapiLib, MAKEINTRESOURCEA(163)); | |
lDwmpUpdateSharedMultiWindowVisual = (DwmpUpdateSharedMultiWindowVisual)GetProcAddress(dwmapiLib, MAKEINTRESOURCEA(164)); | |
if (false) //Just a placeholder, don't. | |
return false; | |
return true; | |
} | |
bool InitPrivateUser32APIs() | |
{ | |
auto user32Lib = LoadLibrary(L"user32.dll"); | |
if (!user32Lib) | |
return false; | |
lSetWindowCompositionAttribute = (SetWindowCompositionAttribute)GetProcAddress(user32Lib, "SetWindowCompositionAttribute"); | |
if (!lSetWindowCompositionAttribute) | |
return false; | |
return true; | |
} | |
//--------------------- Create Device func | |
using namespace Microsoft::WRL; | |
ComPtr<ID3D11Device> direct3dDevice; | |
ComPtr<IDXGIDevice2> dxgiDevice; | |
ComPtr<ID2D1Factory2> d2dFactory2; | |
ComPtr<ID2D1Device> d2dDevice; | |
ComPtr<IDCompositionDesktopDevice> dcompDevice; | |
bool CreateDevice() | |
{ | |
if (D3D11CreateDevice(0, //Adapter | |
D3D_DRIVER_TYPE_HARDWARE, | |
NULL, | |
D3D11_CREATE_DEVICE_BGRA_SUPPORT, | |
NULL, | |
0, | |
D3D11_SDK_VERSION, | |
direct3dDevice.GetAddressOf(), | |
nullptr, | |
nullptr | |
) != S_OK) | |
{ | |
//Maybe try creating with D3D_DRIVER_TYPE_WARP before returning false. | |
//Always listen to device changes. | |
return false; | |
} | |
if (direct3dDevice->QueryInterface(dxgiDevice.GetAddressOf()) != S_OK) | |
{ | |
return false; | |
} | |
if (D2D1CreateFactory( | |
D2D1_FACTORY_TYPE::D2D1_FACTORY_TYPE_SINGLE_THREADED, | |
__uuidof(ID2D1Factory2), | |
(void**)d2dFactory2.GetAddressOf()) != S_OK) | |
{ | |
return false; | |
} | |
if (d2dFactory2->CreateDevice( | |
dxgiDevice.Get(), | |
d2dDevice.GetAddressOf()) != S_OK) | |
{ | |
return false; | |
} | |
return true; | |
} | |
//------------------------ Create window func | |
LRESULT CALLBACK MyWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) | |
{ | |
switch (message) | |
{ | |
case WM_CLOSE: | |
PostQuitMessage(0); | |
break; | |
default: | |
break; | |
} | |
return DefWindowProc(hwnd, message, wParam, lParam); | |
} | |
HWND CreateWindowInternal(LPCWSTR lptitleName, LPCWSTR lpclassName, DWORD dwExStyle, DWORD dwStyle) | |
{ | |
HINSTANCE hInstance = GetModuleHandle(NULL); | |
WNDCLASS wc = { }; | |
wc.lpfnWndProc = MyWndProc; | |
wc.hInstance = hInstance; | |
wc.cbWndExtra = 0; | |
wc.lpszClassName = lpclassName; | |
if (!RegisterClass(&wc)) | |
return nullptr; | |
const auto hwndParent = CreateWindowEx(dwExStyle, lpclassName, lptitleName, | |
dwStyle, CW_USEDEFAULT, CW_USEDEFAULT, 1000, 640, | |
nullptr, nullptr, hInstance, NULL); | |
//This part is needed ONLY if you plan on using MultiWindow/VirtualDesktop functions. | |
BOOL enable = TRUE; | |
WINDOWCOMPOSITIONATTRIBDATA wData{}; | |
wData.Attrib = WCA_EXCLUDED_FROM_LIVEPREVIEW; | |
wData.pvData = &enable; | |
wData.cbData = sizeof(BOOL); | |
lSetWindowCompositionAttribute(hwndParent, &wData); | |
if (!hwndParent) | |
return nullptr; | |
return hwndParent; | |
} | |
void DemoCreateWindowThumbnail(HWND myWnd, IDCompositionVisual2** ppWindowVisual, SIZE* thumbSize) | |
{ | |
//A window target of your choice | |
HWND targetWindow = (HWND)FindWindow(L"Shell_TrayWnd", NULL); | |
//Query the exact thumbnail source size | |
SIZE windowSize{}; | |
lDwmpQueryWindowThumbnailSourceSize(targetWindow, FALSE, &windowSize); | |
*thumbSize = windowSize; | |
//Pretty explanatory and also documented by Microsoft | |
DWM_THUMBNAIL_PROPERTIES thumb{}; | |
thumb.dwFlags = DWM_TNP_SOURCECLIENTAREAONLY | DWM_TNP_VISIBLE | DWM_TNP_RECTDESTINATION | DWM_TNP_RECTSOURCE | DWM_TNP_OPACITY | DWM_TNP_ENABLE3D; | |
thumb.opacity = 255; | |
thumb.fVisible = TRUE; | |
thumb.fSourceClientAreaOnly = FALSE; | |
thumb.rcDestination = RECT{ 0, 0, windowSize.cx, windowSize.cy }; | |
thumb.rcSource = RECT{ 0, 0, windowSize.cx, windowSize.cy }; | |
HTHUMBNAIL hThumbWindow; | |
//Create the shared visual! | |
auto res = lDwmpCreateSharedThumbnailVisual(myWnd, targetWindow, 2, &thumb, | |
dcompDevice.Get(), (void**)ppWindowVisual, &hThumbWindow); | |
} | |
void DemoCreateMultiWindowThumbnail(HWND myWnd, IDCompositionVisual2** ppVirtualDesktopVisual, SIZE* thumbSize) | |
{ | |
HTHUMBNAIL hThumbVirtualDesktop; | |
auto virtualDeskRes = lDwmpCreateSharedMultiWindowVisual(myWnd, dcompDevice.Get(), | |
(void**)ppVirtualDesktopVisual, &hThumbVirtualDesktop); | |
auto monitorSize = RECT{ 0, 0, 1920, 1080 }; | |
auto targetSize = SIZE{ 960, 540 }; | |
*thumbSize = targetSize; | |
HWND hwndTest = (HWND)0x1; //Exclude from the list what you want to exclude | |
HWND* excludeArray = new HWND[1]; | |
excludeArray[0] = hwndTest; | |
//The include list is useless as it will include every window in every case. | |
//You can only play with the exclusion list. | |
auto virtualDesktopUpdate = lDwmpUpdateSharedMultiWindowVisual(hThumbVirtualDesktop, NULL, 0, | |
excludeArray, 1, &monitorSize, &targetSize, 1); //Last parameter has to be "1" | |
//use lDwmpUpdateSharedVirtualDesktopVisual for 19043 or older | |
} | |
//------------------------ Windows.UI.Composit* / IDComposition* interop | |
bool InitializeInteropCompositor(HWND hwnd, IUnknown* d2dDevice, Compositor* compositor, IUnknown** compositionTarget, ContainerVisual* rootVisual) | |
{ | |
auto interopCompositorFactory = winrt::get_activation_factory<Compositor, IInteropCompositorFactoryPartner>(); | |
com_ptr<IInteropCompositorPartner> interopCompositor; | |
auto interopRes = interopCompositorFactory->CreateInteropCompositor(d2dDevice, NULL, winrt::guid_of<IInteropCompositorPartner>(), interopCompositor.put_void()); | |
if (interopRes != S_OK) | |
return false; | |
//Get as Compositor and as IDCompositionDevice | |
auto m_compositor = interopCompositor.as<Compositor>(); | |
dcompDevice = interopCompositor.as<IDCompositionDesktopDevice>().detach(); | |
//Create a target for our window | |
com_ptr<IDCompositionTarget> dcompTarget; | |
auto res = dcompDevice->CreateTargetForHwnd(hwnd, TRUE, dcompTarget.put()); | |
if (res != S_OK) | |
return false; | |
//Create a container visual to hold all our visuals and then set it as root. | |
//InteropCompositionTarget derives from DesktopWindowTarget which ultimately derives from CompositionTarget - 16299+ | |
//InteropCompositionTarget derives from HwndTarget - 14393-15063 | |
auto containerVisual = m_compositor.CreateContainerVisual(); | |
auto compTarget = dcompTarget.try_as<CompositionTarget>(); | |
if (compTarget) | |
{ | |
compTarget.Root(containerVisual); | |
*compositionTarget = compTarget.as<IUnknown>().detach(); | |
} | |
else | |
{ | |
//We are on 15063 or 14393 | |
//Get "raw" pointer to IVisual | |
winrt::com_ptr<ABI::Windows::UI::Composition::IVisual> visualAbi; | |
winrt::get_unknown(containerVisual)->QueryInterface(visualAbi.put()); | |
auto hwndTarget = dcompTarget.as<HwndTarget>(); | |
hwndTarget->SetRoot(visualAbi.get()); | |
*compositionTarget = hwndTarget.as<IUnknown>().detach(); | |
} | |
*compositor = m_compositor; | |
*rootVisual = containerVisual; | |
return true; | |
} | |
Visual DCompVisualToVisual(Compositor compositor, IDCompositionVisual2* dcompVisual, SIZE dcompVisualSize) | |
{ | |
winrt::com_ptr<IDCompositionVisual2> dcompVisualContainer; | |
compositor.as<IDCompositionDesktopDevice>()->CreateVisual(dcompVisualContainer.put()); | |
dcompVisualContainer->AddVisual(dcompVisual, TRUE, nullptr); | |
auto visualContainer = dcompVisualContainer.as<Visual>(); | |
visualContainer.Size({ (float)dcompVisualSize.cx, (float)dcompVisualSize.cy }); | |
return visualContainer; | |
} | |
void CreateAnimationForVisual(Compositor compositor, Visual visual) | |
{ | |
auto animationScale = compositor.CreateVector3KeyFrameAnimation(); | |
auto spring = compositor.CreateCubicBezierEasingFunction({ .41F, .51999998F }, { .00F, .94F }); | |
animationScale.InsertKeyFrame(.15F, { 1.F, 1.F, 1.F }, spring); | |
animationScale.InsertKeyFrame(.3F, { .5F, .5F, .5F }, spring); | |
animationScale.InsertKeyFrame(.6F, { .5F, .5F, .5F }, spring); | |
animationScale.InsertKeyFrame(.85F, { 1.F, 1.F, 1.F }, spring); | |
animationScale.Duration(std::chrono::milliseconds(3000)); | |
animationScale.IterationBehavior(AnimationIterationBehavior::Forever); | |
visual.CenterPoint({ visual.Size() / 2, 0.f }); | |
visual.StartAnimation(L"Scale", animationScale); | |
} | |
CoreDispatcher GetOrCreateCoreDispatcher() | |
{ | |
//CoreDispatcher internally creates a DispatcherQueue if it doesn't exist (and if you are on 15063 or newer) | |
auto dispatcher = winrt::try_get_activation_factory<CoreDispatcher, IInternalCoreDispatcherStatic>(); | |
//On 10586 there isn't a way to create a CoreDispatcher (unless you create a CoreWindow, lol.) | |
if (!dispatcher) | |
return nullptr; | |
CoreDispatcher coreDispatcher{ nullptr }; | |
dispatcher->GetOrCreateForCurrentThread(&coreDispatcher); | |
return coreDispatcher; | |
} | |
int APIENTRY wWinMain(HINSTANCE hInstance, | |
HINSTANCE hPrevInstance, | |
LPWSTR lpCmdLine, | |
int nCmdShow) | |
{ | |
init_apartment(); | |
if (!InitPrivateDwmAPIs() || | |
!InitPrivateUser32APIs() || | |
!CreateDevice()) | |
return 0; | |
auto myWnd = CreateWindowInternal(L"Noice window", L"DwmThumbExampleClass", WS_EX_OVERLAPPEDWINDOW | WS_EX_NOREDIRECTIONBITMAP, WS_OVERLAPPEDWINDOW); | |
ShowWindow(myWnd, SW_SHOW); | |
//Create Compositor, ContainerVisual, *target, and set dcompDevice. | |
Compositor compositor{ nullptr }; | |
ContainerVisual root{ nullptr }; | |
IUnknown* target{ nullptr }; | |
auto resInit = InitializeInteropCompositor(myWnd, d2dDevice.Get(), &compositor, &target, &root); | |
ComPtr<IDCompositionVisual2> thumbVisual; | |
SIZE thumbVisualSize{}; | |
DemoCreateWindowThumbnail(myWnd, thumbVisual.GetAddressOf(), &thumbVisualSize); | |
//ComPtr<IDCompositionVisual2> thumbVisual; | |
//SIZE thumbVisualSize{}; | |
//DemoCreateMultiWindowThumbnail(myWnd, thumbVisual.GetAddressOf(), &thumbVisualSize); | |
//Wrap the IDCompositionVisual into a Windows.UI.Composition.Visual and insert it into the Composition root | |
auto thumbCompositionVisual = DCompVisualToVisual(compositor, thumbVisual.Get(), thumbVisualSize); | |
root.Children().InsertAtTop(thumbCompositionVisual); | |
//Set an animation for the visual! | |
CreateAnimationForVisual(compositor, thumbCompositionVisual); | |
CoreDispatcher coreDispatcher = GetOrCreateCoreDispatcher(); | |
coreDispatcher.ProcessEvents(CoreProcessEventsOption::ProcessUntilQuit); | |
//ComPtr automatically releases for you. | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment