機械学習基礎理論独習

誤りがあればご指摘いただけると幸いです。数式が整うまで少し時間かかります。リンクフリーです。

勉強ログです。リンクフリーです
目次へ戻る

【MFC/OpenGL】imgui の設定方法

imguiとは

まず読み方ですが、「イムギューアイ」 と読む人が多いです。
DirectX12 や OpenGL などのグラフィックスライブラリを使って GUI を描画するライブラリです。
GUI の制御をコードのみでできるので使いやすいのが特徴で、特にデバッグ時に重宝するようです。

対象のウィンドウ

CWndを継承したクラスに表示してみます。

インストール

以下のコマンドラインでインストールできます。

vcpkg install imgui[win32-binding,opengl3-binding]

ヘッダ

pch.h にヘッダを追加します。

#include "imgui.h"
#include "imgui_impl_opengl3.h"
#include "imgui_impl_win32.h"

MyWnd.h に ImGui_ImplWin32_WndProcHandler メソッドを定義します。

// Forward declare message handler from imgui_impl_win32.cpp
extern IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);

ソース

MyWnd::OnCreate() で OpenGL 初期化後に以下のように初期化します。

// DPI awareness(必要なら)
ImGui_ImplWin32_EnableDpiAwareness();
float main_scale = ImGui_ImplWin32_GetDpiScaleForMonitor(
  MonitorFromPoint(POINT{ 0,0 }, MONITOR_DEFAULTTOPRIMARY)
);

// ImGui context
IMGUI_CHECKVERSION();
ImGui::CreateContext();
ImGuiIO& io = ImGui::GetIO();
io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard;
io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad;

// Style
ImGui::StyleColorsDark();
ImGuiStyle& style = ImGui::GetStyle();
style.ScaleAllSizes(main_scale);   // ← OK(master でも使える)

// master 版では FontScaleDpi が無いので、代わりにこれを使う
io.FontGlobalScale = main_scale;

// Backend init
ImGui_ImplWin32_InitForOpenGL(m_hWnd);
ImGui_ImplOpenGL3_Init("#version 130"); // GLAD ならこれでOK

SwapBuffer の前に以下のように書きます。

// Our state
bool show_demo_window = true;
bool show_another_window = false;
ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f);

// Start the Dear ImGui frame
ImGui_ImplOpenGL3_NewFrame();
ImGui_ImplWin32_NewFrame();
ImGui::NewFrame();

ImGui::Begin("Test Movable Window");   // ← フラグ完全に無し
ImGui::Text("Move me!");  
ImGui::End();

ImGui::Render();
ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());

imgui がイベントハンドリングできるように WindowProc を以下のように書きます。

LRESULT CGLLayer::WindowProc(UINT message, WPARAM wParam, LPARAM lParam) {
  // TODO: Add your specialized code here and/or call the base class
  if (ImGui_ImplWin32_WndProcHandler(m_hWnd, message, wParam, lParam)) 
    return true;
  return CWnd::WindowProc(message, wParam, lParam);
}

これで以下のように表示されるはずです。


imguiの再描画

imggi はグラフィックスライブラリで描画をするので、
GmeLoopがある場合はそこで、無い場合は Timer や Mousemove で再描画をする必要があります。

imgui のウィンドウを操作している時は、OnLButtonDownを処理しないようにする

そうしないと imgui のウィンドウを触るたびにイベントが発生して予期しない動作をしてしまいます。
私は、OnLButtonDown に以下のように書きました。

void MyWnd::OnLButtonDown(UINT nFlags, CPoint point) {
  // Add your message handler code here and/or call default
  ImGuiIO& io = ImGui::GetIO();
  if (io.WantCaptureMouse) {
    // ImGui がマウスを使っている -> MFC の処理を無効化
    return;
  }
  // 通常の処理
}

動かない場合は

本家のサンプル を参考にするとよいでしょう。
私もこれだけを見て動かしてみました。

目次へ戻る