module Seiran20
module_function
class ::Integer; def to_ptr; self; end; def to_param; 'i'; end; def ord; self; end; end
class ::String;def to_ptr; [self].pack('p').unpack('L').first; end; def to_param; 'p'; end; end
def api(dll,func)
lambda{|*args|
Win32API.new(dll,func,args.map{|x|x.to_param}, 'i').call *args
}
end
def callproc(addr, type = :cdecl)
stdcall = type == :stdcall
raise "addr == 0 " if addr.to_ptr == 0
apicall = api('user32', 'CallWindowProcW')
lambda{|*args|apicall.call((code=[0x55,0xe589].pack('CS')+args.map{|x| [0x68, x.to_ptr].pack('CL')}.reverse.join+[0xb8, addr.to_ptr, 0xD0FF, 0xc481, (stdcall ? 0 : args.length*4) , 0x10c2c9].pack('CLSSLL')),0,0,0,0)}
end
LL = api("kernel32", "LoadLibrary")
GPA = api("kernel32", "GetProcAddress")
def funcaddr(dll, func)
x = GPA.call(LL.call(dll), func)
x == 0 ? nil : x
end
def capi(dll, func)
callproc(GPA.call(LL.call(dll), func))
end
def hwnd
msg , r, pm, ac = "\0"*24, 0, api('user32', 'PeekMessage'), api('user32', 'GetAncestor')
loop do
return r if pm.call(msg, 0, 0, 0, 0) != 0 and ((r = ac.call(msg.unpack('L').first, 3))!=0)
::Graphics.update if defined?(::Graphics)
end
end
end
module Mouse
extend Seiran20
WINDOW = hwnd
EVENT = []
GS = api 'user32', 'GetCursorPos'
SC = api 'user32', 'ScreenToClient'
KEY = api 'user32', 'GetKeyState'
def self.x
@x
end
def self.y
@y
end
def self.mousepos
GS.call buf = "\0"*8
SC.call WINDOW, buf
buf.unpack "ll"
end
def self.update
lastx, lasty = @x, @y
@x, @y = mousepos
if lastx != @x || lasty != @y
EVENT.push :mouse_move
end
lastkey = (@key|| 0) & 0x8000
@key= KEY.call(1) & 0x8000
if lastkey != @key
EVENT.push @key== 0x8000 ? :mouse_down : :mouse_up
end
end
def self.has_event?
!EVENT.empty?
end
end
def mouse_event
Mouse::EVENT.shift
end
def get_window_under_mouse
$window_list.reverse.find{|w| #找一个包含了鼠标位置的窗体
w.x <= Mouse.x && Mouse.x < w.x + w.width &&
w.y <= Mouse.y && Mouse.y < w.y + w.height
}
end
$data_system = load_data 'Data/system.rvdata2'
def new_window(x, y)
w = Window.new x, y, 1, 1
w.windowskin = Cache.system('window')
w.tone = $data_system.window_tone
w.z = $window_list.size #######add
w
end
def active_window #######add
mz = $window_list.size - 1
$window_list.each {|w|
w.z -= 1 if w.z >= $window.z
}
$window.z = mz
end
def resize_window #######add
$window.width = Mouse.x - $window.x
$window.width = 30 if $window.width < 30
$window.height = Mouse.y - $window.y
$window.height = 22 if $window.height < 22
end
def main_logic
case [mouse_event, $status]
when [:mouse_down, :normal]
if $window = get_window_under_mouse # 鼠标下能取到窗体,就当是拖动
$status = :window_selected
$cx, $cy = Mouse.x - $window.x, Mouse.y - $window.y
active_window #######add
else
$status = :create_window # 否则就是创建
$window = new_window(Mouse.x, Mouse.y)
end
when [:mouse_up, :window_selected]
$status = :normal
when [:mouse_up, :create_window]
$window_list.push $window #加入到某个窗口列表
$status = :normal
$window = nil
when [:mouse_move, :window_selected]
$window.x, $window.y = Mouse.x - $cx, Mouse.y - $cy
when [:mouse_move, :create_window]
resize_window #######add
end while Mouse::has_event?
end
def ui_update
main_logic
$window_list.each{|x| x.update}
$window.update if $window
end
$status = :normal
$window_list = []
loop do
Graphics.update
Input.update
Mouse.update
ui_update
end