left-icon

Direct2D Succinctly®
by Chris Rose

Previous
Chapter

of
A
A
A

CHAPTER 11

Margins

Margins


We now return to our charting application, where we will add a margin around the edge. I am going to add to the code as it was after the “Navigating between Multiple XAML Pages” chapter. Adding a margin to a chart is important, as it can be used to separate the title, axis labels, and grid figures from the data being plotted. The following margin class consists of a collection of four rectangles and a solid color brush. The rectangles form a border around the visible chart area. Add a Margin.h and Margin.cpp file to your project.

// Margin.h

#pragma once

#include "DirectXBase.h"

enum MarginStyle { Absolute, WindowSizeDependent };

class Margin {

     ID2D1SolidColorBrush* m_solidBrush; // Brush to draw margin

     D2D1::ColorF m_color;  // The color of the margin   

     D2D1_RECT_F m_leftRect; // Rectangles which make the margin

     D2D1_RECT_F m_rightRect;

     D2D1_RECT_F m_topRect;

     D2D1_RECT_F m_bottomRect;    

     MarginStyle m_style;   // Style is Absolute or Window size dependent

     // The size of the margin

     float m_left, m_right, m_top, m_bottom;

public:

     // Public constructor

     Margin(float left, float right, float top, float bottom,

D2D1::ColorF color, MarginStyle style);

     // Create the rectangles to draw the margin

     void CreateWindowSizeDependentResources

          (Microsoft::WRL::ComPtr<ID2D1DeviceContext> context);

     // Create the solid brush to draw with

     void CreateDeviceDependentResources

          (Microsoft::WRL::ComPtr<ID2D1DeviceContext> context);

     

     // The render method needs to know the panning and scaling

     void Render(Microsoft::WRL::ComPtr<ID2D1DeviceContext> context);

     };

// Margin.cpp

#include "pch.h"

#include "Margin.h"

Margin::Margin(float left, float right, float top, float bottom,

     D2D1::ColorF color, MarginStyle style)  : m_color(0) {

// Save the parameters for the create resources methods

this->m_color = color; m_style = style; this->m_left = left; this->m_right = right;

this->m_top = top; this->m_bottom = bottom;

}

void Margin::CreateWindowSizeDependentResources(

     Microsoft::WRL::ComPtr<ID2D1DeviceContext> context) {

// If the sizes of the margin passed were percentages of the screen

// we have to multiply the values before creating the rectangles:

if(m_style == MarginStyle::WindowSizeDependent) {

     m_left = context->GetSize().width * m_left;

     m_right = context->GetSize().width * m_right;

     m_top = context->GetSize().height * m_top;

     m_bottom = context->GetSize().height * m_bottom;

     }

// Left rectangle

m_leftRect.left = 0; m_leftRect.right = m_left;

m_leftRect.top = 0; m_leftRect.bottom = context->GetSize().height;

     

// Right rectangle

m_rightRect.left = context->GetSize().width - m_right;

m_rightRect.right = context->GetSize().width;

m_rightRect.top = 0; m_rightRect.bottom = context->GetSize().height;

     

// Top margin

m_topRect.left = m_left;

m_topRect.right = context->GetSize().width - m_right;

m_topRect.top = 0; m_topRect.bottom = m_top;

// Bottom margin

m_bottomRect.left = m_left;

m_bottomRect.right = context->GetSize().width - m_right;

m_bottomRect.top = context->GetSize().height - m_bottom;

m_bottomRect.bottom = context->GetSize().height;

}

void Margin::CreateDeviceDependentResources

     (Microsoft::WRL::ComPtr<ID2D1DeviceContext> context) {

// Create the brush

DX::ThrowIfFailed(context->CreateSolidColorBrush(m_color, &m_solidBrush));

}

void Margin::Render(Microsoft::WRL::ComPtr<ID2D1DeviceContext> context) {

// Draw the left margin

context->FillRectangle(m_leftRect, m_solidBrush);

// Draw the right margin

context->FillRectangle(m_rightRect, m_solidBrush);

// Draw the top margin

context->FillRectangle(m_topRect, m_solidBrush);

// Draw the bottom margin

context->FillRectangle(m_bottomRect, m_solidBrush);

}

To add a margin object, we need to add a member variable to the graph renderer. Load its resources when appropriate and render it.

