当前位置: 首页 > 编程日记 > 正文

Direct2D开发:Direct2D 和 GDI 互操作性概述

本主题说明如何结合使用 Direct2D 和 GDI(可能为英文网页)。有两种方法可以结合使用 Direct2D 和 GDI:您可以将 GDI 内容写入与 Direct2D GDI 兼容的呈现器目标,也可以将 Direct2D 内容写入 GDI 设备上下文 (DC)

0X01 将Direct2D内容绘制到GDI设备上下文:

  要将 Direct2D 内容绘制到 GDI DC,可以使用 ID2D1DCRenderTarget。要创建 DC 呈现器目标,可以使用ID2D1Factory::CreateDCRenderTarget 方法。此方法使用两个参数。

  第一个参数是 D2D1_RENDER_TARGET_PROPERTIES 结构,指定呈现、远程处理、DPI、像素格式和用法信息。要使 DC 呈现器目标能够使用 GDI,请将 DXGI 格式设置为DXGI_FORMAT_B8G8R8A8_UNORM,并将 Alpha 模式设置为 D2D1_ALPHA_MODE_PREMULTIPLIED 或D2D1_ALPHA_MODE_IGNORE

  第二个参数是接收 DC 呈现器目标引用的指针的地址。

  下面的代码创建一个 DC 呈现器目标。

// Create a DC render target.
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);hr = m_pD2DFactory->CreateDCRenderTarget(&props, &m_pDCRT);

  在前面的代码中,m_pD2DFactory 是一个指向 ID2D1Factory 的指针,而 m_pDCRT 是一个指向 ID2D1DCRenderTarget 的指针。

  必须先使用 DC 呈现器目标的 BindDC 方法将该目标与 GDI DC 关联,然后才能使用该目标进行呈现。每次使用不同的 DC 时,或者所要绘制的区域大小发生变化时,都要执行此操作。

  BindDC 方法使用两个参数:hDC 和 pSubRecthDC 参数提供一个设备上下文的句柄,该设备上下文用于接收呈现器目标的输出。pSubRect 参数是一个矩形,描述了用来呈现内容的设备上下文区域。如果 pSubRect 所描述的设备上下文区域改变了大小,DC 呈现器目标也将更新大小,以便与设备上下文区域相匹配。

  下面的代码将 DC 绑定到 DC 呈现器目标。

