Skip to content

Instantly share code, notes, and snippets.

@mirichi

mirichi/actctx.rb Secret

Created Dec 13, 2016
Embed
What would you like to do?
アクティベーションコンテキストサンプル
require 'tmpdir'
require "fiddle/import"
require 'fiddle/types'
width = 320
height = 240
# WindowsAPIのインターフェイス
module WinAPI
extend Fiddle::Importer
dlload "gdi32", "ole32", "user32", "kernel32"
include Fiddle::Win32Types
# 型の定義
typealias "HMENU", "unsigned int"
typealias "HICON", "unsigned int"
typealias "HCURSOR", "unsigned int"
typealias "HBRUSH", "unsigned int"
typealias "HMODULE", "unsigned int"
typealias "WNDPROC", "void *"
typealias "LPVOID", "void *"
typealias "LPMSG", "void *"
typealias "WINBOOL", "int"
typealias "LONG", "long"
typealias "WPARAM", "void *"
typealias "LPARAM", "void *"
typealias "LRESULT", "void *"
typealias "LPRECT", "void *"
typealias "PACTCTX", "void *"
typealias "LPCWSTR", "char *"
typealias "LPCTSTR", "char *"
typealias "USHORT", "unsigned short"
typealias "LANGID", "unsigned short"
# WindowsAPIの定義
extern "HWND CreateWindowExA(DWORD, LPCSTR, LPCSTR, DWORD, DWORD, DWORD, int, int, HWND, HMENU, HINSTANCE, LPVOID)"
extern "ATOM RegisterClassExA(void *)"
extern "HMODULE GetModuleHandleA(LPCSTR)"
extern "UINT DefWindowProcA(HWND, UINT, UINT, LONG)"
extern "WINBOOL GetMessageA(LPMSG, HWND, UINT, UINT)"
extern "WINBOOL TranslateMessage(LPMSG)"
extern "LRESULT DispatchMessageA(LPMSG)"
extern "HCURSOR SetCursor(HCURSOR)"
extern "HCURSOR LoadCursorA(HINSTANCE, LPCSTR)"
extern "WINBOOL AdjustWindowRect(LPRECT, DWORD, WINBOOL)"
extern "void PostQuitMessage(int)"
extern "WINBOOL DestroyWindow(HWND)"
extern "HANDLE CreateActCtx(PACTCTX)"
extern "BOOL ActivateActCtx(HANDLE, void **)"
extern "void ReleaseActCtx(HANDLE)"
# 構造体の定義
WNDCLASSEX = struct([
"UINT cbSize",
"UINT style",
"WNDPROC lpfnWndProc",
"int cbClsExtra",
"int cbWndExtra",
"HINSTANCE hInstance",
"HICON hIcon",
"HCURSOR hCursor",
"HBRUSH hbrBackground",
"LPCSTR lpszMenuName",
"LPCSTR lpszClassName",
"HICON hIconSm"
])
MSG = struct([
"HWND hwnd",
"UINT message",
"WPARAM wParam",
"LPARAM lParam",
"DWORD time",
"LONG x",
"LONG y"
])
RECT = struct([
"LONG left",
"LONG top",
"LONG right",
"LONG bottom"
])
GUID = struct([
"unsigned long Data1",
"unsigned short Data2",
"unsigned short Data3",
"unsigned char Data4[8]"
])
ACTCTX = struct([
"ULONG cbSize",
"DWORD dwFlags",
"LPCWSTR lpSource",
"USHORT wProcessorArchitecture",
"LANGID wLangId",
"LPCTSTR lpAssemblyDirectory",
"LPCTSTR lpResourceName",
"LPCTSTR lpApplicationName",
"HMODULE hModule"
])
# 使いそうな定数の定義
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
BS_PUSHBUTTON = 0x00000000
end
# ウィンドウプロシージャ
class WndProc < Fiddle::Closure
def call(hWnd, msg, wParam, lParam)
case msg
when WinAPI::WM_CLOSE
WinAPI::DestroyWindow(hWnd)
when WinAPI::WM_DESTROY
WinAPI::PostQuitMessage(0)
else
return WinAPI::DefWindowProcA(hWnd, msg, wParam, lParam)
end
return 0
end
end
# 実行中のプログラムのインスタンスハンドル取得
hInstance = WinAPI::GetModuleHandleA(0)
hActCtx = nil
open(Dir.tmpdir + "/XPThemes.manifest", "wt") do |f|
f.write(<<"EOS")
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<dependency>
<dependentAssembly>
<assemblyIdentity
type="win32" name="Microsoft.Windows.Common-Controls" version="6.0.0.0"
processorArchitecture="*" publicKeyToken="6595b64144ccf1df" language="*" />
</dependentAssembly>
</dependency>
</assembly>
EOS
end
# アクティベーションコンテキスト
actctx = WinAPI::ACTCTX.new(Fiddle::Pointer.malloc(WinAPI::ACTCTX.size))
actctx.cbSize = WinAPI::ACTCTX.size
actctx.lpSource = Dir.tmpdir + "/XPThemes.manifest"#.encode("UTF-16LE")
hActCtx = WinAPI::CreateActCtx(actctx)
cookie = Fiddle::Pointer.malloc(4)
WinAPI::ActivateActCtx(hActCtx, cookie)
# ウィンドウプロシージャ
wndproc = WndProc.new(Fiddle::TYPE_LONG, [-Fiddle::TYPE_INT, -Fiddle::TYPE_INT, -Fiddle::TYPE_INT, Fiddle::TYPE_INT])
# WNDCLASSEX構造体作成
wcex = WinAPI::WNDCLASSEX.malloc
wcex.cbSize = WinAPI::WNDCLASSEX.size
wcex.style = WinAPI::CS_HREDRAW | WinAPI::CS_VREDRAW
wcex.lpfnWndProc = 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 = "test"
# (Windowsの)クラス定義
WinAPI::RegisterClassExA(wcex)
# ウィンドウサイズ計算
rect = WinAPI::RECT.malloc
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::CreateWindowExA(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, 0 );
# カーソル設定
WinAPI::SetCursor(WinAPI::LoadCursorA(0, WinAPI::IDC_ARROW))
hButtonWnd = WinAPI::CreateWindowExA(0, "BUTTON", "Button Test1",
WinAPI::WS_VISIBLE | WinAPI::WS_CHILD | WinAPI::BS_PUSHBUTTON | WinAPI::WS_TABSTOP,
20, 20,
100, 30,
hWnd, 0, hInstance, 0 );
hButtonWnd = WinAPI::CreateWindowExA(0, "BUTTON", "Button Test2",
WinAPI::WS_VISIBLE | WinAPI::WS_CHILD | WinAPI::BS_PUSHBUTTON | WinAPI::WS_TABSTOP,
20, 80,
100, 30,
hWnd, 0, hInstance, 0 );
# ウィンドウメッセージ構造体作成
msg = WinAPI::MSG.malloc
# メッセージループ
loop do
if WinAPI::GetMessageA(msg, 0, 0, 0) == 0
break
end
WinAPI::TranslateMessage(msg)
WinAPI::DispatchMessageA(msg)
end
WinAPI::ReleaseActCtx(hActCtx)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment