

[DirectWriteでHello,
Worldを表示するプログラムがビルドエラーになる](https://ja.stackoverflow.com/questions/47253/directwrite%e3%81%a7hello-
world%e3%82%92%e8%a1%a8%e7%a4%ba%e3%81%99%e3%82%8b%e3%83%97%e3%83%ad%e3%82%b0%e3%83%a9%e3%83%a0%e3%81%8c%e3%83%93%e3%83%ab%e3%83%89%e3%82%a8%e3%83%a9%e3%83%bc%e3%81%ab%e3%81%aa%e3%82%8b/47256#47256)  
の続きです。  
ビルドエラーは起きなくなったのですが、実行しても何も表示されません。  
なぜでしょうか?  
デバッグ実行すると、白いWidnowが表示されるだけでHello, Worldが表示されません。  
特にエラーも出ておらずWindowを閉じると正常に終了します。

* * *

## 追記

実行している間はカーソルがとても早く切り替わることに気づきました。(waitと普通の形状に1秒間に5~6回切り替わる)  
なぜ、このようなことがおこるのでしょうか?

CreateSolidBrushでthisがnullptrであるというエラーを修正したのでMyDWRITE.cppを再掲します。

[code]

    // MyDWRITE.cpp : アプリケーションのエントリ ポイントを定義します。
    //
    
    #include "stdafx.h"
    #include "MyDWRITE.h"
    
    
    
    #define MAX_LOADSTRING 100
    template <class T> inline void SafeRelease(T **ppT)
    {
        if (*ppT)
        {
            (*ppT)->Release();
            *ppT = NULL;
        }
    }
    // グローバル変数:
    HINSTANCE hInst;                                // 現在のインターフェイス
    WCHAR szTitle[MAX_LOADSTRING];                  // タイトル バーのテキスト
    WCHAR szWindowClass[MAX_LOADSTRING];            // メイン ウィンドウ クラス名
    ID2D1HwndRenderTarget *pIRenderTarget;
    
    
    
    // このコード モジュールに含まれる関数の宣言を転送します:
    ATOM                MyRegisterClass(HINSTANCE hInstance);
    BOOL                InitInstance(HINSTANCE, int);
    LRESULT CALLBACK    WndProc(HWND, UINT, WPARAM, LPARAM);
    INT_PTR CALLBACK    About(HWND, UINT, WPARAM, LPARAM);
    ID2D1Factory *m_pDirect2dFactory;
    
    
    int APIENTRY wWinMain(_In_ HINSTANCE hInstance,
                         _In_opt_ HINSTANCE hPrevInstance,
                         _In_ LPWSTR    lpCmdLine,
                         _In_ int       nCmdShow)
    {
        UNREFERENCED_PARAMETER(hPrevInstance);
        UNREFERENCED_PARAMETER(lpCmdLine);
    
        // TODO: ここにコードを挿入してください。
    
        // グローバル文字列を初期化しています。
    
        int err = LoadStringW(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
        LoadStringW(hInstance, IDC_MYDWRITE, szWindowClass, MAX_LOADSTRING);
        MyRegisterClass(hInstance);
    
        // アプリケーションの初期化を実行します:
        if (!InitInstance (hInstance, nCmdShow))
        {
            return FALSE;
        }
    
        HACCEL hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_MYDWRITE));
    
        MSG msg;
        HWND hWnd = CreateWindowW(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
            CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, nullptr, nullptr, hInstance, nullptr);
        HRESULT hr = CreateRenderTarget(hWnd, m_pDirect2dFactory, pIRenderTarget);
        if (!SUCCEEDED(hr)) {
            MessageBox(hWnd, L"Hello", L"World", MB_OK);
        }
    
    
        ShowWindow(hWnd, nCmdShow);
    
        // メイン メッセージ ループ:
        while (GetMessage(&msg, nullptr, 0, 0))
        {
            if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
            {
                TranslateMessage(&msg);
                DispatchMessage(&msg);
            }
        }
    
        return (int) msg.wParam;
    }
    
    
    
    //
    //  関数: MyRegisterClass()
    //
    //  目的: ウィンドウ クラスを登録します。
    //
    ATOM MyRegisterClass(HINSTANCE hInstance)
    {
        WNDCLASSEXW wcex;
    
        wcex.cbSize = sizeof(WNDCLASSEX);
    
        wcex.style          = CS_HREDRAW | CS_VREDRAW;
        wcex.lpfnWndProc    = WndProc;
        wcex.cbClsExtra     = 0;
        wcex.cbWndExtra     = 0;
        wcex.hInstance      = hInstance;
        wcex.hIcon          = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_MYDWRITE));
        wcex.hCursor        = LoadCursor(nullptr, IDC_ARROW);
        wcex.hbrBackground  = (HBRUSH)(COLOR_WINDOW+1);
        wcex.lpszMenuName   = MAKEINTRESOURCEW(IDC_MYDWRITE);
        wcex.lpszClassName  = szWindowClass;
        wcex.hIconSm        = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));
    
        return RegisterClassExW(&wcex);
    }
    
    //
    //   関数: InitInstance(HINSTANCE, int)
    //
    //   目的: インスタンス ハンドルを保存して、メイン ウィンドウを作成します。
    //
    //   コメント:
    //
    //        この関数で、グローバル変数でインスタンス ハンドルを保存し、
    //        メイン プログラム ウィンドウを作成および表示します。
    //
    BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
    {
       hInst = hInstance; // グローバル変数にインスタンス処理を格納します。
    
    
       return TRUE;
    }
    
    //
    //  関数: WndProc(HWND, UINT, WPARAM, LPARAM)
    //
    //  目的:    メイン ウィンドウのメッセージを処理します。
    //
    //  WM_COMMAND  - アプリケーション メニューの処理
    //  WM_PAINT    - メイン ウィンドウの描画
    //  WM_DESTROY  - 中止メッセージを表示して戻る
    //
    //
    LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
    {
        switch (message)
        {
        case WM_COMMAND:
            {
                int wmId = LOWORD(wParam);
                // 選択されたメニューの解析:
                switch (wmId)
                {
                case IDM_ABOUT:
                    DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
                    break;
                case IDM_EXIT:
                    DestroyWindow(hWnd);
                    break;
                default:
                    return DefWindowProc(hWnd, message, wParam, lParam);
                }
            }
            break;
        case WM_PAINT:
            {
                Draw(pIRenderTarget);
            }
            break;
        case WM_DESTROY:
            PostQuitMessage(0);
            break;
        default:
            return DefWindowProc(hWnd, message, wParam, lParam);
        }
        return 0;
    }
    
    // バージョン情報ボックスのメッセージ ハンドラーです。
    INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
    {
        UNREFERENCED_PARAMETER(lParam);
        switch (message)
        {
        case WM_INITDIALOG:
            return (INT_PTR)TRUE;
    
        case WM_COMMAND:
            if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
            {
                EndDialog(hDlg, LOWORD(wParam));
                return (INT_PTR)TRUE;
            }
            break;
        }
        return (INT_PTR)FALSE;
    }
    
