スポンサーリンク

WinMainを使わずにウィンドウを開く

雑談

さて、薄々気づいている人もいるかと思うが、著者は今ライザのアトリエをやっていてブログを書く暇がガチでない。というわけで、もう暫くできるだけ楽に更新できる内容で繋いでいきたい。

GetModuleHandle(0)でインスタンスハンドルを取得

Windowsプログラミングはエントリポイントが原則としてWinMainになる。

とはいえmainからは動かないかというとそんなことはない。

ウィンドウを開くために必要なhInstanceはGetModuleHandle関数に0を渡すことで取得できる。

#include <Windows.h>
#include <cstdio>

LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp);

int main()
{
  //インスタンスハンドルの取得
  HINSTANCE hInstance = GetModuleHandle(0);

  HWND hwnd;
  WNDCLASS winc;

  winc.style = CS_HREDRAW | CS_VREDRAW;
  winc.lpfnWndProc = WndProc;
  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("WITHOUT_WINMAIN");

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


  hwnd = CreateWindow(
    TEXT("WITHOUT_WINMAIN"), TEXT("window without WinMain"),
    WS_OVERLAPPEDWINDOW | WS_VISIBLE,
    100, 100, 100, 100, NULL, NULL,
    hInstance, NULL
  );

  if (hwnd == NULL) return 0;

  printf("success\n"); // これを入れるとコンソールに表示される
  FreeConsole(); // これを入れるとコンソール自体が消える


  MSG msg;
  while (GetMessage(&msg, NULL, 0, 0)) {
    DispatchMessage(&msg);
  }
  return msg.wParam;


}
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp) {
  switch (msg) {
  case WM_LBUTTONDOWN:
    MessageBox(hwnd, L"hello", 0, 0);
    break;
  case WM_DESTROY:
    PostQuitMessage(0);
    return 0;
  }
  return DefWindowProc(hwnd, msg, wp, lp);
}

DLL化

これだけだとあまりにも記事として寂しいので、ウィンドウ生成をDLL内に入れることを考える。

これを発展させればクロスプラットフォームなGUIライブラリを作れる(多分)

DLL側

dllport.h

#pragma once

#ifdef  DLL_EXPORT_DO
/*  DLLを作る場合   */
#define  __DLL_PORT  extern "C" __declspec(dllexport)   
#else
/*  DLLを使う場合   */
#define  __DLL_PORT  extern "C" __declspec(dllimport)   
#endif

winshow.h

#pragma once

#include<Windows.h>

#include "../dllport.h"

LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp);

BOOL APIENTRY DllMain(HMODULE hModule,DWORD  ul_reason_for_call,LPVOID lpReserved);

__DLL_PORT int open_window();

winshow.cpp

#include "winshow.h"

BOOL APIENTRY DllMain(HMODULE hModule,
  DWORD  ul_reason_for_call,
  LPVOID lpReserved
)
{
  return TRUE;
}
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp) {
  switch (msg) {
  case WM_LBUTTONDOWN:
    MessageBox(hwnd, L"hello in dll", 0, 0);
    break;
  case WM_DESTROY:
    PostQuitMessage(0);
    return 0;
  }
  return DefWindowProc(hwnd, msg, wp, lp);
}

int open_window() {
  //インスタンスハンドルの取得
  HINSTANCE hInstance = GetModuleHandle(0);

  HWND hwnd;
  WNDCLASS winc;

  winc.style = CS_HREDRAW | CS_VREDRAW;
  winc.lpfnWndProc = WndProc;
  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("WITHOUT_WINMAIN");

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


  hwnd = CreateWindow(
    TEXT("WITHOUT_WINMAIN"), TEXT("window without WinMain"),
    WS_OVERLAPPEDWINDOW | WS_VISIBLE,
    100, 100, 100, 100, NULL, NULL,
    hInstance, NULL
  );

  if (hwnd == NULL) return 0;

  MSG msg;
  while (GetMessage(&msg, NULL, 0, 0)) {
    DispatchMessage(&msg);
  }
  return msg.wParam;

}

exe側

#include <Windows.h>
#include <cstdio>

#include "../winshow/winshow.h"

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

int main()
{
  return open_window();
}

コメントを残す

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

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


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