require 'alien' WS_OVERLAPPED = 0x00000000 WS_CAPTION = 0x00C00000 WS_SYSMENU = 0x00080000 WS_THICKFRAME = 0x00040000 WS_MINIMIZEBOX = 0x00020000 WS_MAXIMIZEBOX = 0x00010000 WS_OVERLAPPEDWINDOW = WS_OVERLAPPED + WS_CAPTION + WS_SYSMENU + WS_THICKFRAME + WS_MINIMIZEBOX + WS_MAXIMIZEBOX WM_DESTROY = 0x0002 WM_SIZE = 0x0005 WM_CLOSE = 0x0010 WM_PAINT = 0x000F CW_USEDEFAULT = 0x80000000 SW_SHOWNORMAL = 1 BLACK_BRUSH = 4 COLOR_WINDOW = 5 POINTAPI = alien.defstruct{ {"x", "long"}; {"y", "long"}; } MSG = alien.defstruct{ {"hwnd", "pointer"}; {"message", "uint"}; {"wParam", "pointer"}; {"lParam", "pointer"}; {"time", "ulong"}; {"x", "long"}; {"y", "long"}; } WNDCLASSEX = alien.defstruct{ {"cbSize", "uint"}; {"style", "uint"}; {"lpfnWndProc", "callback"}; {"cbClsExtra", "int"}; {"cbWndExtra", "int"}; {"hInstance", "pointer"}; {"hIcon", "pointer"}; {"hCursor", "pointer"}; {"hbrBackground", "pointer"}; {"lpszMenuName", "string"}; {"lpszClassName", "string"}; {"hIconSm", "pointer"}; } RECT = alien.defstruct{ {"Left", "long"}; {"Top", "long"}; {"Right", "long"}; {"Bottom", "long"}; } PAINTSTRUCT = alien.defstruct{ {"hdc", "uint"}; {"fErase", "int"}; {"rcPaint_left", "long"}; {"rcPaint_top", "long"}; {"rcPaint_right", "long"}; {"rcPaint_bottom", "long"}; {"fRestore", "int"}; {"fIncUpdate", "int"}; --[[ {"rgbReserved", "byte[32]"}; ]] } PAINTSTRUCT.size = PAINTSTRUCT.size + 32 RegisterClassEx = alien.user32.RegisterClassExA; RegisterClassEx:types{ ret = "ushort", abi = "stdcall"; "pointer" } DestroyWindow = alien.user32.DestroyWindow; DestroyWindow:types{ ret = "int", abi = "stdcall"; "pointer" } PostQuitMessage = alien.user32.PostQuitMessage; PostQuitMessage:types{ ret = "void", abi = "stdcall"; "int" } DefWindowProc = alien.user32.DefWindowProcA; DefWindowProc:types{ ret = "long", abi = "stdcall"; "pointer", "uint", "uint", "long" } GetMessage = alien.user32.GetMessageA; GetMessage:types{ ret = "int", abi = "stdcall"; "pointer", "pointer", "uint", "uint" } TranslateMessage = alien.user32.TranslateMessage; TranslateMessage:types{ ret = "int", abi = "stdcall"; "pointer" } DispatchMessage = alien.user32.DispatchMessageA; DispatchMessage:types{ ret = "int", abi = "stdcall"; "pointer" } CreateWindowEx = alien.user32.CreateWindowExA; CreateWindowEx:types{ ret = "pointer", abi = "stdcall"; "ulong", "string", "string", "ulong", "int", "int", "int", "int", "pointer", "pointer", "pointer" } ShowWindow = alien.user32.ShowWindow; ShowWindow:types{ ret = "int", abi = "stdcall"; "pointer", "int" } UpdateWindow = alien.user32.UpdateWindow; UpdateWindow:types{ ret = "int", abi = "stdcall"; "pointer" } BeginPaint = alien.user32.BeginPaint; BeginPaint:types{ ret = "pointer", abi = "stdcall"; "pointer", "pointer" } EndPaint = alien.user32.EndPaint; EndPaint:types{ ret = "int", abi = "stdcall"; "long", "pointer" } TextOut = alien.gdi32.TextOutA; TextOut:types{ ret = "int", abi = "stdcall"; "pointer", "int", "int", "string", "int" } GetStockObject = alien.gdi32.GetStockObject; GetStockObject:types{ ret = "pointer", abi = "stdcall"; "int" } CLASS_NAME = "helloWindow" WINDOW_NAME = "Hello, World" function WndProc(hwnd, uMsg, wParam, lParam) ps = PAINTSTRUCT:new() strMessage = string.format("Hello, Win32 GUI(Lua) World!") if (uMsg == WM_DESTROY) then PostQuitMessage(0) elseif (uMsg == WM_PAINT) then hdc = BeginPaint( hwnd, ps() ) TextOut( hdc, 0, 0, strMessage, string.len(strMessage) ) EndPaint( hwnd, ps() ) else return DefWindowProc(hwnd, uMsg, wParam, lParam) end return nil end function WinMain() wcex = WNDCLASSEX:new() wcex.cbSize = WNDCLASSEX.size wcex.style = 0 wcex.lpfnWndProc = alien.callback(WndProc, { ret = "long", abi = "stdcall"; "pointer", "uint", "uint", "long" }) wcex.cbClsExtra = 0 wcex.cbWndExtra = 0 wcex.hInstance = nil wcex.hIcon = nil wcex.hCursor = nil wcex.hbrBackground = GetStockObject(COLOR_WINDOW+1) wcex.lpszMenuName = nil wcex.lpszClassName = CLASS_NAME wcex.hIconSm = nil RegisterClassEx(wcex()) hwnd = CreateWindowEx( 0, CLASS_NAME, WINDOW_NAME, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 640, 480, nil, nil, nil) ShowWindow(hwnd, SW_SHOWNORMAL) UpdateWindow(hwnd) msg = MSG:new() msg_ptr = msg() while (GetMessage(msg_ptr, nil, 0, 0) ~= 0) do TranslateMessage(msg_ptr) DispatchMessage(msg_ptr) end end function main() WinMain() end main()