[/code]

* * *

## 追記2

MyDWRITE.h:

[code]

    #pragma once
    
    #include "resource.h"
    #include <d2d1.h>
    #include <dwrite.h>
    #pragma comment(lib, "d2d1.lib")
    #pragma comment(lib, "Dwrite.lib")
    
    
    
    HRESULT CreateRenderTarget(HWND hWnd, ID2D1Factory *pDirect2dFactory, ID2D1HwndRenderTarget *&pIRenderTarget) {
        HRESULT hr = S_OK;
        if (SUCCEEDED(hr)) {
            hr = D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED,
                &pDirect2dFactory);
        }
        if (SUCCEEDED(hr)) {
            hr = pDirect2dFactory->CreateHwndRenderTarget(D2D1::RenderTargetProperties(),
                D2D1::HwndRenderTargetProperties(hWnd),
                &pIRenderTarget);
        }
        return hr;
    }
    
    HRESULT Draw(ID2D1HwndRenderTarget *pIRenderTarget) {
        // &m_pDirect2dFactory
        // &pIRenderTarget
        ID2D1SolidColorBrush *pIRedBrush = NULL;
        IDWriteTextFormat *pITextFormat = NULL;
        IDWriteFactory *pIDWriteFactory = NULL;
    
        HRESULT hr = S_OK;
        if (SUCCEEDED(hr)) {
            hr = DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED,
                __uuidof(IDWriteFactory),
                reinterpret_cast<IUnknown**>(&pIDWriteFactory));
        }
        else {
            MessageBox(pIRenderTarget->GetHwnd(), L"Hello", L"Cat", MB_OK);
            return hr;
        }
    
        if (SUCCEEDED(hr)) {
            hr = pIDWriteFactory->CreateTextFormat(
                L"源ノ角ゴシック Code JP",
                NULL,
                DWRITE_FONT_WEIGHT_NORMAL,
                DWRITE_FONT_STYLE_NORMAL,
                DWRITE_FONT_STRETCH_NORMAL,
                10.0f * 96.0f / 72.0f,
                L"ja-jp",
                &pITextFormat);
        }
        else {
            MessageBox(pIRenderTarget->GetHwnd(), L"Hello", L"Cat", MB_OK);
            OutputDebugString(L"IDWriteFactory->CreateTextFormat");
            return hr;
        }
    
        if (SUCCEEDED(hr)) {
            hr = pIRenderTarget->CreateSolidColorBrush(D2D1::ColorF(D2D1::ColorF::Red),
                &pIRedBrush);
        }
        else {
            MessageBox(pIRenderTarget->GetHwnd(), L"Hello", L"Cat", MB_OK);
            return hr;
        }
    
        if (SUCCEEDED(hr)) {
            D2D1_RECT_F layoutRect = D2D1::RectF(0.f, 0.f, 100.f, 100.f);
            pIRenderTarget->BeginDraw();
            pIRenderTarget->DrawTextW(
                L"Hello, World",
                wcslen(L"Hello, World"),
                pITextFormat,
                layoutRect,
                pIRedBrush
            );
            MessageBox(pIRenderTarget->GetHwnd(), L"Hello", L"Cat", MB_OK);
            pIRenderTarget->EndDraw();
        }
        else {
            OutputDebugString(L"End of error");
            MessageBox(pIRenderTarget->GetHwnd(), L"Hello", L"Cat", MB_OK);
            return hr;
        }
        return hr;
    }
    
