0

I was working on a project which uses DirectX and Direct Composition. I am trying to create a similar effect like windows acrylic blur. Using direct composition I was able to apply the blur effect, saturation and blending to a given input. windows acrylic blur use the content behind the window as input to blur but it is not possible in win32 so I decided to use desktop background as input for my blur function. But the problem is that I was able to crop the background based on window position but if I moved the window to new position the bitmap is cropped based on the new RECT of window but there is flickering while moving to new position.

Here is the previews:

Here is the screenshot of actual window:

Window

Here the red box contains the bitmap saturated and cropped using the window RECT (See the color difference).

Here is a simple code to reproduce the problem:

#ifndef UNICODE
#define UNICODE
#endif 
#include <windows.h>
#include <wrl.h>
#include <dxgi1_3.h>
#include <d3d11_2.h>
#include <d2d1_2.h>
#include <d2d1_1.h>
#include <d2d1_2helper.h>
#include <dcomp.h>
#include <dwmapi.h>
#include <wincodec.h>

#pragma comment(lib, "dxgi")
#pragma comment(lib, "d3d11")
#pragma comment(lib, "d2d1")
#pragma comment(lib, "dwmapi")
#pragma comment(lib, "dxguid")
#pragma comment(lib, "dcomp")

using namespace Microsoft::WRL;

LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);

ComPtr<ID3D11Device> direct3dDevice;
ComPtr<IDXGIDevice> dxgiDevice;
ComPtr<IDXGIFactory2> dxFactory;
ComPtr<IDXGISwapChain1> swapChain;
ComPtr<ID2D1Factory2> d2Factory;
ComPtr<ID2D1Device1> d2Device;
ComPtr<IDCompositionTarget> target;
ComPtr<ID2D1DeviceContext> dc;


//Direct Composition Device,Visual
ComPtr<IDCompositionDevice> dcompDevice;
ComPtr<IDCompositionDevice3> dcompDevice3;
ComPtr<IDCompositionVisual> visual;

//Direct Composition Effects
ComPtr<IDCompositionGaussianBlurEffect> blur;
ComPtr<IDCompositionSaturationEffect> saturation;

IWICImagingFactory* d2dWICFactory = NULL;
IWICBitmapDecoder* d2dDecoder = NULL;
IWICFormatConverter* d2dConverter = NULL;
IWICBitmapFrameDecode* d2dBmpSrc = NULL;
ID2D1Bitmap* d2dBmp = NULL;

HWND hwnd;
RECT windowRect;

void LoadBackground();
void Render();

struct ComException
{
    HRESULT result;
    ComException(HRESULT const value) : result(value)
    {}
};
void HR(HRESULT const result)
{
    if (S_OK != result)
    {
        throw ComException(result);
    }
}

