7.md 11.3 KB
Newer Older
W
wizardforcel 已提交
1
# 七、附录 d:`SimpleTextRenderer`代码列表
W
wizardforcel 已提交
2 3 4 5 6

下面的代码示例是基于构建一个需要打印的应用程序而修改的 SimpleTextRenderer 类。这些代码大部分来自微软视窗 8 示例。我已经更改了格式,以更好地适应这本书的页面,但它的可读性远不如微软提供的原版。

simpletextrenderer . h

W
wizardforcel 已提交
7
```cpp
W
wizardforcel 已提交
8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72
    #pragma once
    #include "DirectXBase.h"
    #include <PrintPreview.h>
    enum class DrawTypes {    Rendering, Preview,  Printing  };

    // RAII (Resource Acquisition Is Initialization) class for manually
    // acquiring/releasing the D2D lock.
    class D2DFactoryLock {
    public:
    D2DFactoryLock(_In_ ID2D1Factory* d2dFactory) {
         DX::ThrowIfFailed(
              d2dFactory->QueryInterface(IID_PPV_ARGS(&m_d2dMultithread))
              );
         m_d2dMultithread->Enter();
         }
    ~D2DFactoryLock() {
         m_d2dMultithread->Leave();
         }
    private:
         Microsoft::WRL::ComPtr<ID2D1Multithread> m_d2dMultithread;
    };

    // Renders or prints drawings using Direct2D
    ref class SimpleTextRenderer sealed : public DirectXBase {
    public:
         SimpleTextRenderer();
         // DirectXBase methods.
         virtual void CreateDeviceIndependentResources() override;
         virtual void CreateDeviceResources() override;
         virtual void CreateWindowSizeDependentResources() override;
         virtual void Render() override;
         void Update(float timeTotal, float timeDelta);
    internal:
         // These two methods return immutable resources shared amongst contexts
         SimpleTextRenderer(
              _In_ D2D1_RECT_F targetBox,
              _In_ ID2D1DeviceContext* d2dContext,
              _In_ DrawTypes type,
              _In_ SimpleTextRenderer^ myParent
              );
        void UpdateTargetBox(_In_ D2D1_RECT_F& targetBox);
        void Draw(_In_ float scale);
         void CreatePrintControl(_In_  IPrintDocumentPackageTarget* docPackageTarget,
                    _In_  D2D1_PRINT_CONTROL_PROPERTIES* printControlProperties);
         HRESULT ClosePrintControl();

         void DrawPreviewSurface(_In_  float width, _In_  float height, _In_  float scale,
              _In_  D2D1_RECT_F contentBox, _In_  uint32 desiredJobPage,
              _In_  IPrintPreviewDxgiPackageTarget* previewTarget);
         void PrintPage(_In_ uint32 pageNumber, _In_ D2D1_RECT_F imageableArea,
              _In_ D2D1_SIZE_F pageSize, _In_opt_ IStream* pagePrintTicketStream);
    private:
         Microsoft::WRL::ComPtr<ID2D1SolidColorBrush> m_blackBrush;
         bool m_renderNeeded;
         // The main print control
         Microsoft::WRL::ComPtr<ID2D1PrintControl> m_d2dPrintControl;
        float m_margin;  // The margin size is in DIPs.
        D2D1_RECT_F m_targetBox; // Region to format for.
        DrawTypes m_type; // Record of context type, screen/preview/printing
    };

```

simpletextrenderer . cpp

