zoukankan      html  css  js  c++  java
  • Direct2D 画刷篇

    微软文档:Brushes overview

    本篇通过官方文档学习,整理出来的demo,初始样本请先创建一个普通的desktop app。

    // Test_Direct2D_Brush.cpp : Defines the entry point for the application.
    //
    
    #include "framework.h"
    #include "Test_Direct2D_Brush.h"
    #include <d2d1.h>
    #include <wincodec.h>
    
    #pragma comment(lib, "D2d1.lib")
    #pragma comment(lib, "Windowscodecs.lib")
    
    #define MAX_LOADSTRING 100
    
    template <class T> void SafeRelease(T** ppT)
    {
        if (*ppT)
        {
            (*ppT)->Release();
            *ppT = NULL;
        }
    }
    
    HWND hWnd;
    ID2D1Factory* l;
    ID2D1HwndRenderTarget* m_pRenderTarget;
    ID2D1SolidColorBrush* m_pBlackBrush;
    ID2D1SolidColorBrush* m_pYellowGreenBrush;
    ID2D1GradientStopCollection* pGradientStops = NULL;
    ID2D1LinearGradientBrush* m_pLinearGradientBrush;
    ID2D1RadialGradientBrush* m_pRadialGradientBrush;
    IWICImagingFactory* pIWICFactory = NULL;
    ID2D1Bitmap* m_pBitmap;
    ID2D1BitmapBrush* m_pBitmapBrush;
    
    // Global Variables:
    HINSTANCE hInst;                                // current instance
    WCHAR szTitle[MAX_LOADSTRING];                  // The title bar text
    WCHAR szWindowClass[MAX_LOADSTRING];            // the main window class name
    
    // Forward declarations of functions included in this code module:
    ATOM                MyRegisterClass(HINSTANCE hInstance);
    BOOL                InitInstance(HINSTANCE, int);
    LRESULT CALLBACK    WndProc(HWND, UINT, WPARAM, LPARAM);
    INT_PTR CALLBACK    About(HWND, UINT, WPARAM, LPARAM);
    void Render();
    void DiscardGraphicsResources();
    HRESULT LoadBitmapFromFile(ID2D1RenderTarget*, IWICImagingFactory*, PCWSTR, UINT, UINT, ID2D1Bitmap**);
    
    int APIENTRY wWinMain(_In_ HINSTANCE hInstance,
                         _In_opt_ HINSTANCE hPrevInstance,
                         _In_ LPWSTR    lpCmdLine,
                         _In_ int       nCmdShow)
    {
        UNREFERENCED_PARAMETER(hPrevInstance);
        UNREFERENCED_PARAMETER(lpCmdLine);
    
        // TODO: Place code here.
    
        // Initialize global strings
        LoadStringW(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
        LoadStringW(hInstance, IDC_TESTDIRECT2DBRUSH, szWindowClass, MAX_LOADSTRING);
        MyRegisterClass(hInstance);
    
        // Perform application initialization:
        if (!InitInstance (hInstance, nCmdShow))
        {
            return FALSE;
        }
    
        HACCEL hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_TESTDIRECT2DBRUSH));
    
        MSG msg;
    
        // Main message loop:
        while (GetMessage(&msg, nullptr, 0, 0))
        {
            if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
            {
                TranslateMessage(&msg);
                DispatchMessage(&msg);
            }
        }
    
        return (int) msg.wParam;
    }
    
    
    
    //
    //  FUNCTION: MyRegisterClass()
    //
    //  PURPOSE: Registers the window class.
    //
    ATOM MyRegisterClass(HINSTANCE hInstance)
    {
        WNDCLASSEXW wcex;
    
        wcex.cbSize = sizeof(WNDCLASSEX);
    
        wcex.style          = CS_HREDRAW | CS_VREDRAW;
        wcex.lpfnWndProc    = WndProc;
        wcex.cbClsExtra     = 0;
        wcex.cbWndExtra     = 0;
        wcex.hInstance      = hInstance;
        wcex.hIcon          = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_TESTDIRECT2DBRUSH));
        wcex.hCursor        = LoadCursor(nullptr, IDC_ARROW);
        wcex.hbrBackground  = (HBRUSH)(COLOR_WINDOW+1);
        wcex.lpszMenuName   = MAKEINTRESOURCEW(IDC_TESTDIRECT2DBRUSH);
        wcex.lpszClassName  = szWindowClass;
        wcex.hIconSm        = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));
    
        return RegisterClassExW(&wcex);
    }
    
    //
    //   FUNCTION: InitInstance(HINSTANCE, int)
    //
    //   PURPOSE: Saves instance handle and creates main window
    //
    //   COMMENTS:
    //
    //        In this function, we save the instance handle in a global variable and
    //        create and display the main program window.
    //
    BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
    {
       hInst = hInstance; // Store instance handle in our global variable
       HRESULT hr = D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &l);
       hWnd = CreateWindowW(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
          CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, nullptr, nullptr, hInstance, nullptr);
    
       if (!hWnd)
       {
          return FALSE;
       }
    
       ShowWindow(hWnd, nCmdShow);
       UpdateWindow(hWnd);
    
       return TRUE;
    }
    
    //
    //  FUNCTION: WndProc(HWND, UINT, WPARAM, LPARAM)
    //
    //  PURPOSE: Processes messages for the main window.
    //
    //  WM_COMMAND  - process the application menu
    //  WM_PAINT    - Paint the main window
    //  WM_DESTROY  - post a quit message and return
    //
    //
    LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
    {
        switch (message)
        {
        case WM_COMMAND:
            {
                int wmId = LOWORD(wParam);
                // Parse the menu selections:
                switch (wmId)
                {
                case IDM_ABOUT:
                    DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
                    break;
                case IDM_EXIT:
                    DestroyWindow(hWnd);
                    break;
                default:
                    return DefWindowProc(hWnd, message, wParam, lParam);
                }
            }
            break;
        case WM_PAINT:
            {
             //   PAINTSTRUCT ps;
             //   HDC hdc = BeginPaint(hWnd, &ps);
                // TODO: Add any drawing code that uses hdc here...
                Render();
                ValidateRect(hWnd, NULL);
             //   EndPaint(hWnd, &ps);
            }
            break;
        case WM_DESTROY:
            PostQuitMessage(0);
            break;
        default:
            return DefWindowProc(hWnd, message, wParam, lParam);
        }
        return 0;
    }
    
    // Message handler for about box.
    INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
    {
        UNREFERENCED_PARAMETER(lParam);
        switch (message)
        {
        case WM_INITDIALOG:
            return (INT_PTR)TRUE;
    
        case WM_COMMAND:
            if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
            {
                EndDialog(hDlg, LOWORD(wParam));
                return (INT_PTR)TRUE;
            }
            break;
        }
        return (INT_PTR)FALSE;
    }
    
    
    void Render()
    {
        D2D1_RECT_F  rcBrushRect;
        rcBrushRect.left = 100;
        rcBrushRect.right = 200;
        rcBrushRect.top = 50;
        rcBrushRect.bottom = 150;
        RECT rc;
        GetClientRect(hWnd, &rc);
    
        D2D1_SIZE_U size = D2D1::SizeU(
            rc.right - rc.left,
            rc.bottom - rc.top
        );
        HRESULT hr = l->CreateHwndRenderTarget(
            D2D1::RenderTargetProperties(),
            D2D1::HwndRenderTargetProperties(hWnd, size),
            &m_pRenderTarget
        );
    
        m_pRenderTarget->BeginDraw();
    
        m_pRenderTarget->Clear(D2D1::ColorF(D2D1::ColorF::White));
        if (SUCCEEDED(hr))
        {
            hr = m_pRenderTarget->CreateSolidColorBrush(
                D2D1::ColorF(D2D1::ColorF::Black, 1.0F),
                &m_pBlackBrush
            );
        }
        
        if (SUCCEEDED(hr))
        {
            hr = m_pRenderTarget->CreateSolidColorBrush(
                D2D1::ColorF(D2D1::ColorF(0x9ACD32, 1.0f)),
                &m_pYellowGreenBrush
            );
        }
    
        m_pRenderTarget->FillRectangle(&rcBrushRect, m_pYellowGreenBrush);
        m_pRenderTarget->DrawRectangle(&rcBrushRect, m_pBlackBrush, 1, NULL);
    
    /*****************************************************************************/
    //渐变画刷
        D2D1_GRADIENT_STOP gradientStops[2];
        gradientStops[0].color = D2D1::ColorF(D2D1::ColorF::Yellow, 1);
        gradientStops[0].position = 0.0f;
        gradientStops[1].color = D2D1::ColorF(D2D1::ColorF::ForestGreen, 1);
        gradientStops[1].position = 1.0f;
        hr = m_pRenderTarget->CreateGradientStopCollection(
            gradientStops,
            2,
            D2D1_GAMMA_2_2,
            D2D1_EXTEND_MODE_CLAMP,
            &pGradientStops
        );
        if (SUCCEEDED(hr))
        {
            hr = m_pRenderTarget->CreateLinearGradientBrush(
                D2D1::LinearGradientBrushProperties(
                    D2D1::Point2F(300, 50),
                    D2D1::Point2F(400, 150)),
                pGradientStops,
                &m_pLinearGradientBrush
            );
        }
        rcBrushRect.left = 300;
        rcBrushRect.right = 400;
        m_pRenderTarget->FillRectangle(&rcBrushRect, m_pLinearGradientBrush);
    /*****************************************************************************/
    //径向渐变
        if (SUCCEEDED(hr))
        {
            hr = m_pRenderTarget->CreateRadialGradientBrush(
                D2D1::RadialGradientBrushProperties(
                    D2D1::Point2F(100, 300),
                    D2D1::Point2F(0, 0),
                    75,
                    75),
                pGradientStops,
                &m_pRadialGradientBrush
            );
        }
        D2D1_ELLIPSE ellipse = D2D1::Ellipse(
            D2D1::Point2F(100.f, 300.f),
            75.f,
            50.f
        );
        m_pRenderTarget->FillEllipse(ellipse, m_pRadialGradientBrush);
        m_pRenderTarget->DrawEllipse(ellipse, m_pBlackBrush, 1, NULL);
    
    /******************************************************************************/
    //next: https://docs.microsoft.com/en-us/windows/win32/direct2d/direct2d-brushes-overview#configuring-a-radial-gradient
    //位图画刷
        CoCreateInstance(CLSID_WICImagingFactory, NULL, CLSCTX_INPROC_SERVER, IID_IWICImagingFactory, reinterpret_cast<void**>(&pIWICFactory));
        if (SUCCEEDED(hr))
        {
            hr = LoadBitmapFromFile(
                m_pRenderTarget,
                pIWICFactory,
                L"C:\Users\strives\Desktop\copy.bmp",
                34,
                34,
                &m_pBitmap
            );
        }
        if (SUCCEEDED(hr))
        {
            hr = m_pRenderTarget->CreateBitmapBrush(
                m_pBitmap,
                &m_pBitmapBrush
            );
        }
        rcBrushRect.left = 0;
        rcBrushRect.right = 34;
        rcBrushRect.top = 0;
        rcBrushRect.bottom = 34;
     //   m_pRenderTarget->FillRectangle(&rcBrushRect, m_pBitmapBrush);
     //位图画刷拓展模式
        m_pBitmapBrush->SetExtendModeX(D2D1_EXTEND_MODE_MIRROR);
        m_pBitmapBrush->SetExtendModeY(D2D1_EXTEND_MODE_MIRROR);
        rcBrushRect.right = 100;
        rcBrushRect.bottom = 100;
        m_pRenderTarget->FillRectangle(rcBrushRect, m_pBitmapBrush);
    /******************************************************************************/
    //变形笔刷
        if (SUCCEEDED(hr))
        {
            hr = LoadBitmapFromFile(
                m_pRenderTarget,
                pIWICFactory,
                L"C:\Users\strives\Desktop\panda.bmp",
                268,
                304,
                &m_pBitmap
            );
        }
        if (SUCCEEDED(hr))
        {
            hr = m_pRenderTarget->CreateBitmapBrush(
                m_pBitmap,
                &m_pBitmapBrush
            );
        }
        D2D1_RECT_F rcTransformedBrushRect = D2D1::RectF(400, 400, 600, 600);
        // Demonstrate the effect of transforming a bitmap brush.
        m_pBitmapBrush->SetTransform(
            D2D1::Matrix3x2F::Translation(D2D1::SizeF(300, 300))
        );
        // To see the content of the rcTransformedBrushRect, comment
        // out this statement.
        m_pRenderTarget->FillRectangle(
            &rcTransformedBrushRect,
            m_pBitmapBrush
        );
        m_pRenderTarget->DrawRectangle(rcTransformedBrushRect, m_pBlackBrush, 1, NULL);
    /*************************************************************************************/
        hr = m_pRenderTarget->EndDraw();
    
        if (FAILED(hr) || hr == D2DERR_RECREATE_TARGET)
        {
            DiscardGraphicsResources();
        }
    //    DiscardGraphicsResources();
    }
    
    void DiscardGraphicsResources()
    {
        SafeRelease(&m_pRenderTarget);
        SafeRelease(&m_pBlackBrush);
        SafeRelease(&m_pYellowGreenBrush);
    }
    
    HRESULT LoadBitmapFromFile(
        ID2D1RenderTarget* pRenderTarget,
        IWICImagingFactory* pIWICFactory,
        PCWSTR uri,
        UINT destinationWidth,
        UINT destinationHeight,
        ID2D1Bitmap** ppBitmap
    )
    {
        IWICBitmapDecoder* pDecoder = NULL;
        IWICBitmapFrameDecode* pSource = NULL;
        IWICStream* pStream = NULL;
        IWICFormatConverter* pConverter = NULL;
        IWICBitmapScaler* pScaler = NULL;
    
        HRESULT hr = pIWICFactory->CreateDecoderFromFilename(
            uri,
            NULL,
            GENERIC_READ,
            WICDecodeMetadataCacheOnLoad,
            &pDecoder
        );
        if (SUCCEEDED(hr))
        {
            // Create the initial frame.
            hr = pDecoder->GetFrame(0, &pSource);
        }
        if (SUCCEEDED(hr))
        {
    
            // Convert the image format to 32bppPBGRA
            // (DXGI_FORMAT_B8G8R8A8_UNORM + D2D1_ALPHA_MODE_PREMULTIPLIED).
            hr = pIWICFactory->CreateFormatConverter(&pConverter);
    
        }
        if (SUCCEEDED(hr))
        {
            hr = pConverter->Initialize(
                pSource,
                GUID_WICPixelFormat32bppPBGRA,
                WICBitmapDitherTypeNone,
                NULL,
                0.f,
                WICBitmapPaletteTypeMedianCut
            );
            if (SUCCEEDED(hr))
            {
    
                // Create a Direct2D bitmap from the WIC bitmap.
                hr = pRenderTarget->CreateBitmapFromWicBitmap(
                    pConverter,
                    NULL,
                    ppBitmap
                );
            }
    
            SafeRelease(&pDecoder);
            SafeRelease(&pSource);
            SafeRelease(&pStream);
            SafeRelease(&pConverter);
            SafeRelease(&pScaler);
    
            return hr;
        }
    }

    效果图:

     图片样本:

     

     代码中的图片路径需要手动设置,因为图片资源是从文件中加入的。

  • 相关阅读:
    Bzoj 2134: [国家集训队2011]单选错位(期望)
    洛谷 P1230 智力大冲浪
    洛谷 P2695 骑士的工作
    洛谷 P1551 亲戚
    洛谷 P1111 修复公路
    洛谷 P1599 结算日
    HDU 1166 敌兵布阵
    洛谷 P2212 [USACO14MAR]浇地Watering the Fields
    洛谷 P1506 拯救oibh总部
    洛谷 P1396 营救
  • 原文地址:https://www.cnblogs.com/strive-sun/p/14308927.html
Copyright © 2011-2022 走看看