Skip to content

Instantly share code, notes, and snippets.

@egtra
Last active September 3, 2016 19:08
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save egtra/6045976 to your computer and use it in GitHub Desktop.
Save egtra/6045976 to your computer and use it in GitHub Desktop.
Window 8.1のDirect2Dで絵文字をカラーで表示するコード(Visual Studio 2013用)。D2D1_DARW_TEXT_OPTIONS_ENABLE_COLOR_FONTがミソ。
/*
NYSL Version 0.9982
----------------------------------------
A. 本ソフトウェアは Everyone'sWare です。このソフトを手にした一人一人が、
ご自分の作ったものを扱うのと同じように、自由に利用することが出来ます。
A-1. フリーウェアです。作者からは使用料等を要求しません。
A-2. 有料無料や媒体の如何を問わず、自由に転載・再配布できます。
A-3. いかなる種類の 改変・他プログラムでの利用 を行っても構いません。
A-4. 変更したものや部分的に使用したものは、あなたのものになります。
公開する場合は、あなたの名前の下で行って下さい。
B. このソフトを利用することによって生じた損害等について、作者は
責任を負わないものとします。各自の責任においてご利用下さい。
C. 著作者人格権は Egtra に帰属します。著作権は放棄します。
D. 以上の3項は、ソース・実行バイナリの双方に適用されます。
NYSL Version 0.9982 (en) (Unofficial)
----------------------------------------
A. This software is "Everyone'sWare". It means:
Anybody who has this software can use it as if he/she is
the author.
A-1. Freeware. No fee is required.
A-2. You can freely redistribute this software.
A-3. You can freely modify this software. And the source
may be used in any software with no limitation.
A-4. When you release a modified version to public, you
must publish it with your name.
B. The author is not responsible for any kind of damages or loss
while using or misusing this software, which is distributed
"AS IS". No warranty of any kind is expressed or implied.
You use AT YOUR OWN RISK.
C. Copyrighted to Egtra.
D. Above three clauses are applied both to source and binary
form of this software.
*/
#define _WIN32_WINNT 0x0603
#define OEMRESOURCE
#include <system_error>
#include <SDKDDKVer.h>
#include <windows.h>
#include <windowsx.h>
#include <d2d1.h>
#include <dwrite.h>
#include <tchar.h>
#include <comdef.h>
#pragma comment(lib, "d2d1.lib")
#pragma comment(lib, "dwrite.lib")
#define EGTRA_COM_SMARTPTR_TYPEDEF(iface) _COM_SMARTPTR_TYPEDEF(iface, __uuidof(iface));
EGTRA_COM_SMARTPTR_TYPEDEF(ID2D1Factory);
EGTRA_COM_SMARTPTR_TYPEDEF(IDWriteFactory);
EGTRA_COM_SMARTPTR_TYPEDEF(ID2D1HwndRenderTarget);
EGTRA_COM_SMARTPTR_TYPEDEF(ID2D1SolidColorBrush);
EGTRA_COM_SMARTPTR_TYPEDEF(IDWriteTextFormat);
void ThrowIfFailed(HRESULT hr)
{
if (FAILED(hr))
{
_com_issue_error(hr);
}
}
class WindowBase
{
public:
static void InitApplication(HINSTANCE hinst)
{
WNDCLASSEX wcex = {
sizeof wcex,
CS_HREDRAW | CS_VREDRAW,
WndProcEntry,
0, 0,
hinst,
static_cast<HICON>(LoadImage(nullptr, MAKEINTRESOURCE(OIC_SAMPLE), IMAGE_ICON, 0, 0, LR_DEFAULTSIZE | LR_SHARED)),
static_cast<HCURSOR>(LoadImage(nullptr, MAKEINTRESOURCE(OCR_NORMAL), IMAGE_CURSOR, 0, 0, LR_DEFAULTSIZE | LR_SHARED)),
reinterpret_cast<HBRUSH>(COLOR_WINDOW + 1),
nullptr,
TEXT("WindowBase Class"),
nullptr,
};
windowClass = RegisterClassEx(&wcex);
if (!windowClass)
{
throw std::system_error(static_cast<int>(GetLastError()), std::system_category());
}
}
WindowBase() : hwnd() {}
void InitInstance()
{
hwnd = CreateWindowEx(
WS_EX_APPWINDOW | WS_EX_OVERLAPPEDWINDOW,
MAKEINTATOM(windowClass),
TEXT(""),
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
nullptr,
nullptr,
nullptr,
this);
if (!hwnd)
{
throw std::system_error(static_cast<int>(GetLastError()), std::system_category());
}
}
HWND GetWindow() { return hwnd; }
protected:
virtual LRESULT WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) = 0;
private:
static BOOL OnNCCreate(HWND hwnd, CREATESTRUCT const* pcs)
{
SetWindowLongPtr(hwnd, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(pcs->lpCreateParams));
return TRUE;
}
static LRESULT CALLBACK WndProcEntry(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg)
{
HANDLE_MSG(hwnd, WM_NCCREATE, OnNCCreate);
}
if (auto pwnd = reinterpret_cast<WindowBase*>(GetWindowLongPtr(hwnd, GWLP_USERDATA)))
{
return pwnd->WndProc(hwnd, msg, wParam, lParam);
}
else
{
return DefWindowProc(hwnd, msg, wParam, lParam);
}
}
static ATOM windowClass;
HWND hwnd;
//WindowBase(WindowBase const&) = delete;
//WindowBase& operator=(WindowBase const&) = delete;
WindowBase(WindowBase const&);
WindowBase& operator=(WindowBase const&);
};
class TestWindow : public WindowBase
{
public:
TestWindow()
{
CreateDeviceIndependentResources();
}
private:
void CreateDeviceIndependentResources()
{
ThrowIfFailed(D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &d2dFactory));
ThrowIfFailed(DWriteCreateFactory(
DWRITE_FACTORY_TYPE_SHARED,
__uuidof(*dwFactory),
reinterpret_cast<IUnknown**>(&dwFactory)));
ThrowIfFailed(dwFactory->CreateTextFormat(
L"Segoe UI",
nullptr,
DWRITE_FONT_WEIGHT_NORMAL,
DWRITE_FONT_STYLE_NORMAL,
DWRITE_FONT_STRETCH_NORMAL,
24,
L"", //locale
&textFormat));
}
void CreateDeviceResources()
{
if (!renderTarget)
{
RECT rc;
GetClientRect(GetWindow(), &rc);
ThrowIfFailed(d2dFactory->CreateHwndRenderTarget(
D2D1::RenderTargetProperties(),
D2D1::HwndRenderTargetProperties(GetWindow(), D2D1_SIZE_U{rc.right, rc.bottom}),
&renderTarget));
}
if (!blackBrush)
{
ThrowIfFailed(renderTarget->CreateSolidColorBrush(
D2D1::ColorF(D2D1::ColorF::Black),
&blackBrush));
}
}
void DiscardDeviceResources()
{
renderTarget = nullptr;
blackBrush = nullptr;
}
void OnRender()
{
static const WCHAR Text[] =
L"\U0001F300\U0001F301\U0001F302\U0001F303\U0001F304\U0001F305"
L"\U0001F306\U0001F307\U0001F308\U0001F309\U0001F30A\U0001F30B"
L"\U0001F30C\U0001F30D\U0001F30E\U0001F30F\U0001F310\U0001F311"
L"\U0001F312\U0001F313\U0001F314\U0001F315\U0001F316\U0001F317"
L"\U0001F318\U0001F319\U0001F31A\U0001F31B\U0001F31C\U0001F31D"
L"\U0001F31E\U0001F31F\U0001F320\U0001F330\U0001F331\U0001F332"
L"\U0001F333\U0001F334\U0001F335\U0001F337\U0001F338\U0001F339"
L"\U0001F33A\U0001F33B\U0001F33C\U0001F33D\U0001F33E\U0001F33F"
L"\U0001F340\U0001F341\U0001F342\U0001F343\U0001F344\U0001F345"
L"\U0001F346\U0001F347\U0001F348\U0001F349\U0001F34A\U0001F34B"
L"\U0001F34C\U0001F34D\U0001F34E\U0001F34F\U0001F350\U0001F351"
L"\U0001F352\U0001F353\U0001F354\U0001F355\U0001F356\U0001F357"
L"\U0001F358\U0001F359\U0001F35A\U0001F35B\U0001F35C\U0001F35D"
L"\U0001F35E\U0001F35F\U0001F360\U0001F361\U0001F362\U0001F363"
L"\U0001F364\U0001F365\U0001F366\U0001F367\U0001F368\U0001F369"
L"\U0001F36A\U0001F36B\U0001F36C\U0001F36D\U0001F36E\U0001F36F"
L"\U0001F370\U0001F371\U0001F372\U0001F373\U0001F374\U0001F375"
L"\U0001F376\U0001F377\U0001F378\U0001F379\U0001F37A\U0001F37B"
L"\U0001F37C\U0001F380\U0001F381\U0001F382\U0001F383\U0001F384"
L"\U0001F385\U0001F386\U0001F387\U0001F388\U0001F389\U0001F38A"
L"\U0001F38B\U0001F38C\U0001F38D\U0001F38E\U0001F38F\U0001F390"
L"\U0001F391\U0001F392\U0001F393\U0001F3A0\U0001F3A1\U0001F3A2"
L"\U0001F3A3\U0001F3A4\U0001F3A5\U0001F3A6\U0001F3A7\U0001F3A8"
L"\U0001F3A9\U0001F3AA\U0001F3AB\U0001F3AC\U0001F3AD\U0001F3AE"
L"\U0001F3AF\U0001F3B0\U0001F3B1\U0001F3B2\U0001F3B3\U0001F3B4"
L"\U0001F3B5\U0001F3B6\U0001F3B7\U0001F3B8\U0001F3B9\U0001F3BA"
L"\U0001F3BB\U0001F3BC\U0001F3BD\U0001F3BE\U0001F3BF\U0001F3C0"
L"\U0001F3C1\U0001F3C2\U0001F3C3\U0001F3C4\U0001F3C6\U0001F3C7"
L"\U0001F3C8\U0001F3C9\U0001F3CA\U0001F3E0\U0001F3E1\U0001F3E2"
L"\U0001F3E3\U0001F3E4\U0001F3E5\U0001F3E6\U0001F3E7\U0001F3E8"
L"\U0001F3E9\U0001F3EA\U0001F3EB\U0001F3EC\U0001F3ED\U0001F3EE"
L"\U0001F3EF\U0001F3F0\U0001F400\U0001F401\U0001F402\U0001F403"
L"\U0001F404\U0001F405\U0001F406\U0001F407\U0001F408\U0001F409"
L"\U0001F40A\U0001F40B\U0001F40C\U0001F40D\U0001F40E\U0001F40F"
L"\U0001F410\U0001F411\U0001F412\U0001F413\U0001F414\U0001F415"
L"\U0001F416\U0001F417\U0001F418\U0001F419\U0001F41A\U0001F41B"
L"\U0001F41C\U0001F41D\U0001F41E\U0001F41F\U0001F420\U0001F421"
L"\U0001F422\U0001F423\U0001F424\U0001F425\U0001F426\U0001F427"
L"\U0001F428\U0001F429\U0001F42A\U0001F42B\U0001F42C\U0001F42D"
L"\U0001F42E\U0001F42F\U0001F430\U0001F431\U0001F432\U0001F433"
L"\U0001F434\U0001F435\U0001F436\U0001F437\U0001F438\U0001F439"
L"\U0001F43A\U0001F43B\U0001F43C\U0001F43D\U0001F43E\U0001F440"
L"\U0001F442\U0001F443\U0001F444\U0001F445\U0001F446\U0001F447"
L"\U0001F448\U0001F449\U0001F44A\U0001F44B\U0001F44C\U0001F44D"
L"\U0001F44E\U0001F44F\U0001F450\U0001F451\U0001F452\U0001F453"
L"\U0001F454\U0001F455\U0001F456\U0001F457\U0001F458\U0001F459"
L"\U0001F45A\U0001F45B\U0001F45C\U0001F45D\U0001F45E\U0001F45F"
L"\U0001F460\U0001F461\U0001F462\U0001F463\U0001F464\U0001F465"
L"\U0001F466\U0001F467\U0001F468\U0001F469\U0001F46A\U0001F46B"
L"\U0001F46C\U0001F46D\U0001F46E\U0001F46F\U0001F470\U0001F471"
L"\U0001F472\U0001F473\U0001F474\U0001F475\U0001F476\U0001F477"
L"\U0001F478\U0001F479\U0001F47A\U0001F47B\U0001F47C\U0001F47D"
L"\U0001F47E\U0001F47F\U0001F480\U0001F481\U0001F482\U0001F483"
L"\U0001F484\U0001F485\U0001F486\U0001F487\U0001F488\U0001F489"
L"\U0001F48A\U0001F48B\U0001F48C\U0001F48D\U0001F48E\U0001F48F"
L"\U0001F490\U0001F491\U0001F492\U0001F493\U0001F494\U0001F495"
L"\U0001F496\U0001F497\U0001F498\U0001F499\U0001F49A\U0001F49B"
L"\U0001F49C\U0001F49D\U0001F49E\U0001F49F\U0001F4A0\U0001F4A1"
L"\U0001F4A2\U0001F4A3\U0001F4A4\U0001F4A5\U0001F4A6\U0001F4A7"
L"\U0001F4A8\U0001F4A9\U0001F4AA\U0001F4AB\U0001F4AC\U0001F4AD"
L"\U0001F4AE\U0001F4AF\U0001F4B0\U0001F4B1\U0001F4B2\U0001F4B3"
L"\U0001F4B4\U0001F4B5\U0001F4B6\U0001F4B7\U0001F4B8\U0001F4B9"
L"\U0001F4BA\U0001F4BB\U0001F4BC\U0001F4BD\U0001F4BE\U0001F4BF"
L"\U0001F4C0\U0001F4C1\U0001F4C2\U0001F4C3\U0001F4C4\U0001F4C5"
L"\U0001F4C6\U0001F4C7\U0001F4C8\U0001F4C9\U0001F4CA\U0001F4CB"
L"\U0001F4CC\U0001F4CD\U0001F4CE\U0001F4CF\U0001F4D0\U0001F4D1"
L"\U0001F4D2\U0001F4D3\U0001F4D4\U0001F4D5\U0001F4D6\U0001F4D7"
L"\U0001F4D8\U0001F4D9\U0001F4DA\U0001F4DB\U0001F4DC\U0001F4DD"
L"\U0001F4DE\U0001F4DF\U0001F4E0\U0001F4E1\U0001F4E2\U0001F4E3"
L"\U0001F4E4\U0001F4E5\U0001F4E6\U0001F4E7\U0001F4E8\U0001F4E9"
L"\U0001F4EA\U0001F4EB\U0001F4EC\U0001F4ED\U0001F4EE\U0001F4EF"
L"\U0001F4F0\U0001F4F1\U0001F4F2\U0001F4F3\U0001F4F4\U0001F4F5"
L"\U0001F4F6\U0001F4F7\U0001F4F9\U0001F4FA\U0001F4FB\U0001F4FC"
L"\U0001F500\U0001F501\U0001F502\U0001F503\U0001F504\U0001F505"
L"\U0001F506\U0001F507\U0001F508\U0001F509\U0001F50A\U0001F50B"
L"\U0001F50C\U0001F50D\U0001F50E\U0001F50F\U0001F510\U0001F511"
L"\U0001F512\U0001F513\U0001F514\U0001F515\U0001F516\U0001F517"
L"\U0001F518\U0001F519\U0001F51A\U0001F51B\U0001F51C\U0001F51D"
L"\U0001F51E\U0001F51F\U0001F520\U0001F521\U0001F522\U0001F523"
L"\U0001F524\U0001F525\U0001F526\U0001F527\U0001F528\U0001F529"
L"\U0001F52A\U0001F52B\U0001F52C\U0001F52D\U0001F52E\U0001F52F"
L"\U0001F530\U0001F531\U0001F532\U0001F533\U0001F534\U0001F535"
L"\U0001F536\U0001F537\U0001F538\U0001F539\U0001F53A\U0001F53B"
L"\U0001F53C\U0001F53D\U0001F550\U0001F551\U0001F552\U0001F553"
L"\U0001F554\U0001F555\U0001F556\U0001F557\U0001F558\U0001F559"
L"\U0001F55A\U0001F55B\U0001F55C\U0001F55D\U0001F55E\U0001F55F"
L"\U0001F560\U0001F561\U0001F562\U0001F563\U0001F564\U0001F565"
L"\U0001F566\U0001F567";
CreateDeviceResources();
if (!(renderTarget->CheckWindowState() & D2D1_WINDOW_STATE_OCCLUDED))
{
auto size = renderTarget->GetSize();
renderTarget->BeginDraw();
renderTarget->SetTransform(D2D1::Matrix3x2F::Identity());
renderTarget->Clear(D2D1::ColorF(D2D1::ColorF::White));
renderTarget->DrawText(
Text, ARRAYSIZE(Text) - 1,
textFormat,
D2D1_RECT_F{0, 0, size.width, size.height},
blackBrush,
D2D1_DRAW_TEXT_OPTIONS_ENABLE_COLOR_FONT);
auto hr = renderTarget->EndDraw();
if (hr == D2DERR_RECREATE_TARGET)
{
DiscardDeviceResources();
}
}
}
void OnDestroy(HWND)
{
PostQuitMessage(0);
}
void OnPaint(HWND)
{
ValidateRect(GetWindow(), nullptr);
OnRender();
}
BOOL OnEraseBackground(HWND, HDC)
{
return TRUE;
}
void OnSize(HWND /*hwnd*/, UINT /*state*/, int cx, int cy)
{
if (renderTarget)
{
renderTarget->Resize(D2D1_SIZE_U{static_cast<UINT>(cx), static_cast<UINT>(cy)});
}
}
void OnDisplayChange(HWND hwnd, UINT /*bitsPerPixel*/, UINT /*cxScreen*/, UINT /*cyScreen*/)
{
InvalidateRect(hwnd, nullptr, TRUE);
}
virtual LRESULT WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) override
{
try
{
switch (msg)
{
HANDLE_MSG(hwnd, WM_DESTROY, OnDestroy);
HANDLE_MSG(hwnd, WM_PAINT, OnPaint);
HANDLE_MSG(hwnd, WM_ERASEBKGND, OnEraseBackground);
HANDLE_MSG(hwnd, WM_SIZE, OnSize);
HANDLE_MSG(hwnd, WM_DISPLAYCHANGE, OnDisplayChange);
}
return DefWindowProc(hwnd, msg, wParam, lParam);
}
catch (_com_error const& e)
{
OutputDebugString(e.ErrorMessage());
return 0;
}
}
// device independent resources
ID2D1FactoryPtr d2dFactory;
IDWriteFactoryPtr dwFactory;
IDWriteTextFormatPtr textFormat;
// device dependent resources
ID2D1HwndRenderTargetPtr renderTarget;
ID2D1SolidColorBrushPtr blackBrush;
TestWindow(TestWindow const&);
TestWindow& operator=(TestWindow const&);
};
ATOM WindowBase::windowClass;
int WINAPI _tWinMain(
HINSTANCE hinst, HINSTANCE, LPTSTR, int cmdShow)
{
try
{
WindowBase::InitApplication(hinst);
TestWindow wnd;
wnd.InitInstance();
ShowWindow(wnd.GetWindow(), cmdShow);
UpdateWindow(wnd.GetWindow());
for (;;)
{
MSG msg = {};
auto ret = GetMessage(&msg, nullptr, 0, 0);
if (ret == 0 || ret == -1)
{
return ret;
}
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
catch (_com_error const& e)
{
OutputDebugString(e.ErrorMessage());
return 1;
}
catch (std::exception const& e)
{
OutputDebugStringA(e.what());
return 1;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment