さて、薄々気づいている人もいるかと思うが、著者は今ライザのアトリエをやっていてブログを書く暇がガチでない。というわけで、もう暫くできるだけ楽に更新できる内容で繋いでいきたい。
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内に入れることを考える。
これを発展させればクロスプラットフォームなGUIライブラリを作れる(多分)
#pragma once #ifdef DLL_EXPORT_DO /* DLLを作る場合 */ #define __DLL_PORT extern "C" __declspec(dllexport) #else /* DLLを使う場合 */ #define __DLL_PORT extern "C" __declspec(dllimport) #endif
#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();
#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; }
#include <Windows.h> #include <cstdio> #include "../winshow/winshow.h" #pragma comment(lib,"winshow.lib") int main() { return open_window(); }