HRESULT DemoApp::OnRender(const PAINTSTRUCT &ps)
{
// Get the dimensions of the client drawing area.
GetClientRect(m_hwnd, &rc);
// Bind the DC to the DC render target.
hr = m_pDCRT->BindDC(ps.hdc, &rc);

  将 DC 呈现器目标与 DC 关联后,就可以使用该 DC 进行绘制。下面的代码使用 DC 来绘制 Direct2D 和 GDI 内容。有关完整代码,请参见Direct2D/GDI 互操作性示例

HRESULT DemoApp::OnRender(const PAINTSTRUCT &ps)
{HRESULT hr;RECT rc;// Get the dimensions of the client drawing area.GetClientRect(m_hwnd, &rc);//// Draw the pie chart with Direct2D.//// Create the DC render target.hr = CreateDeviceResources();if (SUCCEEDED(hr)){// Bind the DC to the DC render target.hr = m_pDCRT->BindDC(ps.hdc, &rc);m_pDCRT->BeginDraw();m_pDCRT->SetTransform(D2D1::Matrix3x2F::Identity());m_pDCRT->Clear(D2D1::ColorF(D2D1::ColorF::White));m_pDCRT->DrawEllipse(D2D1::Ellipse(D2D1::Point2F(150.0f, 150.0f),100.0f,100.0f),m_pBlackBrush,3.0);m_pDCRT->DrawLine(D2D1::Point2F(150.0f, 150.0f),D2D1::Point2F((150.0f + 100.0f * 0.15425f),(150.0f - 100.0f * 0.988f)),m_pBlackBrush,3.0);m_pDCRT->DrawLine(D2D1::Point2F(150.0f, 150.0f),D2D1::Point2F((150.0f + 100.0f * 0.525f),(150.0f + 100.0f * 0.8509f)),m_pBlackBrush,3.0);m_pDCRT->DrawLine(D2D1::Point2F(150.0f, 150.0f),D2D1::Point2F((150.0f - 100.0f * 0.988f),(150.0f - 100.0f * 0.15425f)),m_pBlackBrush,3.0);hr = m_pDCRT->EndDraw();if (SUCCEEDED(hr)){//// Draw the pie chart with GDI.//// Save the original object.HGDIOBJ original = NULL;original = SelectObject(ps.hdc,GetStockObject(DC_PEN));HPEN blackPen = CreatePen(PS_SOLID, 3, 0);SelectObject(ps.hdc, blackPen);Ellipse(ps.hdc, 300, 50, 500, 250);POINT pntArray1[2];pntArray1[0].x = 400;pntArray1[0].y = 150;pntArray1[1].x = static_cast<LONG>(400 + 100 * 0.15425);pntArray1[1].y = static_cast<LONG>(150 - 100 * 0.9885);POINT pntArray2[2];pntArray2[0].x = 400;pntArray2[0].y = 150;pntArray2[1].x = static_cast<LONG>(400 + 100 * 0.525);pntArray2[1].y = static_cast<LONG>(150 + 100 * 0.8509);POINT pntArray3[2];pntArray3[0].x = 400;pntArray3[0].y = 150;pntArray3[1].x = static_cast<LONG>(400 - 100 * 0.988);pntArray3[1].y = static_cast<LONG>(150 - 100 * 0.15425);Polyline(ps.hdc, pntArray1, 2);Polyline(ps.hdc, pntArray2, 2);Polyline(ps.hdc, pntArray3, 2);DeleteObject(blackPen);// Restore the original object.
            SelectObject(ps.hdc, original);}}if (hr == D2DERR_RECREATE_TARGET){hr = S_OK;DiscardDeviceResources();}return hr;
}

  此代码生成以下输出(添加的标注用于强调 Direct2D 和 GDI 呈现方式之间的差别。)

0X02 ID2D1DCRenderTargets、GDI转换以及从右向左书写语言版本的Windows:

在使用 ID2D1DCRenderTarget 时,它会将把 Direct2D 内容呈现到一个内部位图,然后通过 GDI 将该位图呈现到 DC。

  GDI 能够将 GDI 转换(通过 SetWorldTransform 方法)或其他效果应用于呈现器目标使用的同一 DC,在此情况下,GDI 将对 Direct2D 生成的位图进行转换。使用 GDI 转换来转换 Direct2D 内容可能会使输出的视觉质量下降,因为所转换的是已对抗锯齿和子像素定位进行计算的位图。

  例如,假设您使用呈现器目标来绘制一个包含抗锯齿几何图形和文本的场景。如果使用 GDI 转换来向 DC 应用缩放转换,并对场景进行缩放以使其放大 10 倍,那么您将看到像素化和参差不齐的边缘。(但是,如果使用 Direct2D 应用类似的转换,则不会降低场景的视觉质量。)

  在某些情况下,GDI 正在执行的其他处理可能会降低 Direct2D 内容的质量,但这种情况可能并不显而易见。例如,在从右向左书写语言 (RTL) 版本的 Windows 中,由 ID2D1DCRenderTarget 呈现的内容可能会在 GDI 将其复制到目标时发生水平反转。内容实际上是否反转取决于 DC 的当前设置。

  您可能需要防止发生这种反转,具体取决于正在呈现的内容的类型。如果 Direct2D 内容包含 ClearType 文本,则这种反转将会降低文本质量。

  您可使用 SetLayout GDI 函数来控制 RTL 呈现行为。若要防止这种镜像,请调用 SetLayout GDI 函数,并将 LAYOUT_BITMAPORIENTATIONPRESERVED 指定为第二个参数的唯一值(请勿将其与 LAYOUT_RTL 组合),如以下示例所示:

SetLayout(m_hwnd, LAYOUT_BITMAPORIENTATIONPRESERVED);

0X03 将GDI内容绘制到与Direct2D GDI兼容的呈现器目标:

  上一部分说明如何将 Direct2D 内容绘制到 GDI DC。也可以将 GDI 内容绘制到与 Direct2D GDI 兼容的呈现器目标。此方法对于主要使用 Direct2D 来呈现的应用程序很有用,但有一些扩展模型或其他旧内容需要使用 GDI 来呈现。

  要将 GDI 内容呈现到与 Direct2D GDI 兼容的呈现器目标,请使用 ID2D1GdiInteropRenderTarget,通过它可以访问可接受 GDI 绘制调用的设备上下文。与其他接口不同,此接口不会直接创建 ID2D1GdiInteropRenderTarget 对象。而是使用现有呈现器目标实例的 QueryInterface 方法。下面的代码演示如何执行此操作:

D2D1_RENDER_TARGET_PROPERTIES rtProps = D2D1::RenderTargetProperties();rtProps.usage =  D2D1_RENDER_TARGET_USAGE_GDI_COMPATIBLE;// Create a GDI compatible Hwnd render target.hr = m_pD2DFactory->CreateHwndRenderTarget(rtProps,D2D1::HwndRenderTargetProperties(m_hwnd, size),&m_pRenderTarget);if (SUCCEEDED(hr)){hr = m_pRenderTarget->QueryInterface(__uuidof(ID2D1GdiInteropRenderTarget), (void**)&m_pGDIRT); }

  在前面的代码中,m_pD2DFactory 是一个指向 ID2D1Factory 的指针,而 m_pGDIRT 是一个指向 ID2D1GdiInteropRenderTarget 的指针。

  请注意,在创建与 Hwnd GDI 兼容的呈现器目标时,指定了 D2D1_RENDER_TARGET_USAGE_GDI_COMPATIBLE 标志。如果需要像素格式,请使用 DXGI_FORMAT_B8G8R8A8_UNORM(可能为英文网页)。如果需要 Alpha 模式,请使用 D2D1_ALPHA_MODE_PREMULTIPLIED 或D2D1_ALPHA_MODE_IGNORE

  以下示例显示如何将饼图(GDI 内容)绘制到与 Hwnd GDI 兼容的呈现器目标。

HDC hDC = NULL;hr = m_pGDIRT->GetDC(D2D1_DC_INITIALIZE_MODE_COPY, &hDC);if (SUCCEEDED(hr)){// Draw the pie chart to the GDI render target associated with the Hwnd render target.HGDIOBJ original = NULL;original = SelectObject(hDC,GetStockObject(DC_PEN));HPEN blackPen = CreatePen(PS_SOLID, 3, 0);SelectObject(hDC, blackPen);Ellipse(hDC, 300, 50, 500, 250);POINT pntArray1[2];pntArray1[0].x = 400;pntArray1[0].y = 150;pntArray1[1].x = static_cast<LONG>(400 + 100 * 0.15425);pntArray1[1].y = static_cast<LONG>(150 - 100 * 0.9885);POINT pntArray2[2];pntArray2[0].x = 400;pntArray2[0].y = 150;pntArray2[1].x = static_cast<LONG>(400 + 100 * 0.525);pntArray2[1].y = static_cast<LONG>(150 + 100 * 0.8509);POINT pntArray3[2];pntArray3[0].x = 400;pntArray3[0].y = 150;pntArray3[1].x = static_cast<LONG>(400 - 100 * 0.988);pntArray3[1].y = static_cast<LONG>(150 - 100 * 0.15425);Polyline(hDC, pntArray1, 2);Polyline(hDC, pntArray2, 2);Polyline(hDC, pntArray3, 2);DeleteObject(blackPen);// Restore the original object.
            SelectObject(hDC, original);m_pGDIRT->ReleaseDC(NULL);}

  该代码输出以下饼图(含标注,用于强调呈现质量上的差别)。右侧的饼图(GDI 内容)的呈现质量低于左侧的饼图(Direct2D 内容)。这是由于 Direct2D 使用 GPU,而 GDI 使用 CPU。

  

