查看: 13851|回复: 19

[RMVA发布] 免DLL輸入框

[复制链接]
梦石
0
星屑
109
在线时间
67 小时
注册时间
2007-12-16
回帖
64
发表于 2013-3-1 18:24:02 | 显示全部楼层 |阅读模式

加入我们,或者,欢迎回来。

您需要 登录 才可以下载或查看,没有账号?注册会员

×
本帖最后由 danny8376 于 2013-5-23 20:39 编辑

虽然这类脚本发过很多了
不过这个应该算最完整了=w=

基本上一般文字输入框的功能都有了
(显示上也是 选取都有做出来了XDD)

不过原本想改成Unicode 这样可以解决编码问题
不过没办法产生支援Unicode的文字框...
不知道有没有啥办法呢=3=

直接显示文字输入框也有做
不过懒得去背景+改文字颜色
有时间再改吧



符号类别扩充 颇喜欢这种WIN32API用法
[pre lang="ruby" line="1"]#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
[/pre]


下方是修改过的晴兰的纯脚本不使用DLL就读取窗口消息
主要是产生消息函数给文字框用
[pre lang="ruby" line="1"]#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
[/pre]


文字编码
[pre lang="ruby" line="1"]#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
[/pre]



主要负责处理文字框的 TextBox
[pre lang="ruby" line="1"]#==============================================================================
# ■ 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
[/pre]




实际上显示用的窗口 Window_TextBox
[pre lang="ruby" line="1"]#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
[/pre]





附上范例和预览图
未命名.png

AdvanceInput.zip (326.79 KB, 下载次数: 897)      

点评

在下的用户名好像躺枪了……OTZ  发表于 2013-3-1 21:10

评分

参与人数 1星屑 +45 收起 理由
英顺的马甲 + 45 写得比我还完整==

查看全部评分

梦石
0
星屑
50
在线时间
75 小时
注册时间
2011-6-14
回帖
15
发表于 2013-3-1 20:08:46 | 显示全部楼层
哈,今天刚想着这个就看到了好开森。
话说这个系统可以做成做成聊天吗?我本来是想用条件分歧判断当某角色的名字为“你好”时NPC回“大家好才是真的好”,某角色的名字为“你真丑”时NPC回“你更丑”之类的,但是这样对输入的符合程度要求很高,有办法判断关键字的吗?比如我只要输入带有“你,好”的字样,NPC就回“你好”?
回复

使用道具 举报

梦石
0
星屑
109
在线时间
67 小时
注册时间
2007-12-16
回帖
64
 楼主| 发表于 2013-3-1 20:31:35 | 显示全部楼层
shellingford57 发表于 2013-3-1 20:08
哈,今天刚想着这个就看到了好开森。
话说这个系统可以做成做成聊天吗?我本来是想用条件分歧判断当某角色 ...

用正则表示式匹配?

/(你|好)/.match("你好")
/(你|好)/.match("你是?")
/(你|好)/.match("不好")
回复

使用道具 举报

梦石
0
星屑
50
在线时间
75 小时
注册时间
2011-6-14
回帖
15
发表于 2013-3-1 20:43:30 | 显示全部楼层
danny8376 发表于 2013-3-1 20:31
用正则表示式匹配?

/(你|好)/.match("你好")

一脸呆滞看。正则表达式是什么好吃么……

是在事件-脚本里使用么?
回复

使用道具 举报

梦石
0
星屑
109
在线时间
67 小时
注册时间
2007-12-16
回帖
64
 楼主| 发表于 2013-3-1 21:14:34 | 显示全部楼层
shellingford57 发表于 2013-3-1 20:43
一脸呆滞看。正则表达式是什么好吃么……

是在事件-脚本里使用么?

匹配角色名的话
在条件分歧的脚本输入
/(你|好)/.match($game_actors[角色ID].name)
可以查一下怎用正则表示式
回复

使用道具 举报

梦石
0
星屑
50
在线时间
75 小时
注册时间
2011-6-14
回帖
15
发表于 2013-3-1 21:29:35 | 显示全部楼层
好的谢谢!
回复

使用道具 举报

梦石
0
星屑
1547
在线时间
688 小时
注册时间
2009-11-11
回帖
2692
发表于 2013-3-8 04:24:42 | 显示全部楼层
{:2_256:}顶下LZ
回复

使用道具 举报

梦石
0
星屑
50
在线时间
75 小时
注册时间
2011-6-14
回帖
15
发表于 2013-3-9 18:11:38 | 显示全部楼层
加入这个输入框脚本之后,走走路容易出现game map的脚本报错……是脚本冲突了么请问?
回复

使用道具 举报

梦石
0
星屑
50
在线时间
96 小时
注册时间
2009-7-6
回帖
15
发表于 2013-3-15 21:04:20 | 显示全部楼层
RMVA1.01a表示测试失败
窗体直接停止工作……
回复

使用道具 举报

梦石
0
星屑
50
在线时间
25 小时
注册时间
2013-3-23
回帖
6
发表于 2013-4-10 19:23:57 | 显示全部楼层
求助啊!我的复制进来之后,第一次还能输入,以后就怎么按键盘都不会动了,而且没有办法输入中文啊
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册会员

本版积分规则

Powered by Discuz! X5.0 © 2001-2026 Discuz! Team.

在本版发帖返回顶部