void CreateDevice(HWND hwnd)
{
    
    HR(D3D11CreateDevice(nullptr,    // Adapter
        D3D_DRIVER_TYPE_HARDWARE,
        nullptr,    // Module
        D3D11_CREATE_DEVICE_BGRA_SUPPORT,
        nullptr, 0, // Highest available feature level
        D3D11_SDK_VERSION,
        &direct3dDevice,
        nullptr,    // Actual feature level
        nullptr));  // Device context

    HR(direct3dDevice.As(&dxgiDevice));
    HR(CreateDXGIFactory2(
        DXGI_CREATE_FACTORY_DEBUG,
        __uuidof(dxFactory),
        reinterpret_cast<void**>(dxFactory.GetAddressOf())));

    DXGI_SWAP_CHAIN_DESC1 description = {};

    description.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
    description.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
    description.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL;
    description.BufferCount = 2;
    description.SampleDesc.Count = 1;
    description.AlphaMode = DXGI_ALPHA_MODE_PREMULTIPLIED;

    RECT rect = {};
    GetClientRect(hwnd, &rect);
    description.Width = rect.right - rect.left;
    description.Height = rect.bottom - rect.top;
 
    HR(dxFactory->CreateSwapChainForComposition(dxgiDevice.Get(),&description,nullptr,swapChain.GetAddressOf()));

    D2D1_FACTORY_OPTIONS const options = { D2D1_DEBUG_LEVEL_INFORMATION };

    HR(D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED,options,d2Factory.GetAddressOf()));

    HR(d2Factory->CreateDevice(dxgiDevice.Get(),d2Device.GetAddressOf()));

    HR(d2Device->CreateDeviceContext(D2D1_DEVICE_CONTEXT_OPTIONS_NONE,dc.GetAddressOf()));

    ComPtr<IDXGISurface2> surface;
    HR(swapChain->GetBuffer(0,__uuidof(surface),reinterpret_cast<void**>(surface.GetAddressOf())));

    D2D1_BITMAP_PROPERTIES1 properties = {};
    properties.pixelFormat.alphaMode = D2D1_ALPHA_MODE_PREMULTIPLIED;
    properties.pixelFormat.format = DXGI_FORMAT_B8G8R8A8_UNORM;
    properties.bitmapOptions = D2D1_BITMAP_OPTIONS_TARGET | D2D1_BITMAP_OPTIONS_CANNOT_DRAW;

    ComPtr<ID2D1Bitmap1> bitmap;
    HR(dc->CreateBitmapFromDxgiSurface(surface.Get(),properties,bitmap.GetAddressOf()));
    LoadBackground(); // loads my desktop background to d2dBmp using WIC
    dc->SetTarget(bitmap.Get());

    Render(); //render once

   //Creating Direct Compostion Devices and Visual

    HR(DCompositionCreateDevice(dxgiDevice.Get(),__uuidof(dcompDevice),reinterpret_cast<void**>(dcompDevice.GetAddressOf())));
    HR(DCompositionCreateDevice3(dxgiDevice.Get(), __uuidof(dcompDevice),reinterpret_cast<void**>(dcompDevice.GetAddressOf())));
    HR(dcompDevice->QueryInterface(__uuidof(IDCompositionDevice3), (LPVOID*)&dcompDevice3)); // use IDCompositionDevice3 here
   
    HR(dcompDevice3->CreateSaturationEffect(saturation.GetAddressOf()));
    HR(dcompDevice3->CreateGaussianBlurEffect(blur.GetAddressOf()));

    //setting effect properties
    blur->SetStandardDeviation(30.0f); // blur amount
    blur->SetBorderMode(D2D1_BORDER_MODE_HARD);
    saturation->SetSaturation(2.0f); //saturationamount

    HR(dcompDevice->CreateTargetForHwnd(hwnd,true,target.GetAddressOf()));

    blur->SetInput(NULL, bitmap.Get(), NULL);
    saturation->SetInput(NULL, blur.Get(), NULL);

    HR(dcompDevice->CreateVisual(visual.GetAddressOf()));
    HR(visual->SetContent(swapChain.Get()));
    visual->SetEffect(saturation.Get());
    HR(target->SetRoot(visual.Get()));
    HR(dcompDevice->Commit());

}

void LoadBackground()
{
    HR(CoCreateInstance(CLSID_WICImagingFactory, NULL, CLSCTX_INPROC_SERVER, __uuidof(IWICImagingFactory), (void**)(&d2dWICFactory)));
    HR(d2dWICFactory->CreateDecoderFromFilename(L"C:/Users/selas/Downloads/wallpaper.jpg", NULL, GENERIC_READ, WICDecodeMetadataCacheOnLoad, &d2dDecoder));
    HR(d2dWICFactory->CreateFormatConverter(&d2dConverter));
    HR(d2dDecoder->GetFrame(0, &d2dBmpSrc));
    HR(d2dConverter->Initialize(d2dBmpSrc, GUID_WICPixelFormat32bppPBGRA, WICBitmapDitherTypeNone, NULL, 0.f, WICBitmapPaletteTypeMedianCut));
    HR(dc->CreateBitmapFromWicBitmap(d2dConverter, NULL, &d2dBmp));
}

