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;
}
}
效果图:
图片样本:
代码中的图片路径需要手动设置,因为图片资源是从文件中加入的。
Direct2D 画刷篇的更多相关文章
- Direct2D 第4篇 渐变画刷
原文:Direct2D 第4篇 渐变画刷 #include <windows.h> #include <d2d1.h> #include <d2d1helper.h> ...
- Direct2D 学习笔记(2)画刷 Brush
画刷的使用方法 需要包含的文件:<wincodec.h> 需要包含的库: "windowscodecs.lib" 资源网址: https://docs.micro ...
- Direct2D 第5篇 绘制图像
原文:Direct2D 第5篇 绘制图像 我加载的图像是一张透明底PNG图像,背景使用渐变的绿色画刷 #include <windows.h> #include <d2d1.h> ...
- 深入WPF中的图像画刷(ImageBrush)之2——ImageBrush的铺设方式
原文:深入WPF中的图像画刷(ImageBrush)之2--ImageBrush的铺设方式 ------------------------------------------------------ ...
- 深入WPF中的图像画刷(ImageBrush)之1——ImageBrush使用举例
原文:深入WPF中的图像画刷(ImageBrush)之1--ImageBrush使用举例 昨天我在<简述WPF中的画刷(Brush) >中简要介绍了WPF中的画刷的使用.现在接着深入研究 ...
- 简述WPF中的画刷(Brush)
原文:简述WPF中的画刷(Brush) -------------------------------------------------------------------------------- ...
- WPF样式之画刷结合样式
第一种画刷,渐变画刷GradientBrush (拿线性渐变画刷LinearGradientBrush(其实它涵盖在GradientBrush画刷内.现在拿他来说事.),还有一个圆心渐变画刷Radia ...
- C#GDI+基础(三)画刷详解
SolidBrush:一般的画刷,通常只用一种颜色去填充GDI+图形 创建一般画刷: SolidBrush sbBrush1 = new SolidBrush(Color.Green); HatchB ...
- [游戏模版3] Win32 画笔 画刷 图形
>_<:introduce the functions of define\create\use pen and brush to draw all kinds of line and s ...
- Unity3D-terrain brush地形画刷无法出现在Scene中,无法刷地图2
原因大概是 画刷brush 太小了,地图也太小了,没出出现. 如图,非正常状态: 解决方法: tag: terrain brush not working unity
随机推荐
- [转帖]Linux之bash反弹shell原理浅析
环境 攻击机:kali ip:192.168.25.144 靶 机:centos ip:192.168.25.142 过程 kali 监听本地8888端口 靶机 ...
- [转帖]在麒麟Linux安装Postgis
https://jimolonely.github.io/tech/linux/install-postgis-kylin/ 接着上一篇在麒麟linux上安装Postgresql12.5 ,我们来安装 ...
- [转帖]解释docker单机部署kraft模式kafka集群时,尝试各种方式的网络broker全部不通而启动失败的原因,并提示常见bug关注点
现象: controller节点与其他两个broker的通信失败.公网ip,宿主机ip,服务名,各种网络方式,都无法成功. 两点提示: 1.bug原因:因为单机内存不够用,设置了较低的 KAFKA_H ...
- [转帖]网络传输性能netperf测试方法和下载
简介 Netperf是一种网络性能的测试工具,主要针对基于TCP或UDP的传输.Netperf根据应用的不同,可以进行不同模式的网络性能测试,即批量数据传输(bulk data transfer)模式 ...
- 文心一言 VS 讯飞星火 VS chatgpt (187)-- 算法导论14.1 4题
四.用go语言,写出一个递归过程 OS-KEY-RANK(T,k),以一棵顺序统计树T和一个关键字k作为输入,要求返回 k 在由 T 表示的动态集合中的秩.假设 T 的所有关键字都不相同. 文心一言, ...
- 【码农教程】手把手教你学会Mockito使用
作者:京东零售 秦浩然 一.前期准备- 1.准备工作 <!--mockito依赖--> <dependency> <groupId>org.mockito</ ...
- 源码阅读:VictoriaMetrics中的golang代码优化方法
全文请移步:https://zhuanlan.zhihu.com/p/469239020 或关注我的公众号: 公众号:一本正经的瞎扯
- Vue基础系统文章07---webpack安装和配置与打包
1.当前web开发困境 a.文件依赖关系错综复杂 b.静态资源请求效率低 c.模块化支持不友好 d.浏览器对高级js兼容性低 例如:模块代码实现隔行换色 1)在新建空白文件夹中运行:npm init ...
- 🛠 Open Source Instant Messaging (IM) Project OpenIM Source Code
Deploying OpenIM involves multiple components and supports various methods, including source code, D ...
- 9.9 Windows驱动开发:内核远程线程实现DLL注入
在笔者上一篇文章<内核RIP劫持实现DLL注入>介绍了通过劫持RIP指针控制程序执行流实现插入DLL的目的,本章将继续探索全新的注入方式,通过NtCreateThreadEx这个内核函数实 ...