スポンサーリンク

コンソールアプリケーションでデバッグ用のウィンドウを表示-1

プログラムはコンソールで良いが画像での確認もしたい時にウィンドウが欲しくなるので、コンソールアプリから開けるウィンドウを作成する。

gwindbg.hpp

#pragma once

#include <Windows.h>
#include <thread>

class GraphicDebugWindow {
  //! @brief WNDCLASSに設定するウィンドウプロシージャ
  static LRESULT CALLBACK StaticWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
  {
    //CreateWindowの最後の引数で渡したthisポインタを取得
    GraphicDebugWindow* This = (GraphicDebugWindow*)GetWindowLongPtr(hWnd, GWLP_USERDATA);
    if (!This) {//取得できなかった(ウィンドウ生成中)場合
      if (message == WM_CREATE) {
        This = (GraphicDebugWindow*)((LPCREATESTRUCT)lParam)->lpCreateParams;
        if (This) {
          SetWindowLongPtr(hWnd, GWLP_USERDATA, (LONG_PTR)This);
          return This->WndProc(hWnd, message, wParam, lParam);
        }
      }
    }
    else {//取得できた場合(ウィンドウ生成後)
      return This->WndProc(hWnd, message, wParam, lParam);
    }
    return DefWindowProc(hWnd, message, wParam, lParam);
  }

  //メインループのスレッド
  std::unique_ptr<std::thread> m_mainloop;

  HINSTANCE hInstance;
  HWND m_hwnd;
public:

  GraphicDebugWindow() {}

  bool registerWindowClass() {
    //インスタンスハンドルの取得
    hInstance = GetModuleHandle(0);

    WNDCLASS winc;

    winc.style = CS_HREDRAW | CS_VREDRAW;
    winc.lpfnWndProc = StaticWndProc;
    winc.cbClsExtra = winc.cbWndExtra = 0;
    winc.hInstance = hInstance;
    winc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
    winc.hCursor = LoadCursor(NULL, IDC_ARROW);
    winc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
    winc.lpszMenuName = NULL;
    winc.lpszClassName = TEXT("SZL_TEST_GUI_WINDOW");

    if (!RegisterClass(&winc))
      return false;

    return true;
  }
  //! @brief スレッドの内容
  int MainLoop(const TCHAR* title,int posx,int posy,int width,int height) {

    //メッセージループはウィンドウを生成したスレッドに属していなければいけないので
    //CreateWindowの時点でスレッドに入っていなければならないのでここに書く
    m_hwnd = CreateWindow(
      TEXT("SZL_TEST_GUI_WINDOW"), title,
      WS_OVERLAPPEDWINDOW | WS_VISIBLE,
      posx, posy, width, height, NULL, NULL,
      hInstance, this
    );

    if (m_hwnd == NULL)
      return 0;

    MSG msg;
    while (GetMessage(&msg, NULL, 0, 0)) {
      TranslateMessage(&msg);
      DispatchMessage(&msg);
    }

    //スレッドから抜けるときはウィンドウハンドルをnullptrにする
    m_hwnd = nullptr;

    return msg.wParam;

  }

  //! @brief ウィンドウ作成
  bool open(const TCHAR* title, int posx, int posy, int width, int height) {

    if (registerWindowClass() == false)
      return false;

    m_mainloop.reset(//! @brief スレッド作成
      new std::thread(
        &GraphicDebugWindow::MainLoop,
        this, 
        title, 
        posx, 
        posy, 
        width, 
        height
      ));

    return true;
  }

  //! @brief ウィンドウを閉じたいときに呼び出す
  void close() {
    if (m_hwnd ) {
      SendMessage(m_hwnd, WM_DESTROY, 0, 0);
    }
    if (m_mainloop) {
      if (m_mainloop->joinable()) {
        m_mainloop->join();
      }
      m_mainloop.reset();
    }
  }

  void join() {
    if (m_mainloop) {
      if (m_mainloop->joinable()) {
        m_mainloop->join();
      }
      m_mainloop.reset();
    }
  } 
  //! @brief 外にウィンドウハンドルを公開
  HWND get_hwnd() {return m_hwnd;}

  virtual ~GraphicDebugWindow() {
    close();
  }

  //! @brief メンバ関数版ウィンドウプロシージャ
  virtual LRESULT WndProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp)
  {
    PAINTSTRUCT ps;
    HDC hdc;
    switch (msg)
    {
    case WM_DESTROY:
      PostQuitMessage(0);
      return 0;
    }
    return DefWindowProc(hWnd, msg, wp, lp);
  }
};

使用例

コンソールにアルファベットを入力すると、ウィンドウに表示される。

‘c’または’z’で抜ける。

#include <iostream>

#include "gwindbg.hpp"

#pragma warning(disable:4996)

int main()
{
  GraphicDebugWindow gw;
  gw.open(TEXT("入力したキー表示(zで終了)"), 100, 100, 300, 300);

  char a = 'a';
  while (a != 'z') {
    std::cin >> a;

    char text[10];
    sprintf(text, "%c", a);

    //ウィンドウが消されていたらループを抜ける
    if (gw.get_hwnd() == nullptr)
      break;

    // ウィンドウを消す
    if (a == 'c')
      gw.close();

    //ウィンドウの方に入力した文字を表示
    HDC dc = GetDC(gw.get_hwnd());
    TextOutA(dc, 0, 0, "  ", 2);
    TextOutA(dc, 0, 0, text, 1);
    ReleaseDC(gw.get_hwnd(), dc);

  }
  gw.close();
  std::cin >> a;
}

コメントを残す

メールアドレスが公開されることはありません。

日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)


この記事のトラックバックURL: