Project1
标题: 免DLL輸入框 [打印本页]
作者: danny8376 时间: 2013-3-1 18:24
标题: 免DLL輸入框
本帖最后由 danny8376 于 2013-5-23 20:39 编辑
虽然这类脚本发过很多了
不过这个应该算最完整了=w=
基本上一般文字输入框的功能都有了
(显示上也是 选取都有做出来了XDD)
不过原本想改成Unicode 这样可以解决编码问题
不过没办法产生支援Unicode的文字框...
不知道有没有啥办法呢=3=
直接显示文字输入框也有做
不过懒得去背景+改文字颜色
有时间再改吧
符号类别扩充 颇喜欢这种WIN32API用法
#encoding:utf-8
#==============================================================================
# ■ Symbol
#------------------------------------------------------------------------------
# 。
#==============================================================================
$apicache = {}
class Symbol
#--------------------------------------------------------------------------
# ● 轉為Win32API
#--------------------------------------------------------------------------
def to_api
$apicache[self] = Win32API.new(*self.to_s.split("|")) unless $apicache.include? self
return $apicache[self]
end
#--------------------------------------------------------------------------
# ● 轉為Win32API並呼叫
#--------------------------------------------------------------------------
def apicall(*args)
self.to_api.call(*args)
end
end
#encoding:utf-8
#==============================================================================
# ■ Symbol
#------------------------------------------------------------------------------
# 。
#==============================================================================
$apicache = {}
class Symbol
#--------------------------------------------------------------------------
# ● 轉為Win32API
#--------------------------------------------------------------------------
def to_api
$apicache[self] = Win32API.new(*self.to_s.split("|")) unless $apicache.include? self
return $apicache[self]
end
#--------------------------------------------------------------------------
# ● 轉為Win32API並呼叫
#--------------------------------------------------------------------------
def apicall(*args)
self.to_api.call(*args)
end
end
下方是修改过的晴兰的纯脚本不使用DLL就读取窗口消息
主要是产生消息函数给文字框用
#encoding:utf-8
# 纯脚本不使用DLL就读取窗口消息
# By 晴兰 form 66RPG
# 功能擴充 By AAM@_@
#==============================================================================
# ■ MainWindow
#------------------------------------------------------------------------------
# 。
#==============================================================================
module MainWindow
#--------------------------------------------------------------------------
# ● 部分Windows消息定义
#--------------------------------------------------------------------------
WM_CREATE = 0x0001
WM_DESTROY = 0x0002
WM_MOVE = 0x0003
WM_SIZE = 0x0005
WM_ACTIVATE = 0x0006
WM_ACTIVATEAPP = 0x001C
WM_GETTEXT = 0x000D
WM_GETTEXTLENGTH = 0x000E
WM_PAINT = 0x000F
WM_CLOSE = 0x0010
WM_QUERYENDSESSION = 0x0011
WM_QUIT = 0x0012
WM_KEYDOWN = 0x0100
WM_KEYUP = 0x0101
WM_CHAR = 0x0102
WM_SYSKEYDOWN = 0x0104
WM_SYSKEYUP = 0x0105
WM_SYSCHAR = 0x0106
WM_COMMAND = 0x0111
WM_SYSCOMMAND = 0x0112
WM_TIMER = 0x0113
WM_MOUSEMOVE = 0x0200
WM_LBUTTONDOWN = 0x0201
WM_LBUTTONUP = 0x0202
WM_LBUTTONDBLCLK = 0x0203
WM_RBUTTONDOWN = 0x0204
WM_RBUTTONUP = 0x0205
WM_RBUTTONDBLCLK = 0x0206
WM_MBUTTONDOWN = 0x0207
WM_MBUTTONUP = 0x0208
WM_MBUTTONDBLCLK = 0x0209
WM_MOUSEWHEEL = 0x020A
RM_F1MENU_OPEN = 0x0112
RM_F1MENU_CLOSE = 0x0125
#--------------------------------------------------------------------------
# ● 其他常量定义
#--------------------------------------------------------------------------
WA_INACTIVE = 0
WA_ACTIVE = 1
WA_CLICKACTIVE = 2
#--------------------------------------------------------------------------
# ●
#--------------------------------------------------------------------------
@@ShowCursor = :"user32|ShowCursor|i|l".to_api
@@handle = false # 禁用默认窗口过程
@@procs = {}
@@child_procs = {}
@@child_callback = {}
@@child_def_procs = {}
#--------------------------------------------------------------------------
# ● 窗口过程函数 ※ 该名字切勿更改
#--------------------------------------------------------------------------
def self.wnd_proc(hwnd,msg,wparam,lparam)
# 消息分歧
case msg
when WM_CREATE
when WM_MOVE
when WM_ACTIVATEAPP
else
end
# 調用其他外插的視窗訊息
if !@@procs.empty?
@@procs.each_value do |i|
begin
i.call(hwnd,msg,wparam,lparam)
rescue
end
end
end
# 调用默认窗口过程
self.use_rm_proc(hwnd,msg,wparam,lparam)
end
#--------------------------------------------------------------------------
# ●
#--------------------------------------------------------------------------
def self.add_proc(symbol, method)
@@procs[symbol] = method
end
#--------------------------------------------------------------------------
# ●
#--------------------------------------------------------------------------
def self.remove_proc(symbol)
@@procs.delete(symbol)
end
#--------------------------------------------------------------------------
# ●
#--------------------------------------------------------------------------
def self.use_rm_proc(hwnd, msg, wp, lp)
return :"user32|CallWindowProc|iiiii|i".apicall(@@oHandle, hwnd, msg, wp, lp) if !@@handle
end
#--------------------------------------------------------------------------
# ●
#--------------------------------------------------------------------------
def self.disable_rm_proc
@@handle = true
end
#--------------------------------------------------------------------------
# ●
#--------------------------------------------------------------------------
def self.enable_rm_proc
@@handle = false
end
#--------------------------------------------------------------------------
# ●
#--------------------------------------------------------------------------
def self.child_def_proc(symbol, hwnd, msg, wp, lp)
return :"user32|CallWindowProc|iiiii|i".apicall(@@child_def_procs[hwnd], hwnd, msg, wp, lp)
end
#--------------------------------------------------------------------------
# ● ??? ※ 该名字切勿更改
#--------------------------------------------------------------------------
def self.child_wnd_proc(symbol, hwnd, msg, wparam, lparam)
begin
@@child_procs[symbol].call(hwnd,msg,wparam,lparam)
rescue
end
end
#--------------------------------------------------------------------------
# ●
#--------------------------------------------------------------------------
def self.disableChildWndProc(hwnd)
:"user32|SetWindowLong|iii|i".apicall(hwnd, -4, @@child_def_procs[hwnd])
@@child_def_procs.delete(hwnd)
:"msvcrt|free|i|i".apicall(@@child_callback[hwnd])
@@child_callback.delete(hwnd)
@@child_procs.delete(hwnd)
end
#--------------------------------------------------------------------------
# ●
#--------------------------------------------------------------------------
def self.enableChildWndProc(hwnd, proc)
@@child_procs[hwnd] = proc
@malloc = :"msvcrt|malloc|i|i"
@memcpy = :"msvcrt|memcpy|ipi|v"
sprintf = self.findProc("msvcrt", "sprintf")
rgsseval = self.findProc("RGSS300", "RGSSGetInt")
oHandle = :"user32|GetWindowLong|ll|l".apicall(hwnd, -4)
buf = @malloc.apicall(1024)
fmt = @malloc.apicall(2048)
sprintfvar = @malloc.apicall(8)
rgssevalvar= @malloc.apicall(8)
oldvar = @malloc.apicall(8)
fmtvar = @malloc.apicall(8)
bufvar = @malloc.apicall(8)
defvar = @malloc.apicall(8)
@@child_def_procs[hwnd] = oHandle
:"msvcrt|strcpy|pp|p".apicall(fmt, "MainWindow.child_wnd_proc(#{hwnd},%d,%d,%d,%d)")
@memcpy.apicall(sprintfvar, [sprintf].pack("i"), 4)
@memcpy.apicall(rgssevalvar,[rgsseval].pack("i"), 4)
@memcpy.apicall(oldvar, [@@oHandle].pack("i"), 4)
@memcpy.apicall(fmtvar, [fmt].pack("i"), 4)
@memcpy.apicall(bufvar, [buf].pack("i"), 4)
@memcpy.apicall(defvar, [oHandle].pack("i"), 4)
code = [0x55,0x89,0xe5,0xff,0x75,0x14,
0xff,0x75,0x10,0xff,0x75,0x0c,
0xff,0x75,0x08,0xff,0x35].pack('C*')
code << [fmtvar].pack('l') << [0xff, 0x35].pack('C*')
code << [bufvar].pack('l') << [0xff, 0x15].pack('C*')
code << [sprintfvar].pack("l")
code << [0xff, 0x15].pack('C*')
code << [rgssevalvar].pack("l")
code << [0x83,0xc4,0x18].pack('C*')
code << [0xc9,0xc2,0x10,0x00].pack('C*')
#0xD1, 0xE8
shellcode = @malloc.apicall(2048)
@memcpy.apicall(shellcode, code, code.size)
:"user32|SetWindowLong|iii|i".apicall(hwnd, -4, shellcode)
@@child_callback[hwnd] = shellcode
end
#--------------------------------------------------------------------------
# ●
#--------------------------------------------------------------------------
def self.enable
MainWindow.instance_eval do
# 清空 enable 方法(避免重複呼叫)
def self.enable
end
# 取得 HWND
@msg = "\0" * 24
@hwnd = 0
while @hwnd == 0
:"user32|GetMessage|piii|v".apicall(@msg, 0, 0, 0)
@kmsg = @msg
:"user32|TranslateMessage|p|v".apicall(@kmsg)
:"user32|DispatchMessage|p|v".apicall(@kmsg)
@hwnd = @msg.unpack("i*")[0]
end
@hdc = :"user32|GetDC|i|i".apicall(@hwnd)
# 方法:取得HWND
def self.hwnd
return @hwnd
end
# 方法:取得HDC
def self.hdc
return @hdc
end
# 方法:取得HWNDProc
def self.findProc(l, n)
lib = :"kernel32|LoadLibrary|p|i".apicall(l)
ret = :"kernel32|GetProcAddress|ip|l".apicall(lib, n)
:"kernel32|FreeLibrary|l|v".apicall(lib)
return ret
end
# 方法:Hook HWNDProc
def self.enableWndProc
# 清空 enableWndProc 方法(避免重複呼叫)
MainWindow.instance_eval do
def self.enableWndProc
end
end
@malloc = :"msvcrt|malloc|i|i"
@memcpy = :"msvcrt|memcpy|ipi|v"
sprintf = self.findProc("msvcrt", "sprintf")
rgsseval = self.findProc("RGSS300", "RGSSGetInt")
@@oHandle = :"user32|GetWindowLong|ll|l".apicall(@hwnd, -4)
buf = @malloc.apicall(1024)
fmt = @malloc.apicall(2048)
sprintfvar = @malloc.apicall(8)
rgssevalvar= @malloc.apicall(8)
oldvar = @malloc.apicall(8)
fmtvar = @malloc.apicall(8)
bufvar = @malloc.apicall(8)
defvar = @malloc.apicall(8)
:"msvcrt|strcpy|pp|p".apicall(fmt, "MainWindow.wnd_proc(%d,%d,%d,%d)")
@memcpy.apicall(sprintfvar, [sprintf].pack("i"), 4)
@memcpy.apicall(rgssevalvar,[rgsseval].pack("i"), 4)
@memcpy.apicall(oldvar, [@@oHandle].pack("i"), 4)
@memcpy.apicall(fmtvar, [fmt].pack("i"), 4)
@memcpy.apicall(bufvar, [buf].pack("i"), 4)
@memcpy.apicall(defvar, [self.findProc("user32", "DefWindowProcA")].pack("i"), 4)
@code= [0x55,0x89,0xe5,0xff,0x75,0x14,
0xff,0x75,0x10,0xff,0x75,0x0c,
0xff,0x75,0x08,0xff,0x35].pack('C*')
@code<< [fmtvar].pack('l') << [0xff, 0x35].pack('C*')
@code<< [bufvar].pack('l') << [0xff, 0x15].pack('C*')
@code<< [sprintfvar].pack("l")
@code<< [0xff, 0x15].pack('C*')
@code<< [rgssevalvar].pack("l")
@code<< [0x83,0xc4,0x18].pack('C*')
@code<< [0xc9,0xc2,0x10,0x00].pack('C*')
#0xD1, 0xE8
@shellcode = @malloc.apicall(2048)
@memcpy.apicall(@shellcode, @code, @code.size)
:"user32|SetWindowLong|iii|i".apicall(@hwnd, -4, @shellcode)
end
end
end
end
MainWindow.enable
MainWindow.enableWndProc
#encoding:utf-8
# 纯脚本不使用DLL就读取窗口消息
# By 晴兰 form 66RPG
# 功能擴充 By AAM@_@
#==============================================================================
# ■ MainWindow
#------------------------------------------------------------------------------
# 。
#==============================================================================
module MainWindow
#--------------------------------------------------------------------------
# ● 部分Windows消息定义
#--------------------------------------------------------------------------
WM_CREATE = 0x0001
WM_DESTROY = 0x0002
WM_MOVE = 0x0003
WM_SIZE = 0x0005
WM_ACTIVATE = 0x0006
WM_ACTIVATEAPP = 0x001C
WM_GETTEXT = 0x000D
WM_GETTEXTLENGTH = 0x000E
WM_PAINT = 0x000F
WM_CLOSE = 0x0010
WM_QUERYENDSESSION = 0x0011
WM_QUIT = 0x0012
WM_KEYDOWN = 0x0100
WM_KEYUP = 0x0101
WM_CHAR = 0x0102
WM_SYSKEYDOWN = 0x0104
WM_SYSKEYUP = 0x0105
WM_SYSCHAR = 0x0106
WM_COMMAND = 0x0111
WM_SYSCOMMAND = 0x0112
WM_TIMER = 0x0113
WM_MOUSEMOVE = 0x0200
WM_LBUTTONDOWN = 0x0201
WM_LBUTTONUP = 0x0202
WM_LBUTTONDBLCLK = 0x0203
WM_RBUTTONDOWN = 0x0204
WM_RBUTTONUP = 0x0205
WM_RBUTTONDBLCLK = 0x0206
WM_MBUTTONDOWN = 0x0207
WM_MBUTTONUP = 0x0208
WM_MBUTTONDBLCLK = 0x0209
WM_MOUSEWHEEL = 0x020A
RM_F1MENU_OPEN = 0x0112
RM_F1MENU_CLOSE = 0x0125
#--------------------------------------------------------------------------
# ● 其他常量定义
#--------------------------------------------------------------------------
WA_INACTIVE = 0
WA_ACTIVE = 1
WA_CLICKACTIVE = 2
#--------------------------------------------------------------------------
# ●
#--------------------------------------------------------------------------
@@ShowCursor = :"user32|ShowCursor|i|l".to_api
@@handle = false # 禁用默认窗口过程
@@procs = {}
@@child_procs = {}
@@child_callback = {}
@@child_def_procs = {}
#--------------------------------------------------------------------------
# ● 窗口过程函数 ※ 该名字切勿更改
#--------------------------------------------------------------------------
def self.wnd_proc(hwnd,msg,wparam,lparam)
# 消息分歧
case msg
when WM_CREATE
when WM_MOVE
when WM_ACTIVATEAPP
else
end
# 調用其他外插的視窗訊息
if !@@procs.empty?
@@procs.each_value do |i|
begin
i.call(hwnd,msg,wparam,lparam)
rescue
end
end
end
# 调用默认窗口过程
self.use_rm_proc(hwnd,msg,wparam,lparam)
end
#--------------------------------------------------------------------------
# ●
#--------------------------------------------------------------------------
def self.add_proc(symbol, method)
@@procs[symbol] = method
end
#--------------------------------------------------------------------------
# ●
#--------------------------------------------------------------------------
def self.remove_proc(symbol)
@@procs.delete(symbol)
end
#--------------------------------------------------------------------------
# ●
#--------------------------------------------------------------------------
def self.use_rm_proc(hwnd, msg, wp, lp)
return :"user32|CallWindowProc|iiiii|i".apicall(@@oHandle, hwnd, msg, wp, lp) if !@@handle
end
#--------------------------------------------------------------------------
# ●
#--------------------------------------------------------------------------
def self.disable_rm_proc
@@handle = true
end
#--------------------------------------------------------------------------
# ●
#--------------------------------------------------------------------------
def self.enable_rm_proc
@@handle = false
end
#--------------------------------------------------------------------------
# ●
#--------------------------------------------------------------------------
def self.child_def_proc(symbol, hwnd, msg, wp, lp)
return :"user32|CallWindowProc|iiiii|i".apicall(@@child_def_procs[hwnd], hwnd, msg, wp, lp)
end
#--------------------------------------------------------------------------
# ● ??? ※ 该名字切勿更改
#--------------------------------------------------------------------------
def self.child_wnd_proc(symbol, hwnd, msg, wparam, lparam)
begin
@@child_procs[symbol].call(hwnd,msg,wparam,lparam)
rescue
end
end
#--------------------------------------------------------------------------
# ●
#--------------------------------------------------------------------------
def self.disableChildWndProc(hwnd)
:"user32|SetWindowLong|iii|i".apicall(hwnd, -4, @@child_def_procs[hwnd])
@@child_def_procs.delete(hwnd)
:"msvcrt|free|i|i".apicall(@@child_callback[hwnd])
@@child_callback.delete(hwnd)
@@child_procs.delete(hwnd)
end
#--------------------------------------------------------------------------
# ●
#--------------------------------------------------------------------------
def self.enableChildWndProc(hwnd, proc)
@@child_procs[hwnd] = proc
@malloc = :"msvcrt|malloc|i|i"
@memcpy = :"msvcrt|memcpy|ipi|v"
sprintf = self.findProc("msvcrt", "sprintf")
rgsseval = self.findProc("RGSS300", "RGSSGetInt")
oHandle = :"user32|GetWindowLong|ll|l".apicall(hwnd, -4)
buf = @malloc.apicall(1024)
fmt = @malloc.apicall(2048)
sprintfvar = @malloc.apicall(8)
rgssevalvar= @malloc.apicall(8)
oldvar = @malloc.apicall(8)
fmtvar = @malloc.apicall(8)
bufvar = @malloc.apicall(8)
defvar = @malloc.apicall(8)
@@child_def_procs[hwnd] = oHandle
:"msvcrt|strcpy|pp|p".apicall(fmt, "MainWindow.child_wnd_proc(#{hwnd},%d,%d,%d,%d)")
@memcpy.apicall(sprintfvar, [sprintf].pack("i"), 4)
@memcpy.apicall(rgssevalvar,[rgsseval].pack("i"), 4)
@memcpy.apicall(oldvar, [@@oHandle].pack("i"), 4)
@memcpy.apicall(fmtvar, [fmt].pack("i"), 4)
@memcpy.apicall(bufvar, [buf].pack("i"), 4)
@memcpy.apicall(defvar, [oHandle].pack("i"), 4)
code = [0x55,0x89,0xe5,0xff,0x75,0x14,
0xff,0x75,0x10,0xff,0x75,0x0c,
0xff,0x75,0x08,0xff,0x35].pack('C*')
code << [fmtvar].pack('l') << [0xff, 0x35].pack('C*')
code << [bufvar].pack('l') << [0xff, 0x15].pack('C*')
code << [sprintfvar].pack("l")
code << [0xff, 0x15].pack('C*')
code << [rgssevalvar].pack("l")
code << [0x83,0xc4,0x18].pack('C*')
code << [0xc9,0xc2,0x10,0x00].pack('C*')
#0xD1, 0xE8
shellcode = @malloc.apicall(2048)
@memcpy.apicall(shellcode, code, code.size)
:"user32|SetWindowLong|iii|i".apicall(hwnd, -4, shellcode)
@@child_callback[hwnd] = shellcode
end
#--------------------------------------------------------------------------
# ●
#--------------------------------------------------------------------------
def self.enable
MainWindow.instance_eval do
# 清空 enable 方法(避免重複呼叫)
def self.enable
end
# 取得 HWND
@msg = "\0" * 24
@hwnd = 0
while @hwnd == 0
:"user32|GetMessage|piii|v".apicall(@msg, 0, 0, 0)
@kmsg = @msg
:"user32|TranslateMessage|p|v".apicall(@kmsg)
:"user32|DispatchMessage|p|v".apicall(@kmsg)
@hwnd = @msg.unpack("i*")[0]
end
@hdc = :"user32|GetDC|i|i".apicall(@hwnd)
# 方法:取得HWND
def self.hwnd
return @hwnd
end
# 方法:取得HDC
def self.hdc
return @hdc
end
# 方法:取得HWNDProc
def self.findProc(l, n)
lib = :"kernel32|LoadLibrary|p|i".apicall(l)
ret = :"kernel32|GetProcAddress|ip|l".apicall(lib, n)
:"kernel32|FreeLibrary|l|v".apicall(lib)
return ret
end
# 方法:Hook HWNDProc
def self.enableWndProc
# 清空 enableWndProc 方法(避免重複呼叫)
MainWindow.instance_eval do
def self.enableWndProc
end
end
@malloc = :"msvcrt|malloc|i|i"
@memcpy = :"msvcrt|memcpy|ipi|v"
sprintf = self.findProc("msvcrt", "sprintf")
rgsseval = self.findProc("RGSS300", "RGSSGetInt")
@@oHandle = :"user32|GetWindowLong|ll|l".apicall(@hwnd, -4)
buf = @malloc.apicall(1024)
fmt = @malloc.apicall(2048)
sprintfvar = @malloc.apicall(8)
rgssevalvar= @malloc.apicall(8)
oldvar = @malloc.apicall(8)
fmtvar = @malloc.apicall(8)
bufvar = @malloc.apicall(8)
defvar = @malloc.apicall(8)
:"msvcrt|strcpy|pp|p".apicall(fmt, "MainWindow.wnd_proc(%d,%d,%d,%d)")
@memcpy.apicall(sprintfvar, [sprintf].pack("i"), 4)
@memcpy.apicall(rgssevalvar,[rgsseval].pack("i"), 4)
@memcpy.apicall(oldvar, [@@oHandle].pack("i"), 4)
@memcpy.apicall(fmtvar, [fmt].pack("i"), 4)
@memcpy.apicall(bufvar, [buf].pack("i"), 4)
@memcpy.apicall(defvar, [self.findProc("user32", "DefWindowProcA")].pack("i"), 4)
@code= [0x55,0x89,0xe5,0xff,0x75,0x14,
0xff,0x75,0x10,0xff,0x75,0x0c,
0xff,0x75,0x08,0xff,0x35].pack('C*')
@code<< [fmtvar].pack('l') << [0xff, 0x35].pack('C*')
@code<< [bufvar].pack('l') << [0xff, 0x15].pack('C*')
@code<< [sprintfvar].pack("l")
@code<< [0xff, 0x15].pack('C*')
@code<< [rgssevalvar].pack("l")
@code<< [0x83,0xc4,0x18].pack('C*')
@code<< [0xc9,0xc2,0x10,0x00].pack('C*')
#0xD1, 0xE8
@shellcode = @malloc.apicall(2048)
@memcpy.apicall(@shellcode, @code, @code.size)
:"user32|SetWindowLong|iii|i".apicall(@hwnd, -4, @shellcode)
end
end
end
end
MainWindow.enable
MainWindow.enableWndProc
文字编码
#encoding:utf-8
#==============================================================================
# ■ String
#------------------------------------------------------------------------------
# 字符串类。可处理任意长度的字节串。 (追加编码转换的定义)
#==============================================================================
class String
#--------------------------------------------------------------------------
# ●
#--------------------------------------------------------------------------
CP_ACP = 0
CP_UTF8 = 65001
CP_UTF16 = 1200
#--------------------------------------------------------------------------
# ●
#--------------------------------------------------------------------------
def u2s
m2w = :"kernel32|MultiByteToWideChar|ilpipi|i".to_api
w2m = :"kernel32|WideCharToMultiByte|ilpipipp|i".to_api
len = m2w.call(CP_UTF8, 0, self, -1, nil, 0)
buf = "\0" * (len*2)
m2w.call(CP_UTF8, 0, self, -1, buf, buf.size/2)
len = w2m.call(CP_ACP, 0, buf, -1, nil, 0, nil, nil)
ret = "\0" * len
w2m.call(CP_ACP, 0, buf, -1, ret, ret.size, nil, nil)
return ret
end
#--------------------------------------------------------------------------
# ●
#--------------------------------------------------------------------------
def s2u
m2w = :"kernel32|MultiByteToWideChar|ilpipi|i".to_api
w2m = :"kernel32|WideCharToMultiByte|ilpipipp|i".to_api
len = m2w.call(CP_ACP, 0, self, -1, nil, 0);
buf = "\0" * (len*2)
m2w.call(CP_ACP, 0, self, -1, buf, buf.size/2);
len = w2m.call(CP_UTF8, 0, buf, -1, nil, 0, nil, nil);
ret = "\0" * len
w2m.call(CP_UTF8, 0, buf, -1, ret, ret.size, nil, nil);
return ret
end
#--------------------------------------------------------------------------
# ●
#--------------------------------------------------------------------------
def u2w
m2w = :"kernel32|MultiByteToWideChar|ilpipi|i".to_api
len = m2w.call(CP_UTF8, 0, self, -1, nil, 0)
buf = "\0" * (len*2)
m2w.call(CP_UTF8, 0, self, -1, buf, len)
return buf
end
#--------------------------------------------------------------------------
# ●
#--------------------------------------------------------------------------
def w2u
w2m = :"kernel32|WideCharToMultiByte|ilpipipp|i".to_api
len = w2m.call(CP_UTF8, 0, self, -1, nil, 0, nil, nil)
buf = "\0" * len
w2m.call(CP_UTF8, 0, self, -1, buf, len, nil, nil)
return buf
end
#--------------------------------------------------------------------------
# ●
#--------------------------------------------------------------------------
def s2u!
self[0, length] = s2u
end
#--------------------------------------------------------------------------
# ●
#--------------------------------------------------------------------------
def u2s!
self[0, length] = u2s
end
#--------------------------------------------------------------------------
# ●
#--------------------------------------------------------------------------
def u2w!
self[0, length] = u2u16
end
#--------------------------------------------------------------------------
# ●
#--------------------------------------------------------------------------
def w2u!
self[0, length] = u162u
end
end
#encoding:utf-8
#==============================================================================
# ■ String
#------------------------------------------------------------------------------
# 字符串类。可处理任意长度的字节串。 (追加编码转换的定义)
#==============================================================================
class String
#--------------------------------------------------------------------------
# ●
#--------------------------------------------------------------------------
CP_ACP = 0
CP_UTF8 = 65001
CP_UTF16 = 1200
#--------------------------------------------------------------------------
# ●
#--------------------------------------------------------------------------
def u2s
m2w = :"kernel32|MultiByteToWideChar|ilpipi|i".to_api
w2m = :"kernel32|WideCharToMultiByte|ilpipipp|i".to_api
len = m2w.call(CP_UTF8, 0, self, -1, nil, 0)
buf = "\0" * (len*2)
m2w.call(CP_UTF8, 0, self, -1, buf, buf.size/2)
len = w2m.call(CP_ACP, 0, buf, -1, nil, 0, nil, nil)
ret = "\0" * len
w2m.call(CP_ACP, 0, buf, -1, ret, ret.size, nil, nil)
return ret
end
#--------------------------------------------------------------------------
# ●
#--------------------------------------------------------------------------
def s2u
m2w = :"kernel32|MultiByteToWideChar|ilpipi|i".to_api
w2m = :"kernel32|WideCharToMultiByte|ilpipipp|i".to_api
len = m2w.call(CP_ACP, 0, self, -1, nil, 0);
buf = "\0" * (len*2)
m2w.call(CP_ACP, 0, self, -1, buf, buf.size/2);
len = w2m.call(CP_UTF8, 0, buf, -1, nil, 0, nil, nil);
ret = "\0" * len
w2m.call(CP_UTF8, 0, buf, -1, ret, ret.size, nil, nil);
return ret
end
#--------------------------------------------------------------------------
# ●
#--------------------------------------------------------------------------
def u2w
m2w = :"kernel32|MultiByteToWideChar|ilpipi|i".to_api
len = m2w.call(CP_UTF8, 0, self, -1, nil, 0)
buf = "\0" * (len*2)
m2w.call(CP_UTF8, 0, self, -1, buf, len)
return buf
end
#--------------------------------------------------------------------------
# ●
#--------------------------------------------------------------------------
def w2u
w2m = :"kernel32|WideCharToMultiByte|ilpipipp|i".to_api
len = w2m.call(CP_UTF8, 0, self, -1, nil, 0, nil, nil)
buf = "\0" * len
w2m.call(CP_UTF8, 0, self, -1, buf, len, nil, nil)
return buf
end
#--------------------------------------------------------------------------
# ●
#--------------------------------------------------------------------------
def s2u!
self[0, length] = s2u
end
#--------------------------------------------------------------------------
# ●
#--------------------------------------------------------------------------
def u2s!
self[0, length] = u2s
end
#--------------------------------------------------------------------------
# ●
#--------------------------------------------------------------------------
def u2w!
self[0, length] = u2u16
end
#--------------------------------------------------------------------------
# ●
#--------------------------------------------------------------------------
def w2u!
self[0, length] = u162u
end
end
主要负责处理文字框的 TextBox
#==============================================================================
# ■ TextBox By AAM@_@
#------------------------------------------------------------------------------
# 输入框的类。
#==============================================================================
class TextBox
#--------------------------------------------------------------------------
# ● 设置API
#--------------------------------------------------------------------------
@@CreateWindow = :"user32|CreateWindowEx|lpplllllllll|l".to_api
@@ShowWindow = :"user32|ShowWindow|ll|l".to_api
@@DestroyWindow = :"user32|DestroyWindow|l|l".to_api
@@SetWindowPos = :"user32|SetWindowPos|lllllll|l".to_api
@@GetWindowRect = :"user32|GetWindowRect|ll|l".to_api
@@GetWindowText = :"user32|GetWindowText|lpl|l".to_api
@@GetWindowTextLength = :"user32|GetWindowTextLength|l|l".to_api
@@SetWindowText = :"user32|SetWindowText|lp|l".to_api
@@UpdateWindow = :"user32|UpdateWindow|l|i".to_api
@@SetFocus = :"user32|SetFocus|l|l".to_api
@@SendMessage = :"user32|SendMessage|llll|l".to_api
@@SendMessage_Pos = :"user32|SendMessage|llpp|l".to_api
@@CreateFont = :"gdi32|CreateFont|lllllllllllllp|l".to_api
#--------------------------------------------------------------------------
# ● 定义实例变量
#--------------------------------------------------------------------------
attr_accessor :focus
attr_reader :font_name
attr_reader :font_size
attr_reader :password
#--------------------------------------------------------------------------
# ●
#--------------------------------------------------------------------------
def default_font_name
return Font.default_name if Font.default_name.is_a?(String)
for i in Font.default_name
return i if Font.exist?(i)
end
return ""
end
#--------------------------------------------------------------------------
# ●
#--------------------------------------------------------------------------
def font_name=(f)
@font_name = f
update_font
end
#--------------------------------------------------------------------------
# ●
#--------------------------------------------------------------------------
def font_size=(s)
@font_size = s * 0.9
update_font
# Fix window height
rect = "\0" * 16
@@GetWindowRect.call(@window, rect)
rect = rect.unpack("l*")
@@SetWindowPos.call(@window, 0, rect[0], rect[1], @width, @font_size, 0)
end
#--------------------------------------------------------------------------
# ●
#--------------------------------------------------------------------------
def update_font
hFont = @@CreateFont.call(@font_size,@font_size/2,0,0,0,0,0,0,0,0,0,0,0,@font_name.u2s)
@@SendMessage.call(@window, 0x30, hFont, 0) # WM_SETFONT
end
#--------------------------------------------------------------------------
# ● 初始化
#--------------------------------------------------------------------------
def initialize(text = "", limit = 8, password = false, width = 160, direct_show = false, font_name = default_font_name, font_size = Font.default_size)
@password = password
@width = width
@direct_show = direct_show
@font_name = font_name
@font_size = font_size * 0.9
c = 0x40000000
c |= 0x00000020 if password # ES_PASSWORD
@window=@@CreateWindow.call(0, 'EDIT', text.u2s, c, 0, 0, @width, @font_size, MainWindow.hwnd, 0, 0, 0)
if @direct_show
mc = :"user32|GetWindowLong|ll|l".apicall(MainWindow.hwnd, -16) # GWL_STYLE
mc |= 0x02000000 # WS_CLIPCHILDREN
:"user32|SetWindowLong|lll|l".apicall(MainWindow.hwnd, -16, mc) # GWL_STYLE
end
@@ShowWindow.call(@window, 5) if @direct_show
@@SendMessage.call(@window, 0xC5, limit, 0) # WM_SETLIMITTEXT
update_font
MainWindow.enableChildWndProc(@window, method(:wnd_proc))
@enter_pressed = false
@focus = true
@disposed = false
end
#--------------------------------------------------------------------------
# ● 窗口过程函数
#--------------------------------------------------------------------------
def wnd_proc(hwnd, msg, wp, lp)
if hwnd == @window&&msg == MainWindow::WM_CHAR and wp == 0x0D # Enter
@enter_pressed = true
end
MainWindow.child_def_proc(@window, hwnd, msg, wp, lp)
end
#--------------------------------------------------------------------------
# ● 释放
#--------------------------------------------------------------------------
def dispose
@disposed = true
MainWindow.disableChildWndProc(@window)
@@DestroyWindow.call(@window)
end
#--------------------------------------------------------------------------
# ● 刷新
#--------------------------------------------------------------------------
def update
return if !@focus or @disposed
if @direct_show
@@UpdateWindow.call(@window)
else
@@SendMessage.call(@window, 0xB1, sel_spos, sel_epos)
end
@@SetFocus.call(@window)
end
#--------------------------------------------------------------------------
# ●
#--------------------------------------------------------------------------
def set_pos(x, y)
@@SetWindowPos.call(@window, 0, x, y, @width, @font_size, 0)
end
#--------------------------------------------------------------------------
# ● 获取内容
#--------------------------------------------------------------------------
def text
return if @disposed
l = @@GetWindowTextLength.call(@window) + 1
str = "\0" * l
@@GetWindowText.call(@window, str, l)
return str.s2u.strip!
end
#--------------------------------------------------------------------------
# ● 更改内容
#--------------------------------------------------------------------------
def text=(str)
return if @disposed
@@SetWindowText.call(@window, str.u2s)
self.sel_pos = str.u2s.size - 1
str
end
#--------------------------------------------------------------------------
# ● 获取起始光标位置
#--------------------------------------------------------------------------
def sel_spos
return if @disposed
#return @@SendMessage.call(@window, 0xB0, 0, 0) & 0xFFFF
spos = "\0" * 4
@@SendMessage_Pos.call(@window, 0xB0, spos, 0)
return spos.unpack("l")[0]
end
#--------------------------------------------------------------------------
# ● 获取結束光标位置
#--------------------------------------------------------------------------
def sel_epos
return if @disposed
#return @@SendMessage.call(@window, 0xB0, 0, 0) >> 16
epos = "\0" * 4
@@SendMessage_Pos.call(@window, 0xB0, 0, epos)
return epos.unpack("l")[0]
end
#--------------------------------------------------------------------------
# ● 设置光标位置
#--------------------------------------------------------------------------
def sel_spos=(i)
return if @disposed
@@SendMessage.call(@window, 0xB1, i, sel_epos)
end
#--------------------------------------------------------------------------
# ● 设置光标位置
#--------------------------------------------------------------------------
def sel_epos=(i)
return if @disposed
@@SendMessage.call(@window, 0xB1, sel_spos, i)
end
#--------------------------------------------------------------------------
# ● 设置光标位置
#--------------------------------------------------------------------------
def sel_pos=(i)
return if @disposed
@@SendMessage.call(@window, 0xB1, i, i)
end
#--------------------------------------------------------------------------
# ● 获取字數限制
#--------------------------------------------------------------------------
def limit
return if @disposed
return @@SendMessage.call(@window, 0xD5, 0, 0)
end
#--------------------------------------------------------------------------
# ● 设置字數限制
#--------------------------------------------------------------------------
def limit=(i)
return if @disposed
@@SendMessage.call(@window, 0xC5, i, 0)
end
#--------------------------------------------------------------------------
# ● 是否按下回车键(0x0D => Enter, 0x1B => ESC)
#--------------------------------------------------------------------------
def press_enter?
return !(@enter_pressed = false) if @enter_pressed
return false
end
end
#==============================================================================
# ■ TextBox By AAM@_@
#------------------------------------------------------------------------------
# 输入框的类。
#==============================================================================
class TextBox
#--------------------------------------------------------------------------
# ● 设置API
#--------------------------------------------------------------------------
@@CreateWindow = :"user32|CreateWindowEx|lpplllllllll|l".to_api
@@ShowWindow = :"user32|ShowWindow|ll|l".to_api
@@DestroyWindow = :"user32|DestroyWindow|l|l".to_api
@@SetWindowPos = :"user32|SetWindowPos|lllllll|l".to_api
@@GetWindowRect = :"user32|GetWindowRect|ll|l".to_api
@@GetWindowText = :"user32|GetWindowText|lpl|l".to_api
@@GetWindowTextLength = :"user32|GetWindowTextLength|l|l".to_api
@@SetWindowText = :"user32|SetWindowText|lp|l".to_api
@@UpdateWindow = :"user32|UpdateWindow|l|i".to_api
@@SetFocus = :"user32|SetFocus|l|l".to_api
@@SendMessage = :"user32|SendMessage|llll|l".to_api
@@SendMessage_Pos = :"user32|SendMessage|llpp|l".to_api
@@CreateFont = :"gdi32|CreateFont|lllllllllllllp|l".to_api
#--------------------------------------------------------------------------
# ● 定义实例变量
#--------------------------------------------------------------------------
attr_accessor :focus
attr_reader :font_name
attr_reader :font_size
attr_reader :password
#--------------------------------------------------------------------------
# ●
#--------------------------------------------------------------------------
def default_font_name
return Font.default_name if Font.default_name.is_a?(String)
for i in Font.default_name
return i if Font.exist?(i)
end
return ""
end
#--------------------------------------------------------------------------
# ●
#--------------------------------------------------------------------------
def font_name=(f)
@font_name = f
update_font
end
#--------------------------------------------------------------------------
# ●
#--------------------------------------------------------------------------
def font_size=(s)
@font_size = s * 0.9
update_font
# Fix window height
rect = "\0" * 16
@@GetWindowRect.call(@window, rect)
rect = rect.unpack("l*")
@@SetWindowPos.call(@window, 0, rect[0], rect[1], @width, @font_size, 0)
end
#--------------------------------------------------------------------------
# ●
#--------------------------------------------------------------------------
def update_font
hFont = @@CreateFont.call(@font_size,@font_size/2,0,0,0,0,0,0,0,0,0,0,0,@font_name.u2s)
@@SendMessage.call(@window, 0x30, hFont, 0) # WM_SETFONT
end
#--------------------------------------------------------------------------
# ● 初始化
#--------------------------------------------------------------------------
def initialize(text = "", limit = 8, password = false, width = 160, direct_show = false, font_name = default_font_name, font_size = Font.default_size)
@password = password
@width = width
@direct_show = direct_show
@font_name = font_name
@font_size = font_size * 0.9
c = 0x40000000
c |= 0x00000020 if password # ES_PASSWORD
@window=@@CreateWindow.call(0, 'EDIT', text.u2s, c, 0, 0, @width, @font_size, MainWindow.hwnd, 0, 0, 0)
if @direct_show
mc = :"user32|GetWindowLong|ll|l".apicall(MainWindow.hwnd, -16) # GWL_STYLE
mc |= 0x02000000 # WS_CLIPCHILDREN
:"user32|SetWindowLong|lll|l".apicall(MainWindow.hwnd, -16, mc) # GWL_STYLE
end
@@ShowWindow.call(@window, 5) if @direct_show
@@SendMessage.call(@window, 0xC5, limit, 0) # WM_SETLIMITTEXT
update_font
MainWindow.enableChildWndProc(@window, method(:wnd_proc))
@enter_pressed = false
@focus = true
@disposed = false
end
#--------------------------------------------------------------------------
# ● 窗口过程函数
#--------------------------------------------------------------------------
def wnd_proc(hwnd, msg, wp, lp)
if hwnd == @window&&msg == MainWindow::WM_CHAR and wp == 0x0D # Enter
@enter_pressed = true
end
MainWindow.child_def_proc(@window, hwnd, msg, wp, lp)
end
#--------------------------------------------------------------------------
# ● 释放
#--------------------------------------------------------------------------
def dispose
@disposed = true
MainWindow.disableChildWndProc(@window)
@@DestroyWindow.call(@window)
end
#--------------------------------------------------------------------------
# ● 刷新
#--------------------------------------------------------------------------
def update
return if !@focus or @disposed
if @direct_show
@@UpdateWindow.call(@window)
else
@@SendMessage.call(@window, 0xB1, sel_spos, sel_epos)
end
@@SetFocus.call(@window)
end
#--------------------------------------------------------------------------
# ●
#--------------------------------------------------------------------------
def set_pos(x, y)
@@SetWindowPos.call(@window, 0, x, y, @width, @font_size, 0)
end
#--------------------------------------------------------------------------
# ● 获取内容
#--------------------------------------------------------------------------
def text
return if @disposed
l = @@GetWindowTextLength.call(@window) + 1
str = "\0" * l
@@GetWindowText.call(@window, str, l)
return str.s2u.strip!
end
#--------------------------------------------------------------------------
# ● 更改内容
#--------------------------------------------------------------------------
def text=(str)
return if @disposed
@@SetWindowText.call(@window, str.u2s)
self.sel_pos = str.u2s.size - 1
str
end
#--------------------------------------------------------------------------
# ● 获取起始光标位置
#--------------------------------------------------------------------------
def sel_spos
return if @disposed
#return @@SendMessage.call(@window, 0xB0, 0, 0) & 0xFFFF
spos = "\0" * 4
@@SendMessage_Pos.call(@window, 0xB0, spos, 0)
return spos.unpack("l")[0]
end
#--------------------------------------------------------------------------
# ● 获取結束光标位置
#--------------------------------------------------------------------------
def sel_epos
return if @disposed
#return @@SendMessage.call(@window, 0xB0, 0, 0) >> 16
epos = "\0" * 4
@@SendMessage_Pos.call(@window, 0xB0, 0, epos)
return epos.unpack("l")[0]
end
#--------------------------------------------------------------------------
# ● 设置光标位置
#--------------------------------------------------------------------------
def sel_spos=(i)
return if @disposed
@@SendMessage.call(@window, 0xB1, i, sel_epos)
end
#--------------------------------------------------------------------------
# ● 设置光标位置
#--------------------------------------------------------------------------
def sel_epos=(i)
return if @disposed
@@SendMessage.call(@window, 0xB1, sel_spos, i)
end
#--------------------------------------------------------------------------
# ● 设置光标位置
#--------------------------------------------------------------------------
def sel_pos=(i)
return if @disposed
@@SendMessage.call(@window, 0xB1, i, i)
end
#--------------------------------------------------------------------------
# ● 获取字數限制
#--------------------------------------------------------------------------
def limit
return if @disposed
return @@SendMessage.call(@window, 0xD5, 0, 0)
end
#--------------------------------------------------------------------------
# ● 设置字數限制
#--------------------------------------------------------------------------
def limit=(i)
return if @disposed
@@SendMessage.call(@window, 0xC5, i, 0)
end
#--------------------------------------------------------------------------
# ● 是否按下回车键(0x0D => Enter, 0x1B => ESC)
#--------------------------------------------------------------------------
def press_enter?
return !(@enter_pressed = false) if @enter_pressed
return false
end
end
实际上显示用的窗口 Window_TextBox
#encoding:utf-8
#==============================================================================
# ■ Window_TextBox By AAM@_@
#------------------------------------------------------------------------------
# 显示输入框用的窗口。
#==============================================================================
class Window_TextBox < Window_Base
#--------------------------------------------------------------------------
# ● 设置缓存的类
#--------------------------------------------------------------------------
TextBoxMem = Struct.new(:text, :sel_spos, :sel_epos)
#--------------------------------------------------------------------------
# ● 定义实例变量
#--------------------------------------------------------------------------
attr_reader :textbox
attr_reader :sel_pos
#--------------------------------------------------------------------------
# ● 初始化
#--------------------------------------------------------------------------
def initialize(x, y, width = 160, password = false)
super(x, y, width, window_height)
@handler = nil
@textbox = TextBox.new("", 8, password, width - standard_padding * 2)
@textbox.set_pos(self.x + standard_padding, self.y + standard_padding)
@tbmem = TextBoxMem.new
@curcor = Sprite.new
@curcor.bitmap = Bitmap.new(2, line_height)
@curcor.bitmap.fill_rect(@curcor.bitmap.rect, system_color)
@curcor.visible = false
@curcor.x = self.x + standard_padding
@curcor.y = self.y + standard_padding
@curcor.z = self.z + 1
@selection_color = system_color.clone
@selection_color.alpha = 128
refresh
activate
end
#--------------------------------------------------------------------------
# ● 获取窗口的高度
#--------------------------------------------------------------------------
def window_height
fitting_height(1)
end
#--------------------------------------------------------------------------
# ●
#--------------------------------------------------------------------------
def x=(x)
super
@textbox.set_pos(self.x + standard_padding, self.y + standard_padding)
update_cursor_pos
end
#--------------------------------------------------------------------------
# ●
#--------------------------------------------------------------------------
def y=(y)
super
@textbox.set_pos(self.x + standard_padding, self.y + standard_padding)
@curcor.y = y + standard_padding
end
#--------------------------------------------------------------------------
# ●
#--------------------------------------------------------------------------
def z=(z)
super
@curcor.z = z + 1
end
#--------------------------------------------------------------------------
# ●
#--------------------------------------------------------------------------
def viewport=(viewport)
super
@curcor.viewport = viewport
end
#--------------------------------------------------------------------------
# ● 刷新
#--------------------------------------------------------------------------
def update
super
if !@textbox.focus
@curcor.visible = false
return
end
@textbox.update
refresh if @textbox.sel_spos != @tbmem.sel_spos or @textbox.sel_epos != @tbmem.sel_epos or @textbox.text != @tbmem.text
update_cursor
process_handling
end
#--------------------------------------------------------------------------
# ● 刷新游標
#--------------------------------------------------------------------------
def update_cursor
@curcor.visible = !@curcor.visible if Graphics.frame_count % 30 == 0
end
#--------------------------------------------------------------------------
# ● 刷新游標位置
#--------------------------------------------------------------------------
def update_cursor_pos
if @tbmem.sel_spos == @textbox.sel_spos
@sel_pos = @textbox.sel_epos
else
@sel_pos = @textbox.sel_spos
end
t = @textbox.text[0, @sel_pos]
s = contents.text_size(t).width
@curcor.x = x + standard_padding + s
end
#--------------------------------------------------------------------------
# ● 選取繪製
#--------------------------------------------------------------------------
def fill_selection(spos, epos)
return if spos == epos
rect = contents.rect.clone
t = @textbox.text[0, spos]
rect.x = contents.text_size(t).width
t = @textbox.text[spos, epos - spos]
rect.width = contents.text_size(t).width
contents.fill_rect(rect, @selection_color)
end
#--------------------------------------------------------------------------
# ● 释放
#--------------------------------------------------------------------------
def dispose
@textbox.dispose
@curcor.bitmap.dispose
@curcor.dispose
super
end
#--------------------------------------------------------------------------
# ● 内容刷新
#--------------------------------------------------------------------------
def refresh
contents.clear
fill_selection(@textbox.sel_spos, @textbox.sel_epos)
change_color(normal_color)
txt = @textbox.password ? ("*" * @textbox.text.size) : @textbox.text
draw_text(contents.rect, txt)
update_cursor_pos
@tbmem.sel_spos = @textbox.sel_spos
@tbmem.sel_epos = @textbox.sel_epos
@tbmem.text = @textbox.text
end
#--------------------------------------------------------------------------
# ● 设置动作对应的处理方法
#--------------------------------------------------------------------------
def set_ok_handler(method)
@handler = method
end
#--------------------------------------------------------------------------
# ● 调用处理方法
#--------------------------------------------------------------------------
def call_handler(symbol)
@handler[symbol].call if handle?(symbol)
end
#--------------------------------------------------------------------------
# ● “确定”和“取消”的处理
#--------------------------------------------------------------------------
def process_handling
return unless open? && active
return process_ok if ok_enabled? && @textbox.press_enter?
end
#--------------------------------------------------------------------------
# ● 获取确定处理的有效状态
#--------------------------------------------------------------------------
def ok_enabled?
return !@handler.nil?
end
#--------------------------------------------------------------------------
# ● 按下确定键时的处理
#--------------------------------------------------------------------------
def process_ok
Sound.play_ok
Input.update
deactivate
call_ok_handler
end
#--------------------------------------------------------------------------
# ● 调用“确定”的处理方法
#--------------------------------------------------------------------------
def call_ok_handler
@handler.call if ok_enabled?
end
end
#encoding:utf-8
#==============================================================================
# ■ Window_TextBox By AAM@_@
#------------------------------------------------------------------------------
# 显示输入框用的窗口。
#==============================================================================
class Window_TextBox < Window_Base
#--------------------------------------------------------------------------
# ● 设置缓存的类
#--------------------------------------------------------------------------
TextBoxMem = Struct.new(:text, :sel_spos, :sel_epos)
#--------------------------------------------------------------------------
# ● 定义实例变量
#--------------------------------------------------------------------------
attr_reader :textbox
attr_reader :sel_pos
#--------------------------------------------------------------------------
# ● 初始化
#--------------------------------------------------------------------------
def initialize(x, y, width = 160, password = false)
super(x, y, width, window_height)
@handler = nil
@textbox = TextBox.new("", 8, password, width - standard_padding * 2)
@textbox.set_pos(self.x + standard_padding, self.y + standard_padding)
@tbmem = TextBoxMem.new
@curcor = Sprite.new
@curcor.bitmap = Bitmap.new(2, line_height)
@curcor.bitmap.fill_rect(@curcor.bitmap.rect, system_color)
@curcor.visible = false
@curcor.x = self.x + standard_padding
@curcor.y = self.y + standard_padding
@curcor.z = self.z + 1
@selection_color = system_color.clone
@selection_color.alpha = 128
refresh
activate
end
#--------------------------------------------------------------------------
# ● 获取窗口的高度
#--------------------------------------------------------------------------
def window_height
fitting_height(1)
end
#--------------------------------------------------------------------------
# ●
#--------------------------------------------------------------------------
def x=(x)
super
@textbox.set_pos(self.x + standard_padding, self.y + standard_padding)
update_cursor_pos
end
#--------------------------------------------------------------------------
# ●
#--------------------------------------------------------------------------
def y=(y)
super
@textbox.set_pos(self.x + standard_padding, self.y + standard_padding)
@curcor.y = y + standard_padding
end
#--------------------------------------------------------------------------
# ●
#--------------------------------------------------------------------------
def z=(z)
super
@curcor.z = z + 1
end
#--------------------------------------------------------------------------
# ●
#--------------------------------------------------------------------------
def viewport=(viewport)
super
@curcor.viewport = viewport
end
#--------------------------------------------------------------------------
# ● 刷新
#--------------------------------------------------------------------------
def update
super
if !@textbox.focus
@curcor.visible = false
return
end
@textbox.update
refresh if @textbox.sel_spos != @tbmem.sel_spos or @textbox.sel_epos != @tbmem.sel_epos or @textbox.text != @tbmem.text
update_cursor
process_handling
end
#--------------------------------------------------------------------------
# ● 刷新游標
#--------------------------------------------------------------------------
def update_cursor
@curcor.visible = !@curcor.visible if Graphics.frame_count % 30 == 0
end
#--------------------------------------------------------------------------
# ● 刷新游標位置
#--------------------------------------------------------------------------
def update_cursor_pos
if @tbmem.sel_spos == @textbox.sel_spos
@sel_pos = @textbox.sel_epos
else
@sel_pos = @textbox.sel_spos
end
t = @textbox.text[0, @sel_pos]
s = contents.text_size(t).width
@curcor.x = x + standard_padding + s
end
#--------------------------------------------------------------------------
# ● 選取繪製
#--------------------------------------------------------------------------
def fill_selection(spos, epos)
return if spos == epos
rect = contents.rect.clone
t = @textbox.text[0, spos]
rect.x = contents.text_size(t).width
t = @textbox.text[spos, epos - spos]
rect.width = contents.text_size(t).width
contents.fill_rect(rect, @selection_color)
end
#--------------------------------------------------------------------------
# ● 释放
#--------------------------------------------------------------------------
def dispose
@textbox.dispose
@curcor.bitmap.dispose
@curcor.dispose
super
end
#--------------------------------------------------------------------------
# ● 内容刷新
#--------------------------------------------------------------------------
def refresh
contents.clear
fill_selection(@textbox.sel_spos, @textbox.sel_epos)
change_color(normal_color)
txt = @textbox.password ? ("*" * @textbox.text.size) : @textbox.text
draw_text(contents.rect, txt)
update_cursor_pos
@tbmem.sel_spos = @textbox.sel_spos
@tbmem.sel_epos = @textbox.sel_epos
@tbmem.text = @textbox.text
end
#--------------------------------------------------------------------------
# ● 设置动作对应的处理方法
#--------------------------------------------------------------------------
def set_ok_handler(method)
@handler = method
end
#--------------------------------------------------------------------------
# ● 调用处理方法
#--------------------------------------------------------------------------
def call_handler(symbol)
@handler[symbol].call if handle?(symbol)
end
#--------------------------------------------------------------------------
# ● “确定”和“取消”的处理
#--------------------------------------------------------------------------
def process_handling
return unless open? && active
return process_ok if ok_enabled? && @textbox.press_enter?
end
#--------------------------------------------------------------------------
# ● 获取确定处理的有效状态
#--------------------------------------------------------------------------
def ok_enabled?
return !@handler.nil?
end
#--------------------------------------------------------------------------
# ● 按下确定键时的处理
#--------------------------------------------------------------------------
def process_ok
Sound.play_ok
Input.update
deactivate
call_ok_handler
end
#--------------------------------------------------------------------------
# ● 调用“确定”的处理方法
#--------------------------------------------------------------------------
def call_ok_handler
@handler.call if ok_enabled?
end
end
附上范例和预览图
AdvanceInput.zip
(326.79 KB, 下载次数: 893)
作者: shellingford57 时间: 2013-3-1 20:08
哈,今天刚想着这个就看到了好开森。
话说这个系统可以做成做成聊天吗?我本来是想用条件分歧判断当某角色的名字为“你好”时NPC回“大家好才是真的好”,某角色的名字为“你真丑”时NPC回“你更丑”之类的,但是这样对输入的符合程度要求很高,有办法判断关键字的吗?比如我只要输入带有“你,好”的字样,NPC就回“你好”?
作者: danny8376 时间: 2013-3-1 20:31
shellingford57 发表于 2013-3-1 20:08
哈,今天刚想着这个就看到了好开森。
话说这个系统可以做成做成聊天吗?我本来是想用条件分歧判断当某角色 ...
用正则表示式匹配?
/(你|好)/.match("你好")
/(你|好)/.match("你是?")
/(你|好)/.match("不好")
作者: shellingford57 时间: 2013-3-1 20:43
danny8376 发表于 2013-3-1 20:31
用正则表示式匹配?
/(你|好)/.match("你好")
一脸呆滞看。正则表达式是什么好吃么……
是在事件-脚本里使用么?
作者: danny8376 时间: 2013-3-1 21:14
shellingford57 发表于 2013-3-1 20:43
一脸呆滞看。正则表达式是什么好吃么……
是在事件-脚本里使用么?
匹配角色名的话
在条件分歧的脚本输入
/(你|好)/.match($game_actors[角色ID].name)
可以查一下怎用正则表示式
作者: shellingford57 时间: 2013-3-1 21:29
好的谢谢!
作者: summer92 时间: 2013-3-8 04:24
{:2_256:}顶下LZ
作者: shellingford57 时间: 2013-3-9 18:11
加入这个输入框脚本之后,走走路容易出现game map的脚本报错……是脚本冲突了么请问?
作者: 离小可 时间: 2013-3-15 21:04
RMVA1.01a表示测试失败
窗体直接停止工作……
作者: 慕容幽情 时间: 2013-4-10 19:23
求助啊!我的复制进来之后,第一次还能输入,以后就怎么按键盘都不会动了,而且没有办法输入中文啊
作者: 沫流灬游戏流 时间: 2013-8-5 13:50
慕容幽情 发表于 2013-4-10 19:23
求助啊!我的复制进来之后,第一次还能输入,以后就怎么按键盘都不会动了,而且没有办法输入中文啊 ...
我也是啊!!!!!!!!!!!
作者: 627759311 时间: 2013-8-28 22:05
求更新啊……即使是范例也完全用不了,进入输入框之后就所有键都失灵了,英文中文都没用……
作者: OYSRSM 时间: 2013-9-26 11:43
窗体直接停止工作了……
作者: 晴兰 时间: 2013-9-26 20:14
提示: 作者被禁止或删除 内容自动屏蔽
作者: Sion 时间: 2013-10-7 20:39
本帖最后由 Sion 于 2013-10-7 20:41 编辑
好像没法在 win7 的 DEP 下运行,是操作内存那一部分代码有什么问题吗? 其它的 win7 用户有没有类似的情况呢 ?
作者: 不死鸟之翼 时间: 2013-10-11 21:29
本来动态链接DLL就不如静态链接可靠,写这种“不用带DLL”的纯脚本,大量使用API(LoadLibrary)很可能因为操作系统版本等细节问题导致程序崩溃,最好的还是直接用C/C++写出来然后封装到DLL,这样无疑可以大大提高程序健壮性,错误都自己处理了(程序停止工作的话会对用户体验造成负面影响),如果怕用户弄丢了DLL的话,做个自解压弄到临时文件夹就行了
另外说一句楼主辛苦了{:2_275:}
作者: 429833854 时间: 2014-1-11 10:32
本帖最后由 429833854 于 2014-1-11 10:34 编辑
为啥删不掉字啊?也打不上字?直接把脚本复制过来就不好使了。
作者: limingchong 时间: 2014-1-24 14:08
此脚本和
http://rpg.blue/thread-217645-1-1.html(鼠标脚本)
此脚本冲突,鼠标无法使用
作者: 刹那·F·清英VL 时间: 2016-4-23 00:32
楼主,我想做出可以自由键入字母的那种效果,这个脚本可以实现吗?新手小白求教,感谢
作者: dengwei 时间: 2016-5-1 17:59
漏洞较大,不过没关系,慢慢改,期待{:2_260:}
欢迎光临 Project1 (https://rpg.blue/) |
Powered by Discuz! X3.1 |