Note: The margin class takes a MarginStyle enum as one of the parameters to the constructor. I have added this to enable margins to be created dependent on the size and/or resolution of the device running the application. Using Absolute as this parameter results in the margin's thickness parameters being interpreted as pixels. Using WindowSizeDependent means that the parameters passed in are interpreted as a percentage of the context width and height.

Add the Margin.h file to the Graph Renderer.h headers section:

//

// Additional headers for graph objects here

//

#include "GradientBackground.h"

#include "ScatterPlot.h"

#include "LineChart.h"

#include "Axes.h"

#include "Margin.h"

Add the member variables to the GraphRenderer.h file.

// Plottable data

     GraphVariable* m_graphVariable;

     GraphVariable* m_lineChart;

     // Axes

     Axes* m_axes;

     // Margin

     Margin* m_margin;

Call the constructor(s) for the margin(s) in the GraphRenderer constructor; this can be done at any time. I have placed it after constructing the m_axes object.

// Create the line chart

m_lineChart = new LineChart(x, y, count, D2D1::ColorF::Chocolate, 5.0f);

delete[] x;

delete[] y;

// Create the Axes

m_axes = new Axes(D2D1::ColorF::Black, 5.0f, 0.75f);

// Create the margin

m_margin = new Margin(0.1f, 0.1f, 0.1f, 0.1f, // 10% of window size

     D2D1::ColorF(0.38f, 0.66f, 0.74f, 1.0f), MarginStyle::WindowSizeDependent);

}

Call the CreateDeviceDependentResources method for the new m_margin object in the GraphRenderer::CreateDeviceResources method (this will create the margin’s brush).

void GraphRenderer::CreateDeviceResources() {

DirectXBase::CreateDeviceResources();

// Call the create device resources for our graph variable

m_graphVariable->CreateDeviceDependentResources(m_d2dContext);

// Create device resources for the line chart

m_lineChart->CreateDeviceDependentResources(m_d2dContext);

// Create the brush for the Axes

m_axes->CreateDeviceDependentResources(m_d2dContext);

// Create the solid brush for the text

DX::ThrowIfFailed(

     m_d2dContext->CreateSolidColorBrush(ColorF(ColorF::Black),&m_blackBrush));

// Create the margin's device dependent resources

m_margin->CreateDeviceDependentResources(m_d2dContext);

}

Call the CreateWindowSizeDependentResources method for the margin(s) in the GraphRenderer::CreateWindowSizeDependentResources method (this will create the rectangles to fill for the margin).

void GraphRenderer::CreateWindowSizeDependentResources() {

DirectXBase::CreateWindowSizeDependentResources();

// Create window size resources for gradient background

m_gradientBackground->CreateWindowSizeDependentResources(m_d2dContext);

// Set the initial pan value so the lowest node is visible in the corner

m_pan.X = -m_graphVariable->GetMinX();

m_pan.Y = m_graphVariable->GetMinY();

// Create window size dependent resources for the margin

m_margin->CreateWindowSizeDependentResources(m_d2dContext);

}

And finally, call Render on the margin(s) in the GraphRenderer::Render method. I have rendered the margins immediately after the transformation matrix is reset, and just prior to rendering the FPS counter. We originally added this reset to make sure the FPS counter was not affected by the pan and zoom, but we can also use it to ensure the margin is not transformed.

//

// Draw objects here

//

// Render the graph variable(s)

m_lineChart->Render(m_d2dContext);

m_graphVariable->Render(m_d2dContext);

// Reset the transform matrix so the time and FPS do not pan or zoom

m_d2dContext->SetTransform(m_orientationTransform2D);

// Render the margin

m_margin->Render(m_d2dContext);

// Set up the string to print:

std::wstring s = std::wstring(

     L"Total Time: ") + std::to_wstring(m_timeTotal) +

     std::wstring(L" FPS: ") + std::to_wstring(

          (int)(0.5f+1.0f/m_timeDelta)); // FPS rounded to nearest int

Upon debugging the application, you should see a stormy cyan colored margin surrounding the window, as shown in Figure 34.

Margins

Scroll To Top
Disclaimer
DISCLAIMER: Web reader is currently in beta. Please report any issues through our support system. PDF and Kindle format files are also available for download.

Previous

Next



You are one step away from downloading ebooks from the Succinctly® series premier collection!
A confirmation has been sent to your email address. Please check and confirm your email subscription to complete the download.