// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
// PARTICULAR PURPOSE.
//
// Copyright (c) Microsoft Corporation. All rights reserved
#include "SimpleDirect2dApplication.h"
//
// Provides the entry point to the application.
//
int WINAPI WinMain(
HINSTANCE /* hInstance */,
HINSTANCE /* hPrevInstance */,
LPSTR /* lpCmdLine */,
int /* nCmdShow */
)
{
// Ignore the return value because we want to continue running even in the
// unlikely event that HeapSetInformation fails.
HeapSetInformation(NULL, HeapEnableTerminationOnCorruption, NULL, 0);
if (SUCCEEDED(CoInitialize(NULL)))
{
{
DemoApp app;
if (SUCCEEDED(app.Initialize()))
{
app.RunMessageLoop();
}
}
CoUninitialize();
}
return 0;
}
//
// Initialize members.
//
DemoApp::DemoApp() :
m_hwnd(NULL),
m_pD2DFactory(NULL),
m_pWICFactory(NULL),
m_pDWriteFactory(NULL),
m_pRenderTarget(NULL),
m_pTextFormat(NULL),
m_pPathGeometry(NULL),
m_pLinearGradientBrush(NULL),
m_pBlackBrush(NULL),
m_pGridPatternBitmapBrush(NULL),
m_pBitmap(NULL),
m_pAnotherBitmap(NULL)
{
}
//
// Release resources.
//
DemoApp::~DemoApp()
{
SafeRelease(&m_pD2DFactory);
SafeRelease(&m_pWICFactory);
SafeRelease(&m_pDWriteFactory);
SafeRelease(&m_pRenderTarget);
SafeRelease(&m_pTextFormat);
SafeRelease(&m_pPathGeometry);
SafeRelease(&m_pLinearGradientBrush);
SafeRelease(&m_pBlackBrush);
SafeRelease(&m_pGridPatternBitmapBrush);
SafeRelease(&m_pBitmap);
SafeRelease(&m_pAnotherBitmap);
}
//
// Creates the application window and initializes
// device-independent resources.
//
HRESULT DemoApp::Initialize()
{
// Initialize device-indpendent resources, such
// as the Direct2D factory.
HRESULT hr = CreateDeviceIndependentResources();
if (SUCCEEDED(hr))
{
// Register the window class.
WNDCLASSEX wcex = { sizeof(wcex) };
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = WndProc;
wcex.cbWndExtra = sizeof(LONG_PTR);
wcex.hInstance = HINST_THISCOMPONENT;
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.lpszClassName = L"D2DDemoApp";
RegisterClassEx(&wcex);
// Create the application window.
//
// Because the CreateWindow function takes its size in pixels, we
// obtain the system DPI and use it to scale the window size.
FLOAT dpiX, dpiY;
m_pD2DFactory->GetDesktopDpi(&dpiX, &dpiY);
// Create the application window.
m_hwnd = CreateWindow(
L"D2DDemoApp",
L"Direct2D Demo Application",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,
CW_USEDEFAULT,
static_cast<UINT>(ceil(640.f * dpiX / 96.f)),
static_cast<UINT>(ceil(480.f * dpiY / 96.f)),
NULL,
NULL,
HINST_THISCOMPONENT,
this
);
hr = m_hwnd ? S_OK : E_FAIL;
if (SUCCEEDED(hr))
{
ShowWindow(m_hwnd, SW_SHOWNORMAL);
UpdateWindow(m_hwnd);
}
}
return hr;
}
//
// Create resources which are not bound
// to any device. Their lifetime effectively extends for the
// duration of the app. These resources include the Direct2D,
// DirectWrite, and WIC factories; and a DirectWrite Text Format object
// (used for identifying particular font characteristics) and
// a Direct2D geometry.
//
HRESULT DemoApp::CreateDeviceIndependentResources()
{
static const WCHAR msc_fontName[] = L"Verdana";
static const FLOAT msc_fontSize = 50;
// Create a Direct2D factory.
ID2D1GeometrySink *pSink = NULL;
HRESULT hr = D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &m_pD2DFactory);
if (SUCCEEDED(hr))
{
// Create WIC factory.
hr = CoCreateInstance(
CLSID_WICImagingFactory,
NULL,
CLSCTX_INPROC_SERVER,
IID_PPV_ARGS(&m_pWICFactory)
);
}
if (SUCCEEDED(hr))
{
// Create a DirectWrite factory.
hr = DWriteCreateFactory(
DWRITE_FACTORY_TYPE_SHARED,
__uuidof(m_pDWriteFactory),
reinterpret_cast<IUnknown **>(&m_pDWriteFactory)
);
}
if (SUCCEEDED(hr))
{
// Create a DirectWrite text format object.
hr = m_pDWriteFactory->CreateTextFormat(
msc_fontName,
NULL,
DWRITE_FONT_WEIGHT_NORMAL,
DWRITE_FONT_STYLE_NORMAL,
DWRITE_FONT_STRETCH_NORMAL,
msc_fontSize,
L"", //locale
&m_pTextFormat
);
}
if (SUCCEEDED(hr))
{
// Center the text horizontally and vertically.
m_pTextFormat->SetTextAlignment(DWRITE_TEXT_ALIGNMENT_CENTER);
m_pTextFormat->SetParagraphAlignment(DWRITE_PARAGRAPH_ALIGNMENT_CENTER);
}
if (SUCCEEDED(hr))
{
// Create a path geometry.
hr = m_pD2DFactory->CreatePathGeometry(&m_pPathGeometry);
}
if (SUCCEEDED(hr))
{
// Use the geometry sink to write to the path geometry.
hr = m_pPathGeometry->Open(&pSink);
}
if (SUCCEEDED(hr))
{
pSink->SetFillMode(D2D1_FILL_MODE_ALTERNATE);
pSink->BeginFigure(
D2D1::Point2F(0, 0),
D2D1_FIGURE_BEGIN_FILLED
);
pSink->AddLine(D2D1::Point2F(200, 0));
pSink->AddBezier(
D2D1::BezierSegment(
D2D1::Point2F(150, 50),
D2D1::Point2F(150, 150),
D2D1::Point2F(200, 200))
);
pSink->AddLine(D2D1::Point2F(0, 200));
pSink->AddBezier(
D2D1::BezierSegment(
D2D1::Point2F(50, 150),
D2D1::Point2F(50, 50),
D2D1::Point2F(0, 0))
);
pSink->EndFigure(D2D1_FIGURE_END_CLOSED);
hr = pSink->Close();
}
SafeRelease(&pSink);
return hr;
}
//
// This method creates resources which are bound to a particular
// Direct3D device. It's all centralized here, in case the resources
// need to be recreated in case of Direct3D device loss (eg. display
// change, remoting, removal of video card, etc).
//
HRESULT DemoApp::CreateDeviceResources()
{
HRESULT hr = S_OK;
if (!m_pRenderTarget)
{
RECT rc;
GetClientRect(m_hwnd, &rc);
D2D1_SIZE_U size = D2D1::SizeU(
rc.right - rc.left,
rc.bottom - rc.top
);
// Create a Direct2D render target.
hr = m_pD2DFactory->CreateHwndRenderTarget(
D2D1::RenderTargetProperties(),
D2D1::HwndRenderTargetProperties(m_hwnd, size),
&m_pRenderTarget
);
if (SUCCEEDED(hr))
{
// Create a black brush.
hr = m_pRenderTarget->CreateSolidColorBrush(
D2D1::ColorF(D2D1::ColorF::Black),
&m_pBlackBrush
);
}
if (SUCCEEDED(hr))
{
ID2D1GradientStopCollection *pGradientStops = NULL;
// Create a linear gradient.
static const D2D1_GRADIENT_STOP stops[] =
{
{ 0.f, { 0.f, 1.f, 1.f, 0.25f } },
{ 1.f, { 0.f, 0.f, 1.f, 1.f } },
};
hr = m_pRenderTarget->CreateGradien