Hello, Win32 GUI(Ruby) World!

Posted on 7月 14th, 2012 by cx20

Win32 GUI(Ruby)

Win32 アプリケーションは Windows 標準 API である Win32 API を使用した Windows アプリケーションである。
以下は Ruby による Win32 GUI アプリケーション の例となっている。
なお、Win32 の構造体の定義に CStruct ライブラリを使用している。

ソースコード

require 'win32/api'
require 'cstruct/win32struct'
 
include Win32
 
WS_VISIBLE      = 0x10000000
WS_CAPTION      = 0x00C00000
WS_SYSMENU      = 0x00080000
WS_MINIMIZEBOX  = 0x00020000
WS_MAXIMIZEBOX  = 0x00010000
WS_THICKFRAME   = 0x00040000
WS_OVERLAPPED   = 0x00000000
 
WS_OVERLAPPEDWINDOW = (WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX)
 
WM_CREATE       = 0x0001
WM_DESTROY      = 0x0002
WM_PAINT        = 0x000F
WM_CLOSE        = 0x0010
WM_COMMAND      = 0x0111
 
CS_VREDRAW      = 0x0001
CS_HREDRAW      = 0x0002
COLOR_WINDOW    = 5
 
CW_USEDEFAULT   = -2147483648 #0x80000000
 
SW_SHOW         = 5
SW_SHOWDEFAULT  = 10
 
Memset          = API.new('memset', 'PLL', 'L', 'msvcrt')
LocalAlloc      = API.new('LocalAlloc', 'LL', 'L', 'kernel32')
GetModuleHandle = API.new('GetModuleHandle', 'P', 'L', 'kernel32')
RegisterClass   = API.new('RegisterClass', 'P', 'L', 'user32')
RegisterClassEx = API.new('RegisterClassEx', 'P', 'L', 'user32')
CloseWindow     = API.new('CloseWindow', 'L', 'B', 'user32')
CreateWindowEx  = API.new('CreateWindowEx', 'LPPLIIIILLLL', 'L', 'user32')
ShowWindow      = API.new('ShowWindow', 'LL', 'B', 'user32')
UpdateWindow    = API.new('UpdateWindow', 'L', 'B', 'user32')
BeginPaint      = API.new('BeginPaint', 'LP', 'L', 'user32')
EndPaint        = API.new('EndPaint', 'LP', 'L', 'user32')
PostQuitMessage = API.new('PostQuitMessage', 'I', 'V', 'user32')
DefWindowProc   = API.new('DefWindowProc', 'LLLL', 'L', 'user32')
GetMessage      = API.new('GetMessage', 'PLII', 'L', 'user32')
DispatchMessage = API.new('DispatchMessage', 'P', 'L', 'user32')
TranslateMessage = API.new('TranslateMessage', 'P', 'B', 'user32')
TextOut         = API.new('TextOut', 'LLLPL', 'B', 'gdi32' );
 
class POINT < Win32Struct
    LONG    :x
    LONG    :y
end
 
class MSG < Win32Struct
    uint32  :hwnd
    UINT    :message
    WPARAM  :wParam
    LPARAM  :lParam
    DWORD   :time
    POINT   :pt
end
 
class WNDCLASSA < Win32Struct
    UINT    :style
    uint32  :lpfnWndProc
    int32   :cbClsExtra
    int32   :cbWndExtra
    HINSTANCE   :hInstance
    HICON   :hIcon
    HCURSOR :hCursor
    HBRUSH  :hbrBackground
    LPCSTR  :lpszMenuName
    LPCSTR  :lpszClassName
end
 
class RECT < Win32Struct
    LONG    :left
    LONG    :top
    LONG    :right
    LONG    :bottom
end
 
class PAINTSTRUCT < Win32Struct
    HDC     :hdc
    BOOL    :fErase
    RECT    :rcPaint
    BOOL    :fRestore
    BOOL    :fIncUpdate
    BYTE    :rgbReserved,[32]
end
 
@window_proc = API::Callback.new('LLLL', 'I') do |hwnd, msg, wparam, lparam|
    ret = 0
    strMessage = "Hello, Win32 GUI(Ruby) World!"
    case msg
    when WM_PAINT
        ps  = PAINTSTRUCT.new
        hdc = BeginPaint.call(hwnd, ps.data)
        TextOut.call(hdc, 0, 0, strMessage, strMessage.length);
        EndPaint.call(hwnd, ps.data)
    when WM_DESTROY
        PostQuitMessage.call(0)
    else 
        ret = DefWindowProc.call(hwnd, msg, wparam, lparam)
    end
    ret
end
 
def alloc_string_buffer init_string, max_length
    buffer_pointer = LocalAlloc.call(0, max_length)
    buffer_addr = buffer_pointer
    Memset.call(buffer_addr, 0, max_length)
 
    init_string.each_byte do |byte|  
        Memset.call(buffer_pointer, byte, 1)
        buffer_pointer += 1
    end  
    buffer_addr
end
 
def WinMain instance, cmd_show
    msg = MSG.new
 
    wc = WNDCLASSA.new
    wc.style         = 0
    wc.lpfnWndProc   = @window_proc.address
    wc.cbClsExtra    = 0
    wc.cbWndExtra    = 0
    wc.hInstance     = instance
    wc.hIcon         = 0
    wc.hCursor       = 0
    wc.hbrBackground = (COLOR_WINDOW+1)
    wc.lpszMenuName  = 0
    wc.lpszClassName = alloc_string_buffer 'helloWindow', 256
 
    RegisterClass.call(wc.data)
 
    hwnd = CreateWindowEx.call(
        0,
        "helloWindow",
        "Hello, World!",
        WS_OVERLAPPEDWINDOW,
        CW_USEDEFAULT,
        CW_USEDEFAULT,
        640,
        480,
        0,
        0,
        wc.hInstance,
        0
    )
 
    ShowWindow.call(hwnd, cmd_show)
    UpdateWindow.call(hwnd)
 
    while(GetMessage.call(msg.data, 0, 0, 0) > 0)
        TranslateMessage.call(msg.data)
        DispatchMessage.call(msg.data)
    end
 
end
 
def main
    instance = GetModuleHandle.call(0)
    WinMain instance, SW_SHOW
end
 
main

ライブラリ導入方法

C:¥> gem install cstruct

実行方法

C:¥> ruby hello.rb

実行結果

+------------------------------------------+
|Hello, World!                    [_][~][X]|
+------------------------------------------+
|Hello, Win32 GUI(Ruby) World!             |
|                                          |
|                                          |
|                                          |
|                                          |
|                                          |
|                                          |
|                                          |
|                                          |
|                                          |
+------------------------------------------+

Tags:

Categories: Ruby, Win32 GUI

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

WP-SpamFree by Pole Position Marketing