转载于:https://www.cnblogs.com/ye-ming/p/6182442.html

相关文章:

vmware虚拟机启动centOs黑屏

如图所示 &#xff0c; 我的VM 启动虚拟机之后就变成了上面的样子&#xff0c;一直不动&#xff0c;ping也ping不好&#xff0c;这个时候 &#xff1a; 1. 要么 内存不够了&#xff1b; 2. 要么 网络协议存在问题了&#xff1b; 本地windows环境在管理员的cmd命令行输入 &…

plc和pc串口通讯接线_让你搞懂PLC串口通讯和通讯接口,这东西估计没几个能说清楚~...

电力作业人员在使用PLC的时候会接触到很多的通讯协议以及通讯接口&#xff0c;最基本的PLC串口通讯和基本的通讯接口你都了解吗&#xff1f;1&#xff0c;什么是串口通讯&#xff1f;串口是计算机上一种非常通用设备通信的协议(不要与通用串行总线Universal Serial Bus或者USB混…

西班牙放大招,利用区块链技术防腐

链客&#xff0c;专为开发者而生&#xff0c;有问必答&#xff01; 此文章来自区块链技术社区&#xff0c;未经允许拒绝转载。 在过去十年来&#xff0c;西班牙爆发了一系列引人注目的腐败丑闻&#xff0c;其中以公共采购最甚。但据TI 2017年的腐败认知指数表明&#xff0c;西…

FreeBSD 8

FreeBSD 8.0的安装过程和7.2区别不大。先在FreeBSD官方网站上下载安装镜像&#xff0c;我一般都下载DVD的ISO&#xff0c;也有人爱好下最小的安装包&#xff0c;然后通过FTP或HTTP方式从网上下载各个程序包。这里就以DVD的ISO为例&#xff0c;下载DVD的ISO后&#xff0c;刻录到…

c潭州课堂25班:Ph201805201 MySQL第二课 (课堂笔记)

mysql> create table tb_2( -> id int, -> name varchar(10) not null -> ); 插入数据 insert into tb_2 value(1,xiaobai); 在非空时&#xff0c;NOT NULL 必须有值&#xff0c; 2&#xff0c;在已有的表中设置一个字段的非空约束 mysql> alter table tb_2 -…

vanpopup 高度_解决VantUI popup 弹窗不弹出或无蒙层的问题

背景####组件PopupTime.vue把vant官网的popup时间选择器抽成组件&#xff1a;popup1show: true 即弹窗显示:title"popupTitle.popupName"v-model"currentDate"type"datetime"cancel"onCancel" confirm"onConfirm" class&quo…

区块链技术入门,都涉及哪些编程语言?

链客&#xff0c;专为开发者而生&#xff0c;有问必答&#xff01; 此文章来自区块链技术社区&#xff0c;未经允许拒绝转载。 关于区块链的技能掌握&#xff0c;提到最多的就是Go语言和C、Java&#xff0c;但是很多人产生了歧义&#xff0c;认为只有这几种语言才可以&#x…

centos安装配置nginx,ssl生产和配置教程

【一】nginx安装nginx安装带ssl扩展&#xff1a; cd /usr/local/src #进入用户目录 wget http://nginx.org/download/nginx-1.15.0.tar.gz #下载最新版本nginx tar -zxvf nginx-1.15.0.tar.gz #解压 cd nginx-1.15.0 #进入目录 ./configure --prefix/opt/nginx --with-http_stu…

如何将github上的 lib fork之后通过podfile 改变更新源到自己fork的地址

解决办法: http://stackoverflow.com/questions/20936885/cocoapods-and-github-forks 就是fork完后&#xff0c;提交更改到自己的github上 然后修改podfile的pod导入方式 pod lib,:github>your fork lib.git,:commit >your commitid转载于:https://www.cnblogs.com/code…

证书 vivo_iQOO 5 Pro获泰尔实验室首张流畅性能体验五星证书

