-
-
Save mirichi/96eeee34c85677592bd1b0733ccb0f3d to your computer and use it in GitHub Desktop.
なんとか呼べたっぽい
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require 'ffi' | |
width = 320 | |
height = 240 | |
# 構造体にアクセサを生やす拡張 | |
class << FFI::Struct | |
def layout_ex *args | |
layout *args | |
args.each_slice(2) do |member, type| | |
define_method(member) do | |
self[member] | |
end | |
define_method("#{member}=".to_sym) do |v| | |
self[member] = v | |
end | |
end | |
end | |
end | |
# enum時についでに定数を定義する拡張 | |
module FFI::Library | |
def enum_ex *args | |
args.each do |member| | |
self.const_set(member, member) if member.is_a?(Symbol) | |
end | |
enum args | |
end | |
end | |
module WinAPI | |
extend FFI::Library | |
ffi_lib 'gdi32', 'ole32', 'user32', 'kernel32' | |
ffi_convention(:stdcall) | |
ULONG_PTR = FFI::TypeDefs[:uintptr_t] | |
LONG_PTR = FFI::TypeDefs[:intptr_t] | |
ULONG = FFI::TypeDefs[:ulong] | |
LONG = FFI::TypeDefs[:long] | |
UINT = FFI::TypeDefs[:uint] | |
INT = FFI::TypeDefs[:int] | |
BYTE = FFI::TypeDefs[:uchar] | |
WORD = FFI::TypeDefs[:ushort] | |
DWORD = FFI::TypeDefs[:uint] | |
BOOL = FFI::TypeDefs[:int] | |
POINTER = FFI::TypeDefs[:pointer] | |
VOID = FFI::TypeDefs[:void] | |
LPVOID = FFI::TypeDefs[:pointer] | |
LPCSTR = FFI::TypeDefs[:pointer] | |
LPCTSTR = FFI::TypeDefs[:pointer] | |
HWND = HICON = HCURSOR = HBRUSH = HINSTANCE = HMENU = HMODULE = HANDLE = ULONG_PTR | |
LPARAM = LONG_PTR | |
WPARAM = ULONG_PTR | |
LRESULT = LONG_PTR | |
HRESULT = LONG | |
ATOM = WORD | |
WINBOOL = BOOL | |
WNDPROC = callback(:WindowProc, [HWND, UINT, WPARAM, LPARAM], LRESULT) | |
class WNDCLASSEX < FFI::Struct | |
layout_ex :cbSize, UINT, | |
:style, UINT, | |
:lpfnWndProc, WNDPROC, | |
:cbClsExtra, INT, | |
:cbWndExtra, INT, | |
:hInstance, HINSTANCE, | |
:hIcon, HICON, | |
:hCursor, HCURSOR, | |
:hbrBackground, HBRUSH, | |
:lpszMenuName, LPCSTR, | |
:lpszClassName, LPCSTR, | |
:hIconSm, HICON | |
end | |
class POINT < FFI::Struct | |
layout_ex :x, LONG, | |
:y, LONG | |
end | |
class MSG < FFI::Struct | |
layout_ex :hwnd, HWND, | |
:message, UINT, | |
:wParam, WPARAM, | |
:lParam, LPARAM, | |
:time, DWORD, | |
:pt, POINT | |
end | |
class RECT < FFI::Struct | |
layout_ex :left, LONG, | |
:top, LONG, | |
:right, LONG, | |
:bottom, LONG | |
end | |
LPRECT = RECT.ptr | |
attach_function :GetModuleHandle, :GetModuleHandleA, [ LPCSTR ], HMODULE | |
attach_function :RegisterClassEx, :RegisterClassExA, [ WNDCLASSEX.ptr ], ATOM | |
attach_function :AdjustWindowRect, [ LPRECT, DWORD, WINBOOL ], WINBOOL | |
attach_function :CreateWindowEx, :CreateWindowExA, [ DWORD, LPCTSTR, LPCTSTR, DWORD, UINT, UINT, INT, INT, HWND, HMENU, HINSTANCE, LPVOID ], HWND | |
attach_function :DefWindowProc, :DefWindowProcA, [ HWND, UINT, WPARAM, LPARAM ], LRESULT | |
attach_function :DestroyWindow, [ HWND ], BOOL | |
attach_function :PostQuitMessage, [ INT ], VOID | |
attach_function :GetMessage, :GetMessageA, [ MSG.ptr, HWND, UINT, UINT ], BOOL | |
attach_function :TranslateMessage, [ MSG.ptr ], BOOL | |
attach_function :DispatchMessage, :DispatchMessageA, [ MSG.ptr ], BOOL | |
attach_function :SetCursor, [ HCURSOR ], HCURSOR | |
attach_function :LoadCursor, :LoadCursorA, [ HINSTANCE, LPCSTR ], HCURSOR | |
# 使いそうな定数の定義 | |
CS_VREDRAW = 0x0001 | |
CS_HREDRAW = 0x0002 | |
CS_DBLCLKS = 0x0008 | |
CS_OWNDC = 0x0020 | |
CS_CLASSDC = 0x0040 | |
CS_PARENTDC = 0x0080 | |
CS_NOCLOSE = 0x0200 | |
CS_SAVEBITS = 0x0800 | |
CS_BYTEALIGNCLIENT = 0x1000 | |
CS_BYTEALIGNWINDOW = 0x2000 | |
CS_GLOBALCLASS = 0x4000 | |
CS_IME = 0x00010000 | |
CS_DROPSHADOW = 0x00020000 | |
COLOR_SCROLLBAR = 0 | |
COLOR_BACKGROUND = 1 | |
COLOR_ACTIVECAPTION = 2 | |
COLOR_INACTIVECAPTION = 3 | |
COLOR_MENU = 4 | |
COLOR_WINDOW = 5 | |
COLOR_WINDOWFRAME = 6 | |
COLOR_MENUTEXT = 7 | |
COLOR_WINDOWTEXT = 8 | |
COLOR_CAPTIONTEXT = 9 | |
COLOR_ACTIVEBORDER = 10 | |
COLOR_INACTIVEBORDER = 11 | |
COLOR_APPWORKSPACE = 12 | |
COLOR_HIGHLIGHT = 13 | |
COLOR_HIGHLIGHTTEXT = 14 | |
COLOR_BTNFACE = 15 | |
COLOR_BTNSHADOW = 16 | |
COLOR_GRAYTEXT = 17 | |
COLOR_BTNTEXT = 18 | |
COLOR_INACTIVECAPTIONTEXT = 19 | |
COLOR_BTNHIGHLIGHT = 20 | |
COLOR_3DDKSHADOW = 21 | |
COLOR_3DLIGHT = 22 | |
COLOR_INFOTEXT = 23 | |
COLOR_INFOBK = 24 | |
COLOR_HOTLIGHT = 26 | |
COLOR_GRADIENTACTIVECAPTION = 27 | |
COLOR_GRADIENTINACTIVECAPTION = 28 | |
COLOR_MENUHILIGHT = 29 | |
COLOR_MENUBAR = 30 | |
COLOR_DESKTOP = COLOR_BACKGROUND | |
COLOR_3DFACE = COLOR_BTNFACE | |
COLOR_3DSHADOW = COLOR_BTNSHADOW | |
COLOR_3DHIGHLIGHT = COLOR_BTNHIGHLIGHT | |
COLOR_3DHILIGHT = COLOR_BTNHIGHLIGHT | |
COLOR_BTNHILIGHT = COLOR_BTNHIGHLIGHT | |
WS_OVERLAPPED = 0x00000000 | |
WS_POPUP = 0x80000000 | |
WS_CHILD = 0x40000000 | |
WS_MINIMIZE = 0x20000000 | |
WS_VISIBLE = 0x10000000 | |
WS_DISABLED = 0x08000000 | |
WS_CLIPSIBLINGS = 0x04000000 | |
WS_CLIPCHILDREN = 0x02000000 | |
WS_MAXIMIZE = 0x01000000 | |
WS_CAPTION = 0x00C00000 | |
WS_BORDER = 0x00800000 | |
WS_DLGFRAME = 0x00400000 | |
WS_VSCROLL = 0x00200000 | |
WS_HSCROLL = 0x00100000 | |
WS_SYSMENU = 0x00080000 | |
WS_THICKFRAME = 0x00040000 | |
WS_GROUP = 0x00020000 | |
WS_TABSTOP = 0x00010000 | |
WS_MINIMIZEBOX = 0x00020000 | |
WS_MAXIMIZEBOX = 0x00010000 | |
WS_TILED = WS_OVERLAPPED | |
WS_ICONIC = WS_MINIMIZE | |
WS_SIZEBOX = WS_THICKFRAME | |
WS_OVERLAPPEDWINDOW = (WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX) | |
WS_TILEDWINDOW = WS_OVERLAPPEDWINDOW | |
WS_POPUPWINDOW = (WS_POPUP | WS_BORDER | WS_SYSMENU) | |
WS_CHILDWINDOW = (WS_CHILD) | |
CW_USEDEFAULT = 0x80000000 | |
WM_NULL = 0x0000 | |
WM_CREATE = 0x0001 | |
WM_DESTROY = 0x0002 | |
WM_MOVE = 0x0003 | |
WM_SIZE = 0x0005 | |
WM_ACTIVATE = 0x0006 | |
WA_INACTIVE = 0 | |
WA_ACTIVE = 1 | |
WA_CLICKACTIVE = 2 | |
WM_SETFOCUS = 0x0007 | |
WM_KILLFOCUS = 0x0008 | |
WM_ENABLE = 0x000A | |
WM_SETREDRAW = 0x000B | |
WM_SETTEXT = 0x000C | |
WM_GETTEXT = 0x000D | |
WM_GETTEXTLENGTH = 0x000E | |
WM_PAINT = 0x000F | |
WM_CLOSE = 0x0010 | |
WM_QUIT = 0x0012 | |
WM_ERASEBKGND = 0x0014 | |
WM_SYSCOLORCHANGE = 0x0015 | |
WM_SHOWWINDOW = 0x0018 | |
WM_WININICHANGE = 0x001A | |
WM_SETTINGCHANGE = WM_WININICHANGE | |
WM_DEVMODECHANGE = 0x001B | |
WM_ACTIVATEAPP = 0x001C | |
WM_FONTCHANGE = 0x001D | |
WM_TIMECHANGE = 0x001E | |
WM_CANCELMODE = 0x001F | |
WM_SETCURSOR = 0x0020 | |
WM_MOUSEACTIVATE = 0x0021 | |
WM_CHILDACTIVATE = 0x0022 | |
WM_QUEUESYNC = 0x0023 | |
IDC_ARROW = 32512 | |
IDC_IBEAM = 32513 | |
IDC_WAIT = 32514 | |
IDC_CROSS = 32515 | |
IDC_UPARROW = 32516 | |
IDC_SIZE = 32640 | |
IDC_ICON = 32641 | |
IDC_SIZENWSE = 32642 | |
IDC_SIZENESW = 32643 | |
IDC_SIZEWE = 32644 | |
IDC_SIZENS = 32645 | |
IDC_SIZEALL = 32646 | |
IDC_NO = 32648 | |
IDC_HAND = 32649 | |
IDC_APPSTARTING = 32650 | |
IDC_HELP = 32651 | |
end | |
hInstance = WinAPI::GetModuleHandle(nil) | |
def wndproc(hWnd, msg, wParam, lParam) | |
case msg | |
when WinAPI::WM_CLOSE | |
WinAPI::DestroyWindow(hWnd) | |
when WinAPI::WM_DESTROY | |
WinAPI::PostQuitMessage(0) | |
else | |
return WinAPI::DefWindowProc(hWnd, msg, wParam, lParam) | |
end | |
return 0 | |
end | |
wcex = WinAPI::WNDCLASSEX.new | |
wcex.cbSize = WinAPI::WNDCLASSEX.size | |
wcex.style = WinAPI::CS_HREDRAW | WinAPI::CS_VREDRAW | |
wcex.lpfnWndProc = method(:wndproc) | |
wcex.cbClsExtra = 0 | |
wcex.cbWndExtra = 0 | |
wcex.hInstance = hInstance | |
wcex.hIcon = 0 | |
wcex.hIconSm = 0 | |
wcex.hCursor = 0 | |
wcex.hbrBackground = WinAPI::COLOR_WINDOW | |
wcex.lpszMenuName = nil | |
wcex.lpszClassName = FFI::MemoryPointer.from_string("test") | |
atom = WinAPI::RegisterClassEx(wcex) | |
rect = WinAPI::RECT.new | |
rect.top = 0 | |
rect.left = 0 | |
rect.right = width | |
rect.bottom = height | |
WinAPI::AdjustWindowRect(rect, WinAPI::WS_OVERLAPPED | WinAPI::WS_CAPTION | WinAPI::WS_SYSMENU | WinAPI::WS_MINIMIZEBOX, 0) | |
# ウィンドウ作成 | |
hWnd = WinAPI::CreateWindowEx(0, "test", "Test Window", | |
WinAPI::WS_OVERLAPPED | WinAPI::WS_CAPTION | WinAPI::WS_SYSMENU | WinAPI::WS_MINIMIZEBOX | WinAPI::WS_VISIBLE, | |
WinAPI::CW_USEDEFAULT, WinAPI::CW_USEDEFAULT, | |
rect.right - rect.left, rect.bottom - rect.top, | |
0, 0, hInstance, nil ); | |
# カーソル設定 | |
WinAPI::SetCursor(WinAPI::LoadCursor(0, FFI::Pointer.new(WinAPI::IDC_ARROW))) | |
module D3D9 | |
extend FFI::Library | |
ffi_lib 'd3d9', 'ole32' | |
ffi_convention(:stdcall) | |
ULONG_PTR = FFI::TypeDefs[:uintptr_t] | |
LONG_PTR = FFI::TypeDefs[:intptr_t] | |
ULONG = FFI::TypeDefs[:ulong] | |
LONG = FFI::TypeDefs[:long] | |
UINT = FFI::TypeDefs[:uint] | |
INT = FFI::TypeDefs[:int] | |
BYTE = FFI::TypeDefs[:uchar] | |
WORD = FFI::TypeDefs[:ushort] | |
DWORD = FFI::TypeDefs[:uint] | |
BOOL = FFI::TypeDefs[:int] | |
POINTER = FFI::TypeDefs[:pointer] | |
VOID = FFI::TypeDefs[:void] | |
LPVOID = FFI::TypeDefs[:pointer] | |
LPCSTR = FFI::TypeDefs[:pointer] | |
LPCTSTR = FFI::TypeDefs[:pointer] | |
HWND = HICON = HCURSOR = HBRUSH = HINSTANCE = HMENU = HMODULE = HANDLE = ULONG_PTR | |
LPARAM = LONG_PTR | |
WPARAM = ULONG_PTR | |
LRESULT = LONG_PTR | |
HRESULT = LONG | |
ATOM = WORD | |
WINBOOL = BOOL | |
D3DMULTISAMPLE_TYPE = enum_ex( | |
:D3DMULTISAMPLE_NONE , 0, | |
:D3DMULTISAMPLE_NONMASKABLE , 1, | |
:D3DMULTISAMPLE_2_SAMPLES , 2, | |
:D3DMULTISAMPLE_3_SAMPLES , 3, | |
:D3DMULTISAMPLE_4_SAMPLES , 4, | |
:D3DMULTISAMPLE_5_SAMPLES , 5, | |
:D3DMULTISAMPLE_6_SAMPLES , 6, | |
:D3DMULTISAMPLE_7_SAMPLES , 7, | |
:D3DMULTISAMPLE_8_SAMPLES , 8, | |
:D3DMULTISAMPLE_9_SAMPLES , 9, | |
:D3DMULTISAMPLE_10_SAMPLES , 10, | |
:D3DMULTISAMPLE_11_SAMPLES , 11, | |
:D3DMULTISAMPLE_12_SAMPLES , 12, | |
:D3DMULTISAMPLE_13_SAMPLES , 13, | |
:D3DMULTISAMPLE_14_SAMPLES , 14, | |
:D3DMULTISAMPLE_15_SAMPLES , 15, | |
:D3DMULTISAMPLE_16_SAMPLES , 16, | |
:D3DMULTISAMPLE_FORCE_DWORD , 0x7fffffff | |
) | |
# 定数 | |
D3D_SDK_VERSION = 32 | |
D3DFMT_UNKNOWN = 0 | |
D3DFMT_D24S8 = 75 | |
D3DSWAPEFFECT_DISCARD = 1 | |
D3DPRESENT_INTERVAL_IMMEDIATE = 0x80000000 | |
D3DADAPTER_DEFAULT = 0 | |
D3DDEVTYPE_HAL = 1 | |
D3DCREATE_MIXED_VERTEXPROCESSING = 0x00000080 | |
D3DCLEAR_TARGET = 0x00000001 | |
D3DCLEAR_ZBUFFER = 0x00000002 | |
D3DCLEAR_STENCIL = 0x00000004 | |
# COMインターフェイス基本クラス | |
class COM < FFI::Struct | |
class << self | |
# 自身の構造体レイアウトを設定し、VTableクラスを参照してメソッドを定義する | |
def init | |
vtbl = self.const_get(:VTable) | |
layout_ex :lpVtbl, vtbl.ptr | |
vtbl.members.each do |member| | |
define_method(member) do |*args| | |
self[:lpVtbl][member].call(self, *args) | |
end | |
end | |
end | |
end | |
end | |
# IDirect3D9インターフェイス | |
class IDirect3D9 < COM | |
# Idirect3D9のメンバ定義 | |
class VTable < FFI::Struct | |
layout_ex :QueryInterface, callback([ IDirect3D9.ptr ], HRESULT), # できてないので呼ぶとコケる | |
:AddRef, callback([ IDirect3D9.ptr ], ULONG), | |
:Release, callback([ IDirect3D9.ptr ], ULONG) | |
end | |
# VTable構造体を定義してからinitを呼ぶとメソッドが定義される | |
init | |
end | |
attach_function :Direct3DCreate9, [ UINT ], IDirect3D9.ptr | |
attach_function :CoInitialize, [ LPVOID ], HRESULT | |
end | |
D3D9::CoInitialize(nil) | |
d3d9 = D3D9::Direct3DCreate9(D3D9::D3D_SDK_VERSION) # IDirect3D9インターフェイスが返る | |
p d3d9.Release # こんな感じに呼べる | |
# ウィンドウメッセージ構造体作成 | |
msg = WinAPI::MSG.new | |
# メッセージループ | |
loop do | |
if WinAPI::GetMessage(msg, 0, 0, 0) == 0 | |
break | |
end | |
WinAPI::TranslateMessage(msg) | |
WinAPI::DispatchMessage(msg) | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment