Загрузка...

ImGui DirectX11 Desktop Example

Тема в разделе C/C++ создана пользователем shadurn 6 июл 2019. 1143 просмотра

  1. shadurn
    shadurn Автор темы 6 июл 2019 1069 7 май 2017
    ImGui - GUI-фреймворк, написанный на C++ с минимальными зависимостями. Ссылка на github - https://github.com/ocornut/imgui

    [IMG]

    Это самый обычный пример использования ImGui для desktop-приложения с передвижением окна, можно применять для любых целей.
    Для тех, кто сам не может сделать.

    Код

    #include "Frameworks/ImGui/imgui.h"
    #include "Frameworks/ImGui/imgui_impl_win32.h"
    #include "Frameworks/ImGui/imgui_impl_dx11.h"
    #include <d3d11.h>
    #define DIRECTINPUT_VERSION 0x0800
    #include <dinput.h>
    #include <tchar.h>
    #include <string>

    #pragma comment(lib, "d3d11.lib")

    POINTS m_Pos;

    float WindowWidth = 800.0;
    float WindowHeight = 600.0;

    bool IsOpened = true;

    static ID3D11Device* g_pd3dDevice = NULL;
    static ID3D11DeviceContext* g_pd3dDeviceContext = NULL;
    static IDXGISwapChain* g_pSwapChain = NULL;
    static ID3D11RenderTargetView* g_mainRenderTargetView = NULL;

    bool CreateDeviceD3D(HWND hWnd);
    void CleanupDeviceD3D();
    void CreateRenderTarget();
    void CleanupRenderTarget();
    LRESULT WINAPI WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);

    int WINAPI WinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPSTR lpCmdLine, _In_ int nShowCmd)
    {
    WNDCLASSEX wc = { sizeof(WNDCLASSEX), CS_CLASSDC, WndProc, 0L, 0L, GetModuleHandle(NULL), NULL, LoadCursor(NULL, IDC_ARROW), NULL, NULL, _T("ImGui Example"), NULL };
    ::RegisterClassEx(&wc);
    HWND hwnd = ::CreateWindow(wc.lpszClassName, _T("Dear ImGui DirectX11 Example"), WS_POPUP, 0, 0, (int)WindowWidth, (int)WindowHeight, NULL, NULL, wc.hInstance, NULL);

    if (!CreateDeviceD3D(hwnd)) {
    CleanupDeviceD3D();
    ::UnregisterClass(wc.lpszClassName, wc.hInstance);
    return 1;
    }

    ::ShowWindow(hwnd, SW_SHOWDEFAULT);
    ::UpdateWindow(hwnd);

    IMGUI_CHECKVERSION();
    ImGui::CreateContext();
    ImGuiIO& io = ImGui::GetIO(); (void)io;

    ImGui::StyleColorsDark();

    ImGui_ImplWin32_Init(hwnd);
    ImGui_ImplDX11_Init(g_pd3dDevice, g_pd3dDeviceContext);

    // Load Fonts
    // - If no fonts are loaded, dear imgui will use the default font. You can also load multiple fonts and use ImGui::PushFont()/PopFont() to select them.
    // - AddFontFromFileTTF() will return the ImFont* so you can store it if you need to select the font among multiple.
    // - If the file cannot be loaded, the function will return NULL. Please handle those errors in your application (e.g. use an assertion, or display an error and quit).
    // - The fonts will be rasterized at a given size (w/ oversampling) and stored into a texture when calling ImFontAtlas::Build()/GetTexDataAsXXXX(), which ImGui_ImplXXXX_NewFrame below will call.
    // - Read 'misc/fonts/README.txt' for more instructions and details.
    // - Remember that in C/C++ if you want to include a backslash \ in a string literal you need to write a double backslash \\ !
    //io.Fonts->AddFontDefault();
    //io.Fonts->AddFontFromFileTTF("../../misc/fonts/Roboto-Medium.ttf", 16.0f);
    //io.Fonts->AddFontFromFileTTF("../../misc/fonts/Cousine-Regular.ttf", 15.0f);
    //io.Fonts->AddFontFromFileTTF("../../misc/fonts/DroidSans.ttf", 16.0f);
    //io.Fonts->AddFontFromFileTTF("../../misc/fonts/ProggyTiny.ttf", 10.0f);
    //ImFont* font = io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf", 18.0f, NULL, io.Fonts->GetGlyphRangesJapanese());
    //IM_ASSERT(font != NULL);

    MSG msg;
    ZeroMemory(&msg, sizeof(msg));
    while (msg.message != WM_QUIT)
    {
    if (::PeekMessage(&msg, NULL, 0U, 0U, PM_REMOVE))
    {
    ::TranslateMessage(&msg);
    ::DispatchMessage(&msg);
    continue;
    }

    ImGui_ImplDX11_NewFrame();
    ImGui_ImplWin32_NewFrame();
    ImGui::NewFrame();

    ImGui::SetNextWindowPos(ImVec2(0, 0));
    ImGui::Begin("ImGui Example", &IsOpened, ImVec2(WindowWidth, WindowHeight), 1.0f, ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoCollapse);
    {
    static float f = 0.0f;
    static int counter = 0;

    if (IsOpened == false)
    exit(0);

    ImGui::Text("This is some useful text.");

    if (ImGui::Button("Button"))
    counter++;
    ImGui::SameLine();
    ImGui::Text("counter = %d", counter);

    static char str1[128] = "";
    ImGui::InputTextWithHint("input text (w/ hint)", "enter text here", str1, IM_ARRAYSIZE(str1));

    ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate);
    }
    ImGui::End();

    ImGui::Render();
    g_pd3dDeviceContext->OMSetRenderTargets(1, &g_mainRenderTargetView, NULL);
    //g_pd3dDeviceContext->ClearRenderTargetView(g_mainRenderTargetView, (float*)& ImVec4(0.00f, 0.00f, 0.00f, 0.00f));
    ImGui_ImplDX11_RenderDrawData(ImGui::GetDrawData());

    g_pSwapChain->Present(1, 0);
    }

    ImGui_ImplDX11_Shutdown();
    ImGui_ImplWin32_Shutdown();
    ImGui::DestroyContext();

    CleanupDeviceD3D();
    ::DestroyWindow(hwnd);
    ::UnregisterClass(wc.lpszClassName, wc.hInstance);

    return 0;
    }

    bool CreateDeviceD3D(HWND hWnd)
    {
    DXGI_SWAP_CHAIN_DESC sd;
    ZeroMemory(&sd, sizeof(sd));
    sd.BufferCount = 2;
    sd.BufferDesc.Width = 0;
    sd.BufferDesc.Height = 0;
    sd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
    sd.BufferDesc.RefreshRate.Numerator = 60;
    sd.BufferDesc.RefreshRate.Denominator = 1;
    sd.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH;
    sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
    sd.OutputWindow = hWnd;
    sd.SampleDesc.Count = 1;
    sd.SampleDesc.Quality = 0;
    sd.Windowed = TRUE;
    sd.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;

    UINT createDeviceFlags = 0;
    D3D_FEATURE_LEVEL featureLevel;
    const D3D_FEATURE_LEVEL featureLevelArray[2] = { D3D_FEATURE_LEVEL_11_0, D3D_FEATURE_LEVEL_10_0, };
    if (D3D11CreateDeviceAndSwapChain(NULL, D3D_DRIVER_TYPE_HARDWARE, NULL, createDeviceFlags, featureLevelArray, 2, D3D11_SDK_VERSION, &sd, &g_pSwapChain, &g_pd3dDevice, &featureLevel, &g_pd3dDeviceContext) != S_OK)
    return false;

    CreateRenderTarget();
    return true;
    }

    void CleanupDeviceD3D()
    {
    CleanupRenderTarget();
    if (g_pSwapChain) { g_pSwapChain->Release(); g_pSwapChain = NULL; }
    if (g_pd3dDeviceContext) { g_pd3dDeviceContext->Release(); g_pd3dDeviceContext = NULL; }
    if (g_pd3dDevice) { g_pd3dDevice->Release(); g_pd3dDevice = NULL; }
    }

    void CreateRenderTarget()
    {
    ID3D11Texture2D* pBackBuffer;
    g_pSwapChain->GetBuffer(0, IID_PPV_ARGS(&pBackBuffer));
    g_pd3dDevice->CreateRenderTargetView(pBackBuffer, NULL, &g_mainRenderTargetView);
    pBackBuffer->Release();
    }

    void CleanupRenderTarget()
    {
    if (g_mainRenderTargetView) { g_mainRenderTargetView->Release(); g_mainRenderTargetView = NULL; }
    }

    extern LRESULT ImGui_ImplWin32_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
    LRESULT WINAPI WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
    {
    if (ImGui_ImplWin32_WndProcHandler(hWnd, msg, wParam, lParam))
    return true;

    ImGuiIO& io = ImGui::GetIO();
    switch (msg)
    {
    case WM_LBUTTONDOWN: case WM_LBUTTONDBLCLK:
    case WM_RBUTTONDOWN: case WM_RBUTTONDBLCLK:
    case WM_MBUTTONDOWN: case WM_MBUTTONDBLCLK:
    {
    if (msg == WM_LBUTTONDOWN) m_Pos = MAKEPOINTS(lParam);
    int button = 0;
    if (msg == WM_LBUTTONDOWN || msg == WM_LBUTTONDBLCLK) button = 0;
    if (msg == WM_RBUTTONDOWN || msg == WM_RBUTTONDBLCLK) button = 1;
    if (msg == WM_MBUTTONDOWN || msg == WM_MBUTTONDBLCLK) button = 2;
    if (!ImGui::IsAnyMouseDown() && ::GetCapture() == NULL)
    ::SetCapture(hWnd);
    io.MouseDown[button] = true;
    return 0;
    }
    case WM_LBUTTONUP:
    case WM_RBUTTONUP:
    case WM_MBUTTONUP:
    {
    int button = 0;
    if (msg == WM_LBUTTONUP) button = 0;
    if (msg == WM_RBUTTONUP) button = 1;
    if (msg == WM_MBUTTONUP) button = 2;
    io.MouseDown[button] = false;
    if (!ImGui::IsAnyMouseDown() && ::GetCapture() == hWnd)
    ::ReleaseCapture();
    return 0;
    }
    case WM_MOUSEWHEEL:
    io.MouseWheel += GET_WHEEL_DELTA_WPARAM(wParam) > 0 ? +1.0f : -1.0f;
    return 0;
    case WM_MOUSEHWHEEL:
    io.MouseWheelH += GET_WHEEL_DELTA_WPARAM(wParam) > 0 ? +1.0f : -1.0f;
    return 0;

    case WM_KEYDOWN:
    case WM_SYSKEYDOWN:
    if (wParam < 256)
    io.KeysDown[wParam] = 1;
    return 0;
    case WM_KEYUP:
    case WM_SYSKEYUP:
    if (wParam < 256)
    io.KeysDown[wParam] = 0;
    return 0;
    //case WM_CHAR:
    // wchar_t wch;
    // MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, (char*)& wParam, 1, &wch, 1);
    // io.AddInputCharacter(wch);
    // return 0;
    case WM_SETCURSOR:
    if (LOWORD(lParam) == HTCLIENT)
    {
    if (io.ConfigFlags & ImGuiConfigFlags_NoMouseCursorChange)
    return false;

    ImGuiMouseCursor imgui_cursor = ImGui::GetMouseCursor();
    if (imgui_cursor == ImGuiMouseCursor_None || io.MouseDrawCursor)
    {
    ::SetCursor(NULL);
    }
    else
    {
    LPTSTR win32_cursor = IDC_ARROW;
    switch (imgui_cursor)
    {
    case ImGuiMouseCursor_Arrow: win32_cursor = IDC_ARROW; break;
    case ImGuiMouseCursor_TextInput: win32_cursor = IDC_IBEAM; break;
    case ImGuiMouseCursor_ResizeAll: win32_cursor = IDC_SIZEALL; break;
    case ImGuiMouseCursor_ResizeEW: win32_cursor = IDC_SIZEWE; break;
    case ImGuiMouseCursor_ResizeNS: win32_cursor = IDC_SIZENS; break;
    case ImGuiMouseCursor_ResizeNESW: win32_cursor = IDC_SIZENESW; break;
    case ImGuiMouseCursor_ResizeNWSE: win32_cursor = IDC_SIZENWSE; break;
    case ImGuiMouseCursor_Hand: win32_cursor = IDC_HAND; break;
    }
    ::SetCursor(::LoadCursor(NULL, win32_cursor));
    }

    return 1;
    }
    return 0;
    case WM_DESTROY:
    PostQuitMessage(0);
    return 0;
    case WM_MOUSEMOVE:
    {
    float TitleHeight = ImGui::GetFontSize() + ImGui::GetStyle().FramePadding.y * 2.0f;
    io.MousePos.x = (signed short)(lParam);
    io.MousePos.y = (signed short)(lParam >> 16);
    if (wParam == MK_LBUTTON)
    {
    POINTS p = MAKEPOINTS(lParam);
    RECT rect;
    GetWindowRect(hWnd, &rect);
    rect.left += p.x - m_Pos.x;
    rect.top += p.y - m_Pos.y;
    if ((m_Pos.x >= 0 && m_Pos.x <= WindowWidth && m_Pos.y >= 0 && m_Pos.y <= TitleHeight))
    SetWindowPos(hWnd, HWND_TOPMOST, rect.left, rect.top, 0, 0, SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOZORDER);
    }
    return 0;
    }
    }
    return DefWindowProc(hWnd, msg, wParam, lParam);
    }
    Ссылка на готовый проект - https://yadi.sk/d/qBs0aTbudC4-fA (выставить Release x86 при компиляции)

    [IMG]
     
    6 июл 2019 Изменено
Загрузка...
Top