近日&#xff0c;中国泰尔实验室向vivo旗下的iQOO 5 Pro(V2025A)型号手机颁发了流畅性能体验五星证书。据中国泰尔实验室官方表示&#xff0c;这是“泰尔证书-流畅性能体验”测评方案推出后的首张证书。“泰尔证书-流畅性能体验”测评方案据悉&#xff0c;“泰尔证书-流畅性能体…

GUI编程之tkinter

链客&#xff0c;专为开发者而生&#xff0c;有问必答&#xff01; 此文章来自区块链技术社区&#xff0c;未经允许拒绝转载。 0. 前言 本文内容为使用Python3的tkinter模块&#xff0c;开发GUI。在阅读本文前&#xff0c;请确保你已经或可能满足以下条件&#xff1a; 电脑中…

js插件 webp_(转)让浏览器支持Webp

转载自&#xff1a;https://segmentfault.com/a/1190000005898538?utm_sourcetuicool&utm_mediumreferral转换工具判断浏览器支持webP方法一&#xff1a;functioncheckWebp() {try{return (document.createElement(canvas).toDataURL(image/webp).indexOf(data:image/webp…

一些大佬博客里的个签

觉得很励志~遇到了就复制下来激励自己。 1.宜静默&#xff0c;宜从容&#xff0c;宜谨严&#xff0c;宜俭约。 //读了两遍感觉心都静下来了。 2.别打扰我&#xff0c;我还能写一套程序。 3.时间并不会因为你的迷茫和迟疑而停留&#xff0c;就在你看这篇文章的同时&#xff0c…

以太坊搭建私有链

链客&#xff0c;专为开发者而生&#xff0c;有问必答&#xff01; 此文章来自区块链技术社区&#xff0c;未经允许拒绝转载。 1.关于私有链 在以太坊上部署智能合约、发起交易需要花费以太币。而私链和公有链没有关系&#xff0c;不用同步大量的数据&#xff0c;也不用花钱购…

C++回溯法走迷宫

1 #include <iostream> 2 #include <iomanip> 3 #include <cstdlib> 4 using namespace std;5 6 #define MaxSize 100 7 int maze[10][10] //定义一个迷宫&#xff0c;0表示通道&#xff0c;1表示墙 8 {9 { 1,1,1,1,1,1,1,1,1,1 },10 { 1,0,…

js放大镜特效

原理分析&#xff1a;当鼠标在小图片上移动时&#xff0c;通过捕捉鼠标在小图片上的位置&#xff0c;定位大图片的相应位置。&#xff08;同时&#xff0c;当鼠标在小图片上移动时&#xff0c;右侧大图片往相反的方向移动。&#xff09; 放大镜特效设计&#xff1a; ①页面元素…

5页面返回上个页面定位_5个步骤,画好页面流程图

对于任何产品设计来说&#xff0c;构建流程都是一个绕不开的环节。其奠定了后续的产品框架&#xff0c;是用户体验的基石。本文将从定义和方法出发&#xff0c;结合实际案例&#xff0c;深入浅出地阐述流程图的作用以及画法。最近在做一个关于阅读笔记的原型&#xff0c;业务流…

EOS智能合约:system系统合约源码分析

链客&#xff0c;专为开发者而生&#xff0c;有问必答&#xff01; 此文章来自区块链技术社区&#xff0c;未经允许拒绝转载。 eosio.system 概览 笔者使用的IDE是VScode&#xff0c;首先来看eosio.system的源码结构。如下图所示。 本文分析的源码来自于eosio.contracts。 …

文字超过省略_从楚篆到楚玺的文字结构

从古文字研究的角度来说&#xff0c;楚玺文字也是楚文字系统中重要的组成部分。古文字发展演变的一般规律&#xff0c;如简化、繁化、异化、分化、类化等在印章上也有反映。在楚系简帛书没有大量出土发现和研究出版前&#xff0c;楚玺研究的文字参照物不多&#xff0c;主要是依…

caffe prototxt分析