W
wizardforcel 已提交
73
```cpp
W
wizardforcel 已提交
74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372
    #include "pch.h"
    #include "SimpleTextRenderer.h"

    using namespace D2D1;
    using namespace DirectX;
    using namespace Microsoft::WRL;
    using namespace Windows::Foundation;
    using namespace Windows::Foundation::Collections;
    using namespace Windows::UI::Core;
    SimpleTextRenderer::SimpleTextRenderer() :
         m_renderNeeded(true),
         m_type(DrawTypes::Rendering),  // By default the context is rendering to screen
         m_margin(96.0f)           // Default margin size
    {}

    SimpleTextRenderer::SimpleTextRenderer(_In_ D2D1_RECT_F targetBox,
         _In_ ID2D1DeviceContext* d2dContext, _In_ DrawTypes type,
         _In_ SimpleTextRenderer^ myParent) {
    m_margin = 96.0f;
    m_d2dContext = d2dContext;
    m_type = type;
    UpdateTargetBox(targetBox);
    DX::ThrowIfFailed(
         d2dContext->CreateSolidColorBrush(
         D2D1::ColorF(D2D1::ColorF::Black),
         &m_blackBrush));
    }

    void SimpleTextRenderer::CreateDeviceIndependentResources() {
         DirectXBase::CreateDeviceIndependentResources();
    }

    void SimpleTextRenderer::CreateDeviceResources() {
         DirectXBase::CreateDeviceResources();
         DX::ThrowIfFailed(
              m_d2dContext->CreateSolidColorBrush(
                    ColorF(ColorF::Black),
                    &m_blackBrush
                    )
              );
    }

    void SimpleTextRenderer::CreateWindowSizeDependentResources() {
         DirectXBase::CreateWindowSizeDependentResources();
         // Make the target box the whole screen
         D2D1_SIZE_F size = m_d2dContext->GetSize();   
         m_targetBox = D2D1::RectF(0, 0, size.width, size.height);
    }

    void SimpleTextRenderer::Update(float timeTotal, float timeDelta) {
         (void) timeTotal; // Unused parameter.
         (void) timeDelta; // Unused parameter.
    }

    void SimpleTextRenderer::Render() {
    m_d2dContext->BeginDraw();
    // Microsoft check that the current screen is not snapped here but we will
    // assume it is not.
    // Render page context.
    Draw(1.0f);
    // We ignore D2DERR_RECREATE_TARGET here. This error indicates that the device
    // is lost. It will be handled during the next call to Present.
    HRESULT hr = m_d2dContext->EndDraw();
    if (hr != D2DERR_RECREATE_TARGET) DX::ThrowIfFailed(hr);
    // We are accessing D3D resources directly in Present() without D2D's knowledge,
    // so we must manually acquire the D2D factory lock.
    //
    // Note: it's absolutely critical that the factory lock be released upon
    // exiting this function, or else the entire app will deadlock. This is
    // ensured via the following RAII class.
    D2DFactoryLock factoryLock(m_d2dFactory.Get());
    Present();
    }
    void SimpleTextRenderer::UpdateTargetBox(_In_ D2D1_RECT_F& targetBox) {
        m_targetBox = targetBox;
    }

      // Draws the scene to a rendering device context or a printing device context.
      void SimpleTextRenderer::Draw(_In_ float scale)

```

{

if(m _ type = = draw types::Rendering){//如果渲染到屏幕,则清除为矢车菊蓝色

m _ D2 dconte-> clear(D2 D1::colorf(D2 D1::colorf::cornflower));}

else if(m _ type = = draw types::Preview){//打印时不清除

m _ D2 dconte-> clear(D2 D1::colorf(D2 D1::colorf::white));}

//预览时我们使用比例矩阵来缩小图像。

//屏幕渲染或打印比例为 1.f。

m _ d2d context-> SetTransform(d2d 1::Matrix3x2F(1/scale,0,0,1/scale,0,0));

//这是绘制图表的地方。下面是一个图案

//以彩色圆圈为例:

D2D1 _ ELLIPSE ell

for(float y = 0;y < 16y++){ 0

for(float x = 0;x < 16x++){ 0

ell = D2D1::椭圆(D2D1::Point2F(x * 50.0f,y * 50.0f),100.0f,100.0 f);

m _ black rush-> set color(D2 D1::colorf(

(x * 16.0f) / 256.0f,

(y * 16.0f) / 256.0f,

((x+y)* 8.0f)/256.0 f));

m _ d2d context-> draw elliplex(ell,m _ blackBrush。get());

}

}

}

HRESULT SimpleTextRenderer::ClosePrintControl(){ 0

return(m _ d2dPrintControl = = null ptr)?s _ OK:m _ d2d print control-> Close();

}