[/code]

* * *

MyDWRITE.cpp:

[code]

    #include "stdafx.h"
    #include "MyDWRITE.h"
    
    
    
    #define MAX_LOADSTRING 100
    template <class T> inline void SafeRelease(T **ppT)
    {
        if (*ppT)
        {
            (*ppT)->Release();
            *ppT = NULL;
        }
    }
    // グローバル変数:
    HINSTANCE hInst;                                // 現在のインターフェイス
    WCHAR szTitle[MAX_LOADSTRING];                  // タイトル バーのテキスト
    WCHAR szWindowClass[MAX_LOADSTRING];            // メイン ウィンドウ クラス名
    
    ID2D1HwndRenderTarget *pIRenderTarget;
    ID2D1Factory *m_pDirect2dFactory;
    ID2D1SolidColorBrush *pIRedBrush = NULL;
    IDWriteTextFormat *pITextFormat = NULL;
    IDWriteFactory *pIDWriteFactory = NULL;
    
    // このコード モジュールに含まれる関数の宣言を転送します:
    ATOM                MyRegisterClass(HINSTANCE hInstance);
    BOOL                InitInstance(HINSTANCE, int);
    LRESULT CALLBACK    WndProc(HWND, UINT, WPARAM, LPARAM);
    INT_PTR CALLBACK    About(HWND, UINT, WPARAM, LPARAM);
    
    int APIENTRY wWinMain(_In_ HINSTANCE hInstance,
                         _In_opt_ HINSTANCE hPrevInstance,
                         _In_ LPWSTR    lpCmdLine,
                         _In_ int       nCmdShow)
    {
        UNREFERENCED_PARAMETER(hPrevInstance);
        UNREFERENCED_PARAMETER(lpCmdLine);
    
        // TODO: ここにコードを挿入してください。
    
        // グローバル文字列を初期化しています。
        LoadStringW(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
        LoadStringW(hInstance, IDC_MYDWRITE, szWindowClass, MAX_LOADSTRING);
        MyRegisterClass(hInstance);
    
        // アプリケーションの初期化を実行します:
        if (!InitInstance (hInstance, nCmdShow))
        {
            return FALSE;
        }
    
        HACCEL hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_MYDWRITE));
    
        MSG msg;
    
        // メイン メッセージ ループ:
        while (GetMessage(&msg, nullptr, 0, 0))
        {
            if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
            {
                TranslateMessage(&msg);
                DispatchMessage(&msg);
            }
        }
    
        return (int) msg.wParam;
    }
    
    
    
    //
    //  関数: MyRegisterClass()
    //
    //  目的: ウィンドウ クラスを登録します。
    //
    ATOM MyRegisterClass(HINSTANCE hInstance)
    {
        WNDCLASSEXW wcex;
    
        wcex.cbSize = sizeof(WNDCLASSEX);
    
        wcex.style          = CS_HREDRAW | CS_VREDRAW;
        wcex.lpfnWndProc    = WndProc;
        wcex.cbClsExtra     = 0;
        wcex.cbWndExtra     = 0;
        wcex.hInstance      = hInstance;
        wcex.hIcon          = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_MYDWRITE));
        wcex.hCursor        = LoadCursor(nullptr, IDC_ARROW);
        wcex.hbrBackground  = (HBRUSH)(COLOR_WINDOW+1);
        wcex.lpszMenuName   = MAKEINTRESOURCEW(IDC_MYDWRITE);
        wcex.lpszClassName  = szWindowClass;
        wcex.hIconSm        = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));
    
        return RegisterClassExW(&wcex);
    }
    
    //
    //   関数: InitInstance(HINSTANCE, int)
    //
    //   目的: インスタンス ハンドルを保存して、メイン ウィンドウを作成します。
    //
    //   コメント:
    //
    //        この関数で、グローバル変数でインスタンス ハンドルを保存し、
    //        メイン プログラム ウィンドウを作成および表示します。
    //
    BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
    {
       hInst = hInstance; // グローバル変数にインスタンス処理を格納します。
    
       HWND hWnd = CreateWindowW(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
          CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, nullptr, nullptr, hInstance, nullptr);
    
       if (!hWnd)
       {
          return FALSE;
       }
    
       ShowWindow(hWnd, nCmdShow);
       UpdateWindow(hWnd);
    
       return TRUE;
    }
    
    //
    //  関数: WndProc(HWND, UINT, WPARAM, LPARAM)
    //
    //  目的:    メイン ウィンドウのメッセージを処理します。
    //
    //  WM_COMMAND  - アプリケーション メニューの処理
    //  WM_PAINT    - メイン ウィンドウの描画
    //  WM_DESTROY  - 中止メッセージを表示して戻る
    //
    //
    LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
    {
        switch (message)
        {
        case WM_COMMAND:
            {
                int wmId = LOWORD(wParam);
                // 選択されたメニューの解析:
                switch (wmId)
                {
                case IDM_ABOUT:
                    DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
                    break;
                case IDM_EXIT:
                    DestroyWindow(hWnd);
                    break;
                default:
                    return DefWindowProc(hWnd, message, wParam, lParam);
                }
            }
            break;
        case WM_PAINT:
            {
                PAINTSTRUCT ps;
                HDC hdc = BeginPaint(hWnd, &ps);
                // TODO: HDC を使用する描画コードをここに追加してください...
                HRESULT hr = S_OK;
    
                if (SUCCEEDED(hr)) {
                    D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED,
                        &m_pDirect2dFactory);
    
                }
    
                if (SUCCEEDED(hr)) {
                    m_pDirect2dFactory->CreateHwndRenderTarget(D2D1::RenderTargetProperties(),
                        D2D1::HwndRenderTargetProperties(hWnd),
                        &pIRenderTarget);
                }
    
                if (SUCCEEDED(hr)) {
                    hr = DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED,
                        __uuidof(IDWriteFactory),
                        reinterpret_cast<IUnknown**>(&pIDWriteFactory));
                }
    
    
    
                if (SUCCEEDED(hr)) {
                    hr = pIDWriteFactory->CreateTextFormat(
                        L"源ノ角ゴシック Code JP",
                        NULL,
                        DWRITE_FONT_WEIGHT_NORMAL,
                        DWRITE_FONT_STYLE_NORMAL,
                        DWRITE_FONT_STRETCH_NORMAL,
                        10.0f * 96.0f / 72.0f,
                        L"ja-JP",
                        &pITextFormat);
                }
    
                if (SUCCEEDED(hr)) {
                    hr = pIRenderTarget->CreateSolidColorBrush(D2D1::ColorF(D2D1::ColorF::Red),
                        &pIRedBrush);
                }
                D2D1_RECT_F layoutRect = D2D1::RectF(0.f, 0.f, 100.f, 100.f);
                if (SUCCEEDED(hr)) {
                    pIRenderTarget->BeginDraw();
                    pIRenderTarget->DrawTextW(
                        L"Hello, World",
                        wcslen(L"Hello, World"),
                        pITextFormat,
                        layoutRect,
                        pIRedBrush
                    );
                    pIRenderTarget->EndDraw();
                }
    
            }
            break;
        case WM_DESTROY:
            SafeRelease(&pIRedBrush);
            SafeRelease(&pITextFormat);
            SafeRelease(&pIDWriteFactory);
            PostQuitMessage(0);
            break;
        default:
            return DefWindowProc(hWnd, message, wParam, lParam);
        }
        return 0;
    }
    
    // バージョン情報ボックスのメッセージ ハンドラーです。
    INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
    {
        UNREFERENCED_PARAMETER(lParam);
        switch (message)
        {
        case WM_INITDIALOG:
            return (INT_PTR)TRUE;
    
        case WM_COMMAND:
            if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
            {
                EndDialog(hDlg, LOWORD(wParam));
                return (INT_PTR)TRUE;
            }
            break;
        }
        return (INT_PTR)FALSE;
    }
    