void Render()
{
    if (dc)
    {
        dc->BeginDraw();
        dc->Clear();
        D2D1_POINT_2F offset = D2D1::Point2F(0, 0);
        D2D1_RECT_F imgRect = D2D1::RectF(windowRect.left, windowRect.top, windowRect.right, windowRect.bottom);
        dc->DrawImage(d2dBmp, offset, imgRect, D2D1_INTERPOLATION_MODE_LINEAR, D2D1_COMPOSITE_MODE_SOURCE_OVER);
        HR(dc->EndDraw());
        HR(swapChain->Present(1, 0));
    }

}

int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE, 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,
        wc.lpszClassName, L"Sample",
        WS_OVERLAPPEDWINDOW | WS_VISIBLE,
        CW_USEDEFAULT, CW_USEDEFAULT,
        500, 500,
        nullptr, nullptr, hInstance, nullptr);

    if (hwnd == NULL)
    {
        return 0;
    }
    
    CreateDevice(hwnd);
    ShowWindow(hwnd, nCmdShow);

    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_MOVING:
        {
            GetWindowRect(hwnd, &windowRect);
            Render();
            return 0;
        }
        

        case WM_PAINT:
        {
            PAINTSTRUCT ps;
            HDC hdc = BeginPaint(hwnd, &ps);
            FillRect(hdc, &ps.rcPaint, (HBRUSH)(COLOR_WINDOW + 1));
            EndPaint(hwnd, &ps);
            return 0;
        }

        case WM_DESTROY:
        {
            PostQuitMessage(0);
            d2dWICFactory->Release();
            d2dDecoder->Release();
            d2dConverter->Release();
            d2dBmpSrc->Release();
            d2dBmp->Release();
        }
        return 0;
    }
    return DefWindowProc(hwnd, uMsg, wParam, lParam);
}

Please don't forget to replace "C:/Users/selas/Downloads/wallpaper.jpg" with your desktop wallpaper

Note: The sample videos are actually edited ones its not the output I've got.