测试用prototxt name: "CIFAR10_quick"layer {name: "data" type: "MemoryData" top: "data" top: "label" memory_data_param {batch_size: 1 #样本个数 channels: 3 height: 32 width: 32 }}layer {name: "conv1…

Mysql与Oracle区别

Mysql与Oracle区别 文章分类:数据库 周五去一家公司去面试&#xff0c;那公司经理问了关于Mysql与Oracle的区别问题&#xff0c;以前没有总结&#xff0c;回答也不是很好&#xff0c;只是凭感觉&#xff0c;先总结如下&#xff1a; 1. Oracle是大型数据库而Mysql是中小型数据库…

区块链 + 大数据:EOS存储

链客&#xff0c;专为开发者而生&#xff0c;有问必答&#xff01; 此文章来自区块链技术社区&#xff0c;未经允许拒绝转载。 谈到区块链的存储&#xff0c;我们很容易联想到它的链式存储结构&#xff0c;然而区块链从比特币发展到今日当红的EOS&#xff0c;技术形态已经演化…

全网最全的Windows下Anaconda2 / Anaconda3里Python语言实现定时发送微信消息给好友或群里(图文详解)...

不多说&#xff0c;直接上干货&#xff01; 缘由&#xff1a; &#xff08;1&#xff09;最近看到情侣零点送祝福&#xff0c;感觉还是很浪漫的事情&#xff0c;相信有很多人熬夜为了给爱的人送上零点祝福&#xff0c;但是有时等着等着就睡着了或者时间并不是卡的那么准就有点强…

Agreeing to the Xcode/iOS license requires admin privileges, please re-run as root via sudo

更新了xcode后使用goland运行项目时提示 Agreeing to the Xcode/iOS license requires admin privileges, please re-run as root via sudo 更具提示打开xcode 点击agree安装即可&#xff01; 转载于:https://www.cnblogs.com/mafeng/p/6196494.html

arc diff 指定版本号_Phabricator客户端安装

前提需要配置好服务器端客户端安装mac环境下&#xff0c;指定一个目录$ mkdir somewhere/$ cd somewhere/somewhere/ $ git clone https://github.com/phacility/libphutil.gitsomewhere/ $ git clone https://github.com/phacility/arcanist.git配置环境变量&#xff0c;在.ba…

EOSIO 转帐详解

链客&#xff0c;专为开发者而生&#xff0c;有问必答&#xff01; 此文章来自区块链技术社区&#xff0c;未经允许拒绝转载。 EOS和EOS的不同之处 在EOS网络中存在两种货币&#xff0c;一种是EOS&#xff0c;还有一种是EOS网络中的代币。说到这里大家似乎有点疑惑&#xff0…

各种函数调用约定及浮点数传参

32位下_stdcall, _fastcall, _cdecl #include <windows.h>int _stdcall Func1(int a, int b, int c, int d) {return abcd; } int _fastcall Func2(int a, int b, int c, int d) {return abcd; } int _cdecl Func3(int a, int b, int c, int d) {return a b c d; }…

cookie、session总结

前几天在调试第三方支付接口时碰到一个session失效问题&#xff0c;用了几天时间才搞明白&#xff0c;现在回想一下&#xff0c;主要还是由于cookie和session这一块的一些基本概念没有搞清楚&#xff0c;现总结一下。 浏览器使用HTTP协议作为应用层协议&#xff0c;而HTTP协议是…

glibc降级后怎么恢复 linux_Linux(CentOS)GLIBC出错补救方式

出于各种原因&#xff0c;我玩坏了我的系统.........主要出错原因是更改 /usr/lib64 下的 libc.so.6 等文件引起&#xff0c;具体错误及补救方式附上&#xff0c;希望可以帮到心里失火后来人&#xff1a;首先&#xff0c;不要随便重新启动&#xff01;&#xff01;&#xff01;…

将Eclipse代码导入到AndroidStudio的两种方式

实现步骤 1. 从Eclipse中导出Gradle build files 在Eclipse菜单中 File --> Export-->Generate Gradle build files接下来会到达警告界面&#xff0c;这里会提示AndroidStudio可以直接导入ADT的工程&#xff0c;先过&#xff0c;后面有直接导入的讲解。选中你的项目工程&…