[/code]


CC BY-SA 4.0
2018-08-06T13:00:41.600
47285
2018-08-10T09:49:36.727
2018-08-10T09:09:25.993
5246
5246
question
c++ windows visual-studio
DirectWriteでHello, Worldを表示するプログラムを実行しても何も表示されない


> 特にエラーも出ておらず

と書かれていますが、実際のコードは「特にエラーチェックをしておらず」です。例えば`wWinMain`の処理では

>
[code]

>     LoadStringW(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
>     LoadStringW(hInstance, IDC_MYDWRITE, szWindowClass, MAX_LOADSTRING);
>     MyRegisterClass(hInstance);
>  
[/code]

と各関数は実行結果を返しているにもかかわらず、それを捨てています。各戻り値を確認し、正常でなければエラー値を確認することから始めてください。


CC BY-SA 4.0
2018-08-06T13:18:06.513
47287
2018-08-06T13:18:06.513
4236
47285
answer


WM_PAINT受領時、

[code]

    BeginPaint();
    EndPaint();
    
[/code]

で、SDK側の再描画要求を完了させる必要があります。  
これにより、無用な再描画要求の頻繁な発生を抑えることができます。  
まず、これをやってみてはどうでしょう。チラチラしなくなるかと思います。

上記コードの直下で、レンダ(本件はHWND型のレンダ)による描画 Draw(・・・)を行ってみてはどうでしょう。


CC BY-SA 4.0
2018-08-10T09:49:36.727
47415
2018-08-10T09:49:36.727
3793
47285
answer