Pure RubyでWindowsアプリ
DLを使ってコールバックできれば、ウィンドウプロシージャも作れてWindowsアプリが書けるのではなかろうか。
という話だったので、試してみた。
require "dl/import" require "dl/struct" module LIBC extend DL::Importable dlload "user32.dll" dlload "kernel32.dll" extern "int RegisterClassEx(int*)" extern "int DefWindowProc(int,int,int,int)" extern "int CreateWindowEx(int,char*,char*,int,int,int,int,int,int*,int*,int*,int*)" extern "int PeekMessage(int*,int*,int,int,int)" extern "int TranslateMessage(int*)" extern "int DispatchMessage(int*)" extern "void PostQuitMessage(int)" WndClassEx = struct [ "int cbSize", "int style", "int* lpfnWndProc", "int cbClsExtra", "int cbWndExtra", "int* hInstance", "int* hIcon", "int* hCursor", "int hbrBackground", "char* lpszMenuName", "char* lpszClassName", "int* hIconSm" ] MSG = struct [ "int hwnd", "int message", "int wParam", "int lParam", "int time", "int ptx", "int pty" ] def wndproc(a,b,c,d) if b == 2 then # WM_DESTROY postQuitMessage(0) return 0 end defWindowProc(a,b,c,d) end WNDPROC = callback "int wndproc(int,int,int,int)" end wndclass = LIBC::WndClassEx.malloc wndclass.cbSize = wndclass.size wndclass.style = 0 wndclass.lpfnWndProc = LIBC::WNDPROC wndclass.cbClsExtra = 0 wndclass.cbWndExtra = 0 wndclass.hInstance = nil wndclass.hIcon = nil wndclass.hCursor = nil wndclass.hbrBackground = 5 # COLOR_WINDOW wndclass.lpszMenuName = nil wndclass.lpszClassName = "testclass" wndclass.hIconSm = nil LIBC.registerClassEx(wndclass.to_ptr) # WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME LIBC.createWindowEx(0,"testclass", "testwindow", 0x10000000 | 0x00000000 | 0x00C00000 | 0x00080000 | 0x00040000, 0, 0, 200, 200, nil, nil, nil, nil) msg = LIBC::MSG.malloc loop do if LIBC.peekMessage(msg, nil, 0, 0, 0x0001) != 0 then # PM_REMOVE if msg.message == 0x0012 then # WM_QUIT break end LIBC.translateMessage(msg) LIBC.dispatchMessage(msg) end sleep 0.001 end
うむ。
テキトーに作ったからいろいろ問題はありそうなソースだが、とりあえず動いた。
頑張ればRubyだけできちんとしたWindowsアプリが作れそうだ。
それに意味があるかどうかはちょっと疑問だが。