trickymind
  • 557
  • 5
  • 21
  • You can have the acrylic brush (composed with the host backdrop brush, recipe is here https://github.com/microsoft/microsoft-ui-xaml/blob/master/dev/Materials/Acrylic/AcrylicBrush.cpp#L697), but only with Windows.UI.Composition (which is somehow Direct Composition V3, just not named like that), *not* with dcomp.h. Windows.UI.Composition is accessible to Win32 desktop apps without the need for packaging. The seminal sample that shows how to use WUC with Win32 is here https://gist.github.com/kennykerr/62923cdacaba28fedc4f3dab6e0c12ec – Simon Mourier Jan 14 '21 at 08:53
  • thankyou let me have a look into it – trickymind Jan 14 '21 at 09:53
  • @Simon Mourier I have already used this library in a WFP application but this one was very much laggy i was not even able to move the window from one position to another. The newer windows version have fixed the lag issue but it was flickering too much while resizing. The acrylic blur was going out of the window on resize. Here is the sample i have used : https://github.com/Microsoft/Windows.UI.Composition-Win32-Samples/tree/master/dotnet/WPF/AcrylicEffect – trickymind Jan 14 '21 at 11:05
  • Try to expand the acrylic blur to the entire window and if you resize the window it goes out of the window. So that's why i am trying another work arounds – trickymind Jan 14 '21 at 11:06
  • If I was able to remove this flicker from the sample I posted in the question, the next thing I would do is to use the frame obtained from Desktop Duplication as the input for blur which will help me to create the same acrylic Blur effect. and by setting WDA_EXCLUDEFROMCAPTURE i can hide my window in desktop duplication. so I get exactly what is behind my window. – trickymind Jan 14 '21 at 11:10
  • The Sample from here https://github.com/chrishermans/magnify ,was able to crop the source rectangle without flickering and displaying it. but it does everything on GetCursorPos() coordinates, what i need to do is to do the same in GetWindowRect(). I tried it once but not working for me can you plz help me to figure this out. – trickymind Jan 14 '21 at 11:13
  • try compiling the source and reduce the scale factor to 1 by pressing windows+z, it looks exactly like a transparent window – trickymind Jan 14 '21 at 11:15
  • I've never tried the WPF one, but I did use the Winforms one with success: https://github.com/microsoft/Windows.UI.Composition-Win32-Samples/tree/master/dotnet/WinForms/AcrylicEffect the only drawback of these samples is they use the Win2D "thing" that Microsoft never ported back to Win32 (it's stupidly hardcoded for UWP), but in C/C++, that's not an issue as Direct2D is (relatively) easy to use and combine with WUC. The benefit of WUC is it's integrated with DWM (Desktop Window Manager), which is the real master of Windows desktop, and that's the only documented tech that is capable of that. – Simon Mourier Jan 14 '21 at 12:43
  • It is possible to remove the flickering of the sample I have given in the question see the video quoted "Solution: This is what I need to get". I did create this but in that code the window moves along with the cursor (using GetCursorPos()) when i am trying to make the window just to move when i drag it , but it causes the flickering. (I don't know what part in this code helps to avoid flickering, please have a look into this code, its actually taken from a magnifier source and mixed up with my code, so its a little bit messy, i tried removing the code piece by piece but doesn't work. – trickymind Jan 14 '21 at 13:10
  • Here is the code : https://firebasestorage.googleapis.com/v0/b/quizbox-f1bb1.appspot.com/o/magnify-master.zip?alt=media&token=c81f4dd2-3739-4143-912f-c3993eb8d724 – trickymind Jan 14 '21 at 13:10
  • after running use windowskey+ ` to open window, (its actually the magnifier show window part) – trickymind Jan 14 '21 at 13:13

1 Answers1

0

Finally I figured it out. Now I am able to move the window without any flickering to the image I rendered as background. The problem was in two places in my code.

  • GetWindowRect(): In WM_MOVING I was using GetWindowRect() to get the window Rectangle, this causes delay to obtain the window Rectangle and caused the flickering issue. The Solution I found was simple, I Converted the lParm to RECT by typecasting and using it as the value to update the location solved the issue. The code I used to solve the issue is given below :

RECT *hostRect = reinterpret_cast<RECT*>(lParam)


  • MagSetWindowSource(): This is an interesting thing. I Don't know what is the use of magnifier in this. The code will not remove the flicker until I call MagSetWindowSource() function, I don't know why it is required, that alone consumes more memory in my program. if I removed this line of code it again starts to flicker. The input to the function doesn't matter you just have to call the function that's it.

Updated :

Finally figured out what is MagSetWindowSource() is doing, it actually calls a DWM function called DwmFlush() which Issues a flush call that blocks the caller until the next present. and that solved my issue. now it is flickerless and smooth.

Here is the fully updated code:

#ifndef UNICODE
#define UNICODE
#endif 
#include <windows.h>
#include <wrl.h>
#include <dxgi1_3.h>
#include <d3d11_2.h>
#include <d2d1_2.h>
#include <d2d1_1.h>
#include <d2d1_2helper.h>
#include <dcomp.h>
#include <dwmapi.h>
#include <wincodec.h>
#include <magnification.h>

#pragma comment(lib, "dxgi")
#pragma comment(lib, "d3d11")
#pragma comment(lib, "d2d1")
#pragma comment(lib, "dwmapi")
#pragma comment(lib, "dxguid")
#pragma comment(lib, "dcomp")
#pragma comment(lib, "magnification")

using namespace Microsoft::WRL;

LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);

ComPtr<ID3D11Device> direct3dDevice;
ComPtr<IDXGIDevice> dxgiDevice;
ComPtr<IDXGIFactory2> dxFactory;
ComPtr<IDXGISwapChain1> swapChain;
ComPtr<ID2D1Factory2> d2Factory;
ComPtr<ID2D1Device1> d2Device;
ComPtr<IDCompositionTarget> target;
ComPtr<ID2D1DeviceContext> dc;


//Direct Composition Device,Visual
ComPtr<IDCompositionDevice> dcompDevice;
ComPtr<IDCompositionDevice3> dcompDevice3;
ComPtr<IDCompositionVisual> visual;

//Direct Composition Effects
ComPtr<IDCompositionGaussianBlurEffect> blur;
ComPtr<IDCompositionSaturationEffect> saturation;

IWICImagingFactory* d2dWICFactory = NULL;
IWICBitmapDecoder* d2dDecoder = NULL;
IWICFormatConverter* d2dConverter = NULL;
IWICBitmapFrameDecode* d2dBmpSrc = NULL;
ID2D1Bitmap* d2dBmp = NULL;

HWND hwnd;
RECT windowRect,temp;
RECT* hostRect;

void LoadBackground();
void Render();

struct ComException
{
    HRESULT result;
    ComException(HRESULT const value) : result(value)
    {}
};
void HR(HRESULT const result)
{
    if (S_OK != result)
    {
        throw ComException(result);
    }
}

void CreateDevice(HWND hwnd)
{

    HR(D3D11CreateDevice(nullptr,    // Adapter
        D3D_DRIVER_TYPE_HARDWARE,
        nullptr,    // Module
        D3D11_CREATE_DEVICE_BGRA_SUPPORT,
        nullptr, 0, // Highest available feature level
        D3D11_SDK_VERSION,
        &direct3dDevice,
        nullptr,    // Actual feature level
        nullptr));  // Device context

    HR(direct3dDevice.As(&dxgiDevice));
    HR(CreateDXGIFactory2(
        DXGI_CREATE_FACTORY_DEBUG,
        __uuidof(dxFactory),
        reinterpret_cast<void**>(dxFactory.GetAddressOf())));

    DXGI_SWAP_CHAIN_DESC1 description = {};

    description.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
    description.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
    description.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL;
    description.BufferCount = 2;
    description.SampleDesc.Count = 1;
    description.AlphaMode = DXGI_ALPHA_MODE_PREMULTIPLIED;

    RECT rect = {};
    GetClientRect(hwnd, &rect);
    description.Width = rect.right - rect.left;
    description.Height = rect.bottom - rect.top;

    HR(dxFactory->CreateSwapChainForComposition(dxgiDevice.Get(), &description, nullptr, swapChain.GetAddressOf()));

    D2D1_FACTORY_OPTIONS const options = { D2D1_DEBUG_LEVEL_INFORMATION };

    HR(D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, options, d2Factory.GetAddressOf()));

    HR(d2Factory->CreateDevice(dxgiDevice.Get(), d2Device.GetAddressOf()));

    HR(d2Device->CreateDeviceContext(D2D1_DEVICE_CONTEXT_OPTIONS_NONE, dc.GetAddressOf()));

    ComPtr<IDXGISurface2> surface;
    HR(swapChain->GetBuffer(0, __uuidof(surface), reinterpret_cast<void**>(surface.GetAddressOf())));

    D2D1_BITMAP_PROPERTIES1 properties = {};
    properties.pixelFormat.alphaMode = D2D1_ALPHA_MODE_PREMULTIPLIED;
    properties.pixelFormat.format = DXGI_FORMAT_B8G8R8A8_UNORM;
    properties.bitmapOptions = D2D1_BITMAP_OPTIONS_TARGET | D2D1_BITMAP_OPTIONS_CANNOT_DRAW;

    ComPtr<ID2D1Bitmap1> bitmap;
    HR(dc->CreateBitmapFromDxgiSurface(surface.Get(), properties, bitmap.GetAddressOf()));
    LoadBackground(); // loads my desktop background to d2dBmp using WIC
    dc->SetTarget(bitmap.Get());

    Render(); //render once

   //Creating Direct Compostion Devices and Visual

    HR(DCompositionCreateDevice(dxgiDevice.Get(), __uuidof(dcompDevice), reinterpret_cast<void**>(dcompDevice.GetAddressOf())));
    HR(DCompositionCreateDevice3(dxgiDevice.Get(), __uuidof(dcompDevice), reinterpret_cast<void**>(dcompDevice.GetAddressOf())));
    HR(dcompDevice->QueryInterface(__uuidof(IDCompositionDevice3), (LPVOID*)&dcompDevice3)); // use IDCompositionDevice3 here

    HR(dcompDevice3->CreateSaturationEffect(saturation.GetAddressOf()));
    HR(dcompDevice3->CreateGaussianBlurEffect(blur.GetAddressOf()));

    //setting effect properties
    blur->SetStandardDeviation(0.0f); // blur amount
    blur->SetBorderMode(D2D1_BORDER_MODE_HARD);
    saturation->SetSaturation(2.0f); //saturationamount

    HR(dcompDevice->CreateTargetForHwnd(hwnd, true, target.GetAddressOf()));

    blur->SetInput(NULL, bitmap.Get(), NULL);
    saturation->SetInput(NULL, blur.Get(), NULL);

    HR(dcompDevice->CreateVisual(visual.GetAddressOf()));
    HR(visual->SetContent(swapChain.Get()));
    visual->SetEffect(saturation.Get());
    HR(target->SetRoot(visual.Get()));
    HR(dcompDevice->Commit());

}

void LoadBackground()
{
    HR(CoCreateInstance(CLSID_WICImagingFactory, NULL, CLSCTX_INPROC_SERVER, __uuidof(IWICImagingFactory), (void**)(&d2dWICFactory)));
    HR(d2dWICFactory->CreateDecoderFromFilename(L"C:/Users/selas/Downloads/wallpaper.jpg", NULL, GENERIC_READ, WICDecodeMetadataCacheOnLoad, &d2dDecoder));
    HR(d2dWICFactory->CreateFormatConverter(&d2dConverter));
    HR(d2dDecoder->GetFrame(0, &d2dBmpSrc));
    HR(d2dConverter->Initialize(d2dBmpSrc, GUID_WICPixelFormat32bppPBGRA, WICBitmapDitherTypeNone, NULL, 0.f, WICBitmapPaletteTypeMedianCut));
    HR(dc->CreateBitmapFromWicBitmap(d2dConverter, NULL, &d2dBmp));
}

void Render()
{
    if (dc)
    {
        dc->BeginDraw();
        dc->Clear();
        if (hostRect)
        {
            D2D1_POINT_2F offset = D2D1::Point2F(0, 0);
            D2D1_RECT_F imgRect = D2D1::RectF(hostRect->left, hostRect->top, hostRect->right, hostRect->bottom);
            dc->DrawImage(d2dBmp, offset, imgRect, D2D1_INTERPOLATION_MODE_LINEAR, D2D1_COMPOSITE_MODE_SOURCE_OVER);
        }
        HR(dc->EndDraw());
        HR(swapChain->Present(1, 0));
    }

}

int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE, 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,
        wc.lpszClassName, L"Sample",
        WS_OVERLAPPEDWINDOW | WS_VISIBLE,
        CW_USEDEFAULT, CW_USEDEFAULT,
        500, 500,
        nullptr, nullptr, hInstance, nullptr);

    if (hwnd == NULL)
    {
        return 0;
    }

    CreateDevice(hwnd);
    ShowWindow(hwnd, nCmdShow);

    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_MOVING:
    {
        hostRect = reinterpret_cast<RECT*>(lParam);
        windowRect.left = hostRect->left;
        windowRect.top = hostRect->top;
        windowRect.right = hostRect->right;
        windowRect.bottom = hostRect->bottom;
        if (hostRect->left == 0 || hostRect->top == 0)
        {
            GetWindowRect(hwnd, &temp);
            hostRect->left = temp.left;
            hostRect->top = temp.top;
        }
        DwmFlush();
        Render();
        return 0;
    }


    case WM_PAINT:
    {
        PAINTSTRUCT ps;
        HDC hdc = BeginPaint(hwnd, &ps);
        FillRect(hdc, &ps.rcPaint, (HBRUSH)(COLOR_WINDOW + 1));
        EndPaint(hwnd, &ps);
        return 0;
    }

    case WM_DESTROY:
    {
        PostQuitMessage(0);
        d2dWICFactory->Release();
        d2dDecoder->Release();
        d2dConverter->Release();
        d2dBmpSrc->Release();
        d2dBmp->Release();
    }
    return 0;
    }
    return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
trickymind
  • 557
  • 5
  • 21