void SimpleTextRenderer::CreatePrintControl(_ In _ iprintdockagetarget * docPackageTarget,_ In _ d2d 1 _ PRINT _ CONTROL _ PROPERTIES * printControlProperties){ 0

//显式释放现有的 D2D 打印控件。

m _ D2 dpprintcontrol = zero tr:

DX::throwifffailed(

m _ d2d device-> CreatePrintControl(m _ wic factory。Get(),

docpackage target print control properties,& m _ D2 dprincontrol);

}

void SimpleTextRenderer::draw preview surface(_In_ float 宽度,_ In _ float 高度,

_In_ float scale,_In_ D2D1_RECT_F contentBox,_ In _ uint32 desiredJobPage,

_ in _ iprinpreviewdxgipackagetarget * preview target)

{

d2d factory lock factory lock(m _ d2d factory。get());

cd3d 11 _ texture 2d _ desc texture desec(DXGI _ FORMAT _ b8g 8r 8 a 8 _ unrom,static _ cast<uint32>(ceil(width * m _ dpi/96)),</uint32>

static_cast <uint32>(天花板(高度* m_dpi / 96)),1,1,</uint32>

d3d 11 _ BIND _ RENDER _ TARGET | d3d 11 _ BIND _ SHADER _ RESOURCE);

comptr〔t0〕纹理;

dx::throwiffailed(m _ d3d vice-> create texture 2d(& texture desc,zero tr,& texture));

//创建给定大小的 DXGI 预览曲面。

comptr<idxgisurface>dx GIS surface;</idxgisurface>

DX::ThrowIfFailed(纹理。as<idxgisurface>(& dxgiSurface));</idxgisurface>

//为渲染预览表面创建新的 D2D 设备上下文。D2D

//设备上下文是有状态的,因此唯一的设备上下文必须是

//用于每个线程。

comptr<id2d1devicecontext>D2 dconte;</id2d1devicecontext>

DX::ThrowIfFailed(m _ d2d device-> CreateDeviceContext(

d2d 1 _ DEVICE _ CONTEXT _ OPTIONS _ NONE,& d2d CONTEXT));

//同时更新预览表面的 DPI。

d2dContext->SetDpi(m_dpi,m _ dpi);

//建议使用屏幕 DPI,以便在打印预览中获得更好的保真度和性能。

D2 D1 _ bitmap _ properties 1 bitmap properties = D2 D1::bitmap properties 1(

d2d 1 _ 位图 _ 选项 _ 目标| D2D1 _ 位图 _ 选项 _ 无法 _ 绘制,

D2D1::像素格式(dxgi _ format _ b8g8 r8 a 8 _ unom、D2 D1 _ alpha _ mode _ preplied);

//创建绘制页面内容的表面位图。

comptr<id2d1bitmap1>D2 dssurfacebitmap;</id2d1bitmap1>

DX::throwifffailed(

D2 dcontext-> createbitmapfromdxgissurface(dxgissurface)。Get(),

&bitmapProperties,& D2 dssurfacebitmap);

D2 dcontext-> settarget(D2 dssurfacebitmap)。get());

//创建并初始化页面渲染器上下文以进行预览。

simpletext enderer ^ preview text enders = ref new simpletext enders(content box,d2dContext.Get()、DrawTypes::Preview,this);

D2 dcontext-> begin draw();

//在预览图面上绘制页面内容。

preview text runs-> draw(缩放):

//文档源处理 D2DERR _ RECREATETARGET,这里抛出就可以了。

dx::throwiffailed(D2 dcontext-> end raw());

//必须通过用于创建 DXGI 表面的相同 DPI,才能正确打印

//预览。

DX::throwifffailed(

previewTarget->DrawPage(所需作业版本,dxgisurface)。Get()、m_dpi、m_dpi)

);

}

void SimpleTextRenderer::PrintPage(_ In _ uint 32 页码,

_ in _ D2 D1 _ rect _ f image table area,_In_ D2D1_SIZE_F pageSize,

_ In _ opt _ iStream * page printicket stream)

{

//创建一个新的 D2D 设备上下文来生成打印命令列表。

// D2D 设备上下文是有状态的,因此唯一的设备上下文必须

//用于每个线程。

comptr<id2d1devicecontext>D2 dconte;</id2d1devicecontext>

DX::throwifffailed(

m _ d2d DEVICE-> CreateDeviceContext(d2d 1 _ DEVICE _ CONTEXT _ OPTIONS _ NONE,&d2dContext)

);

ComPtr <id2d1commandlist>打印命令列表;</id2d1commandlist>

DX::throwifffailed(

d2dContext->CreateCommandList(&printCommandList)

);

d2dcontext->

//为打印创建并初始化页面渲染器上下文。

//在这种情况下,我们希望使用已经有的位图源

//嵌入其中的颜色上下文。因此,我们将空值传递给

//颜色上下文参数。

simpletext enderer ^ printpagerenderercontext = ref new simpletext enderer(imageablearea,d2dContext)。Get(),

DrawTypes::Printing,this);

D2 dcontext-> begin draw();

//在命令列表上绘制页面内容。

//下面 1.0f 表示打印内容不缩放。

//“drawing types::Printing”下面表示是打印案例。

printpagerenderercontext-> draw(1.0f);

//文档源处理 D2DERR _ RECREATETARGET,这里抛出就可以了。

dx::throwiffailed(D2 dcontext-> end raw());

DX::ThrowIfFailed(printCommandList-> Close());

DX::ThrowIfFailed(m _ d2dPrintControl-> AddPage(printCommandList。Get(),pageSize,

pageprinticket stream));

}