zoukankan      html  css  js  c++  java
  • Direct2D CreateHwndRenderTarget 和 CreateDCRenderTarget

    前段时间稍微看了点Direct3D, 觉得挺有意思的,但是想着要有3D得先从2D开始。故开始了D2D旅行。

    如标题所示,CreateHwndRenderTarget 是在用来创建一个渲染到窗口的渲染目标。

    创建渲染目标并且可以使用硬件加速时,可以在计算机的GPU上分配资源。通过一次创建渲染目标并保留尽可能长的时间,您可以获得性能上的好处。您的应用程序应一次创建渲染目标,并在应用程序的生命周期内或在收到D2DERR_RECREATE_TARGET错误之前将其保留。收到此错误时,您需要重新创建渲染目标(及其创建的所有资源)。

    它与CreateDCRenderTarget最大的区别,也就是GDI的绘图技巧与D2D的区别了。

    我的个人理解是,前者是自己在GPU上创建渲染目标,并停留一段时间用来绘制,不用我们操心上下文的环境了。 而后者的作用是

    创建一个绘制目标,以绘制到Windows图形设备接口(GDI)设备上下文。

    很显然它是用来充当D2D与GDI的交互的。

    这篇文档是介绍这个作用的, Direct2D and GDI Interoperability Overview

    在代码上使用肯定也是有区别的。

    前者的使用,可以先看D2D入门的代码,下面的代码是用来将图片绘制到窗口上,

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <Windows.h>
    #include <d2d1.h>
    #include <d2d1_1.h>
    
    #include <wincodec.h>
    
    #pragma comment(lib, "d2d1.lib")
    #pragma comment(lib, "Windowscodecs.lib")
    
    #define SAFE_RELEASE(P) if(P){P->Release() ; P = NULL ;}
    
    
    extern "C" ID2D1Bitmap * mybitmapcreate(ID2D1DCRenderTarget*);
    float left = 5;
    float top = 10;
    float Bottom = 10;
    float Right = 30;
    ID2D1Bitmap* pBitmap = NULL;
    IWICImagingFactory* pIWICFactory = NULL;
    HWND hWnd;
    ID2D1HwndRenderTarget* m_pRenderTarget;
    
    void initize();
    void draw();
    D2D1_RECT_F myrect = D2D1::RectF(left, top, Bottom, Right);
    ID2D1Bitmap* mybitmap;
    ID2D1Factory* l;
    REFIID x = __uuidof(ID2D1Factory);
    
    HRESULT LoadBitmapFromFile(
        ID2D1RenderTarget* pRenderTarget,
        IWICImagingFactory* pIWICFactory,
        PCWSTR uri,
        UINT destinationWidth,
        UINT destinationHeight
    )
    {
        HRESULT hr = S_OK;
    
        IWICBitmapDecoder* pDecoder = NULL;
        IWICBitmapFrameDecode* pSource = NULL;
        IWICStream* pStream = NULL;
        IWICFormatConverter* pConverter = NULL;
        IWICBitmapScaler* pScaler = NULL;
    
    
        hr = pIWICFactory->CreateDecoderFromFilename(
            uri,
            NULL,
            GENERIC_READ,
            WICDecodeMetadataCacheOnLoad,
            &pDecoder
        );
        if (SUCCEEDED(hr))
        {
    
            // Create the initial frame.
            hr = pDecoder->GetFrame(0, &pSource);
        }
        if (SUCCEEDED(hr))
        {
            hr = pIWICFactory->CreateFormatConverter(&pConverter);
        }
        // If a new width or height was specified, create an
    // IWICBitmapScaler and use it to resize the image.
        if (destinationWidth != 0 || destinationHeight != 0)
        {
            UINT originalWidth, originalHeight;
            hr = pSource->GetSize(&originalWidth, &originalHeight);
            if (SUCCEEDED(hr))
            {
                if (destinationWidth == 0)
                {
                    FLOAT scalar = static_cast<FLOAT>(destinationHeight) / static_cast<FLOAT>(originalHeight);
                    destinationWidth = static_cast<UINT>(scalar * static_cast<FLOAT>(originalWidth));
                }
                else if (destinationHeight == 0)
                {
                    FLOAT scalar = static_cast<FLOAT>(destinationWidth) / static_cast<FLOAT>(originalWidth);
                    destinationHeight = static_cast<UINT>(scalar * static_cast<FLOAT>(originalHeight));
                }
    
                hr = pIWICFactory->CreateBitmapScaler(&pScaler);
                if (SUCCEEDED(hr))
                {
                    hr = pScaler->Initialize(
                        pSource,
                        destinationWidth,
                        destinationHeight,
                        WICBitmapInterpolationModeCubic
                    );
                }
                if (SUCCEEDED(hr))
                {
                    hr = pConverter->Initialize(
                        pScaler,
                        GUID_WICPixelFormat32bppPBGRA,
                        WICBitmapDitherTypeNone,
                        NULL,
                        0.f,
                        WICBitmapPaletteTypeMedianCut
                    );
                }
            }
        }
        if (SUCCEEDED(hr))
        {
            // Create a Direct2D bitmap from the WIC bitmap.
            hr = pRenderTarget->CreateBitmapFromWicBitmap(
                pConverter,
                NULL,
                &pBitmap
            );
        }
    
        SAFE_RELEASE(pDecoder);
        SAFE_RELEASE(pSource);
        SAFE_RELEASE(pStream);
        SAFE_RELEASE(pConverter);
        SAFE_RELEASE(pScaler);
    
        return TRUE;
    }
    
    LRESULT CALLBACK WndProcFunc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
    {
        RECT rc;
        switch (message)
        {
        case WM_PAINT:
        {
            draw();
        }
        break;
        case WM_DESTROY:
            PostQuitMessage(0);
            return 0;
        }
        return DefWindowProc(hwnd, message, wParam, lParam);
    }
    int main(int argc, char* argv[])
    {
        WNDCLASS wc{};
        wc.style = CS_HREDRAW | CS_VREDRAW;
        wc.lpfnWndProc = WndProcFunc;
        wc.hInstance = GetModuleHandle(NULL);
        wc.lpszClassName = L"Class_Name";
        wc.hCursor = LoadCursor(nullptr, IDC_ARROW);
        RegisterClass(&wc);
    
        hWnd = CreateWindow(L"Class_Name", L"Test", WS_OVERLAPPEDWINDOW, 100, 100, 1000, 500, NULL, NULL, GetModuleHandle(NULL), NULL);
        initize();
    
        ShowWindow(hWnd, 1);
        UpdateWindow(hWnd);
    
        MSG Msg;
        while (GetMessage(&Msg, NULL, 0, 0))
        {
            TranslateMessage(&Msg);
            DispatchMessage(&Msg);
        }
    
        return 0;
    }
    
    void initize()
    {
        CoInitializeEx(NULL, COINIT_MULTITHREADED);
        CoCreateInstance(CLSID_WICImagingFactory, NULL, CLSCTX_INPROC_SERVER, IID_IWICImagingFactory, reinterpret_cast<void**>(&pIWICFactory));
    
        HRESULT hr = D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &l);
    
        RECT rc;
        GetClientRect(hWnd, &rc);
    
        D2D1_SIZE_U size = D2D1::SizeU(
            rc.right - rc.left,
            rc.bottom - rc.top
        );
    
        // Create a Direct2D render target.
        hr = l->CreateHwndRenderTarget(
            D2D1::RenderTargetProperties(),
            D2D1::HwndRenderTargetProperties(hWnd, size),
            &m_pRenderTarget
        );
    
    }
    
    void draw()
    {
    
        LoadBitmapFromFile(m_pRenderTarget, pIWICFactory, L"timg.bmp", 650, 400);
    
    
        m_pRenderTarget->BeginDraw();
    
        m_pRenderTarget->Clear(D2D1::ColorF(D2D1::ColorF::White));
    
        D2D1_SIZE_F size = pBitmap->GetSize();
        D2D1_POINT_2F upperLeftCorner = D2D1::Point2F(0.f, 0.f);
    
        // Draw bitmap
        m_pRenderTarget->DrawBitmap(
            pBitmap,
            D2D1::RectF(
                upperLeftCorner.x,
                upperLeftCorner.y,
                upperLeftCorner.x + size.width,
                upperLeftCorner.y + size.height)
        );
        m_pRenderTarget->EndDraw();
    
    }

    后者则是需要使用ID2D1DCRenderTarget::BindDC 将渲染目标绑定到向其发出绘图命令的设备上下文。

    需要更改的代码部分,

    //创建DC的渲染目标
    ID2D1DCRenderTarget* pow;
    ...
    
    void initize()
    {
        CoInitializeEx(NULL, COINIT_MULTITHREADED);
        CoCreateInstance(CLSID_WICImagingFactory, NULL, CLSCTX_INPROC_SERVER, IID_IWICImagingFactory, reinterpret_cast<void**>(&pIWICFactory));
    
        HRESULT hr = D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &l);
    
        D2D1_RENDER_TARGET_PROPERTIES props = D2D1::RenderTargetProperties(
            D2D1_RENDER_TARGET_TYPE_DEFAULT,
            D2D1::PixelFormat(
                DXGI_FORMAT_B8G8R8A8_UNORM,
                D2D1_ALPHA_MODE_IGNORE),
            0,
            0,
            D2D1_RENDER_TARGET_USAGE_NONE,
            D2D1_FEATURE_LEVEL_DEFAULT
        );   
        l->CreateDCRenderTarget(&props, &pow);
    
    }
    void draw()
    {
    
        LoadBitmapFromFile(m_pRenderTarget, pIWICFactory, L"timg.bmp", 650, 400);
    
    
        pow->BeginDraw();
    
        pow->Clear(D2D1::ColorF(D2D1::ColorF::White));
    
        D2D1_SIZE_F size = pBitmap->GetSize();
        D2D1_POINT_2F upperLeftCorner = D2D1::Point2F(0.f, 0.f);
    
        // Draw bitmap
        pow->DrawBitmap(
            pBitmap,
            D2D1::RectF(
                upperLeftCorner.x,
                upperLeftCorner.y,
                upperLeftCorner.x + size.width,
                upperLeftCorner.y + size.height)
        );
        pow->EndDraw();
    
    }
    
    case WM_PAINT:
    {
            PAINTSTRUCT ps;
            HDC hdc = BeginPaint(hwnd, &ps);
            GetClientRect(hwnd, &rc);
            pow->BindDC(ps.hdc, &rc);
            draw();
            EndPaint(hwnd, &ps);
    }
    break;
    ...
  • 相关阅读:
    Running APP 使用说明
    Android 控件八 WebView 控件
    Android 控件七 ImageView 控件
    Android 控件六 CheckBox 控件
    Android 控件五 RadioButton 控件
    Android 控件四 EditText 控件
    Android 控件三 TextView 控件实现 Button
    Android 控件二 Button
    Android 基础控件演示实例
    Android 控件一 TextView
  • 原文地址:https://www.cnblogs.com/strive-sun/p/14282000.html
Copyright © 2011-2022 走看看