Skip to content

Instantly share code, notes, and snippets.

@sgraham
Last active October 15, 2020 06:42
Show Gist options
  • Select an option

  • Save sgraham/96ced4b387e09752bc15fbebc1b46791 to your computer and use it in GitHub Desktop.

Select an option

Save sgraham/96ced4b387e09752bc15fbebc1b46791 to your computer and use it in GitHub Desktop.
using System.Diagnostics;
using System;
using System.Collections;
namespace Hackity
{
[CRepr]
struct WNDCLASSEXA
{
public uint32 cbSize;
public uint32 style;
public Windows.WndProc lpfnWndProc;
public int32 cbClsExtra;
public int32 cbWndExtra;
public Windows.HInstance hInstance;
public Windows.Handle hIcon;
public Windows.Handle hCursor;
public Windows.Handle hbrBackground;
public char8* lpszMenuName;
public char8* lpszClassName;
public Windows.Handle hIconSm;
}
[CRepr]
struct RECT
{
public int32 left;
public int32 top;
public int32 right;
public int32 bottom;
}
[CRepr]
struct POINT
{
public int32 x;
public int32 y;
}
[CRepr]
struct MSG
{
public Windows.HWnd hwnd;
public uint32 message;
public uint64 wParam;
public int64 lParam;
public uint32 time;
public POINT pt;
}
[CRepr]
struct PAINTSTRUCT
{
Windows.Handle hdc;
int32 fErase;
RECT rcPaint;
int32 fRestore;
int32 fIncUpdate;
char8[32] rgbReserved;
}
class Window
{
const uint32 CS_VREDRAW = 0x0001;
const uint32 CS_HREDRAW = 0x0002;
const uint32 WS_OVERLAPPED = 0x00000000L;
const uint32 WS_CAPTION = 0x00C00000L;
const uint32 WS_SYSMENU = 0x00080000L;
const uint32 WS_THICKFRAME = 0x00040000L;
const uint32 WS_MINIMIZEBOX = 0x00020000L;
const uint32 WS_MAXIMIZEBOX = 0x00010000L;
const uint32 WS_OVERLAPPEDWINDOW = WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX;
const int32 CW_USEDEFAULT = (int32)0x80000000;
const int32 SW_SHOWDEFAULT = 10;
const int32 WM_DESTROY = 0x0002;
const int32 WM_PAINT = 0x000F;
const int32 WM_CLOSE = 0x0010;
const int32 WM_QUIT = 0x0012;
const int32 PM_REMOVE = 0x0001;
char8* IDC_ARROW = (char8*)(void*)(int)32512;
const int32 COLOR_WINDOW = 5;
[Import("user32.lib"), CLink, CallingConvention(.Stdcall)]
public static extern uint16 RegisterClassExA(WNDCLASSEXA* wndclass);
[Import("user32.lib"), CLink, CallingConvention(.Stdcall)]
public static extern int32 AdjustWindowRect(RECT* lpRect, uint32 dwStyle, int32 bMenu);
[Import("user32.lib"), CLink, CallingConvention(.Stdcall)]
public static extern Windows.HWnd CreateWindowExA(uint32 dwExStyle, char8* lpClassName, char8* lpWindowName, uint32 dwStyle,
int32 x, int32 y, int32 nWidth, int32 nHeight,
Windows.HWnd hWndParent, Windows.Handle hMenu, Windows.HInstance hInstance, void* lpParam);
[Import("user32.lib"), CLink, CallingConvention(.Stdcall)]
public static extern int DefWindowProcA(Windows.HWnd hWnd, int32 Msg, int wParam, int lParam);
[Import("user32.lib"), CLink, CallingConvention(.Stdcall)]
public static extern int32 ShowWindow(Windows.HWnd hWnd, int32 nCmdShow);
[Import("user32.lib"), CLink, CallingConvention(.Stdcall)]
public static extern int32 PeekMessageA(MSG* msg, Windows.HWnd hWnd, uint32 wMsgFilterMin, uint32 wMsgFilterMax, uint32 wRemoveMsg);
[Import("user32.lib"), CLink, CallingConvention(.Stdcall)]
public static extern int32 TranslateMessage(MSG* msg);
[Import("user32.lib"), CLink, CallingConvention(.Stdcall)]
public static extern int64 DispatchMessageA(MSG* lpMsg);
[Import("user32.lib"), CLink, CallingConvention(.Stdcall)]
public static extern Windows.Handle BeginPaint(Windows.HWnd hWnd, PAINTSTRUCT* lpPaint);
[Import("user32.lib"), CLink, CallingConvention(.Stdcall)]
public static extern int32 EndPaint(Windows.HWnd hWnd, PAINTSTRUCT* lpPaint);
[Import("gdi32.lib"), CLink, CallingConvention(.Stdcall)]
public static extern int32 TextOutA(Windows.Handle hdc, int32 x, int32 y, char8* lpString, int32 c);
[Import("user32.lib"), CLink, CallingConvention(.Stdcall)]
public static extern bool DestroyWindow(Windows.HWnd hWnd);
[Import("user32.lib"), CLink, CallingConvention(.Stdcall)]
public static extern void PostQuitMessage(int32 nExitCode);
[Import("user32.lib"), CLink, CallingConvention(.Stdcall)]
public static extern Windows.Handle LoadIconA(Windows.HInstance hInstance, char8* lpIconName);
[Import("user32.lib"), CLink, CallingConvention(.Stdcall)]
public static extern Windows.Handle LoadCursorA(Windows.HInstance hInstance, char8* lpCursorName);
[CallingConvention(.Stdcall)]
// TODO: Windows.bf def if WndProc is incorrect, this should be uint32 msg.
static int WndProc(Windows.HWnd hWnd, int32 msg, int wParam, int lParam)
{
if (msg == WM_CLOSE)
{
DestroyWindow(hWnd);
return 0;
}
else if (msg == WM_DESTROY)
{
PostQuitMessage(0);
return 0;
}
else if (msg == WM_PAINT)
{
PAINTSTRUCT ps;
Windows.Handle hdc = BeginPaint(hWnd, &ps);
TextOutA(hdc, 100, 100, "Hello, world!".CStr(), 13);
EndPaint(hWnd, &ps);
return 0;
}
return DefWindowProcA(hWnd, msg, wParam, lParam);
}
void PErr(StringView name)
{
Diagnostics.Debug.WriteLine("{}: GLE={}", name, Windows.GetLastError());
Debug.Assert(false);
}
public this()
{
hwnd_ = 0;
Windows.HInstance hInstance = (Windows.HInstance)0;// TODO: available somewhere?
WNDCLASSEXA wcex = WNDCLASSEXA();
wcex.cbSize = sizeof(WNDCLASSEXA);
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = => WndProc;
wcex.hInstance = hInstance;
wcex.hIcon = LoadIconA(hInstance, "IDI_ICON".CStr());
wcex.hCursor = LoadCursorA(hInstance, IDC_ARROW);
wcex.hbrBackground = (Windows.Handle)(int)(COLOR_WINDOW + 1);
wcex.lpszClassName = "Hackity.WindowClass".CStr();
wcex.hIconSm = LoadIconA(hInstance, "IDI_ICON".CStr());
if (RegisterClassExA(&wcex) == 0) PErr("RegisterClassExA");
RECT rc;
rc.left = 0; rc.top = 0; rc.right = 1024; rc.bottom = 768;
AdjustWindowRect(&rc, WS_OVERLAPPEDWINDOW,/*FALSE*/ 0);
Windows.HWnd parent_hwnd = 0;
Windows.Handle hmenu = 0;
hwnd_ = CreateWindowExA(0, "Hackity.WindowClass".CStr(), "Hackity".CStr(), WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT, rc.right - rc.left, rc.bottom - rc.top,
parent_hwnd, hmenu, hInstance, null);
if (hwnd_ == 0) PErr("CreateWindowExA");
ShowWindow(hwnd_, SW_SHOWDEFAULT);
//SetWindowLongPtr(hwnd, GWLP_USERDATA, user_data_ptr));
//GetClientRect(hwnd, &rc);*/
// TODO: init with rc
}
public void MessagePump()
{
MSG msg = MSG();
while (msg.message != WM_QUIT)
{
if (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE) != 0)
{
TranslateMessage(&msg);
DispatchMessageA(&msg);
}
else
{
// TODO: tick!
}
}
}
private Windows.HWnd hwnd_;
}
class Program
{
public static void Main(String[] args)
{
let w = scope Hackity.Window();
w.MessagePump();
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment