查看: 4419|回复: 4

[通用发布] 【fix】Input & Mouse & 真·窗口拖动

[复制链接]
梦石
0
星屑
76
在线时间
1379 小时
注册时间
2012-7-5
回帖
1643

开拓者

发表于 2015-1-6 13:01:22 | 显示全部楼层 |阅读模式

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

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

×
本帖最后由 kuerlulu 于 2016-6-8 16:43 编辑

0.gif
Input:
author: 余烬之中
change: 1.修正 bitween 拼写错误; 2. key_type 判定微调; 3.重写 Mouse 并独立在外
Mouse:
(可选) 最后一段 alias 如果不希望和 Input 绑定在一起可以删去, Mouse 可单独使用
(为什么是"真")
之前能找到的窗口拖动的实现都建立在鼠标在窗口内, 换句话说鼠标一旦移出窗口就会判定异常, 本脚本修正了这一点
Mouse的最后有一段简短的拖动介绍 :P

[fold=Mouse][pre lang="ruby" line="0"]
#==============================================================================
# ■ M3L::Mouse
#------------------------------------------------------------------------------
#  Module for processing mouse input.
#  EXAMPLE for dragging:
#    update: M3L::Mouse[self] = [x, y]   if M3L::Mouse.down_in? rect
#            self.x = M3L::Mouse.dx self if M3L::Mouse.dref self
#            self.y = M3L::Mouse.dy self if M3L::Mouse.dref self
#  PS: `dx' means "dragging x" :P
#==============================================================================
M3L = Module.new unless defined? M3L
module M3L::Mouse
  #--------------------------------------------------------------------------
  # ● Data
  #--------------------------------------------------------------------------
  Data = {
    :position => [0, 0],
    :last_pos => [0, 0],
    :dump_pos => [0, 0],
    :left     => [0, 0],
    :middle   => [0, 0],
    :right    => [0, 0],
    :timer    =>  0
  }
  Drag = {}
  #--------------------------------------------------------------------------
  # ● Win32API
  #--------------------------------------------------------------------------
  GetCursorPos     = Win32API.new("user32", "GetCursorPos"    , "p" , "i")
  ScreenToClient   = Win32API.new("user32", "ScreenToClient"  , "pp", "i")
  GetActiveWindow  = Win32API.new("user32", "GetActiveWindow" , ""  , "i")
  GetAsyncKeyState = Win32API.new("user32", "GetAsyncKeyState", "i" , "i")
  ShowCursor       = Win32API.new("user32", "ShowCursor"      , "i" , "i")
#============================================================================
# ● MouseAPI
#============================================================================
class << self
  def _hwnd
    (
      defined? @hWnd) ?  @hWnd         : (
      defined?  hwnd) ? (@hWnd = hwnd) : (
                         @hWnd = GetActiveWindow.call
    )
  end
  def _pos
    GetCursorPos.call buffer = "\0" * 8
    ScreenToClient.call _hwnd, buffer
    buffer.unpack "ll"
  end
  def _press? button
    GetAsyncKeyState.call(button).abs & 0x8000 == 0x8000
  end
  def dump_button key, b
    Data[key][1] = Data[key][0]
    Data[key][0] = (_press? b) ? Data[key][0] + 1 : 0
  end
  private :_hwnd, :_press?, :_pos, :dump_button
  #--------------------------------------------------------------------------
  # ● Update Data
  #--------------------------------------------------------------------------
  def update
    Data[:last_pos] = Data[:position]
    Data[:position] = _pos
    Data[:timer] = Data[:last_pos] == Data[:position] ? Data[:timer] + 1 : 0
    dump_button :left  , 0b001
    dump_button :right , 0b010
    dump_button :middle, 0b100
    Data[:dump_pos] = Data[:position] if down_left?
    Drag.clear if !Drag.empty? and left == 0
  end
  #--------------------------------------------------------------------------
  # ● Shotcuts
  #--------------------------------------------------------------------------
  def pos         ; Data[:position]                               ; end
  def timer       ; Data[:timer]                                  ; end
  def left        ; Data[:left][0]                                ; end
  def right       ; Data[:right][0]                               ; end
  def middle      ; Data[:middle][0]                              ; end
  def moving?     ; Data[:timer]     == 0                         ; end
  def down_left?  ; Data[:left][1]   == 0 && Data[:left][0]   != 0; end
  def down_right? ; Data[:right][1]  == 0 && Data[:right][0]  != 0; end
  def down_middle?; Data[:middle][1] == 0 && Data[:middle][0] != 0; end
  def hold_left?  ; Data[:left][1]   != 0 && Data[:left][0]   != 0; end
  def hold_right? ; Data[:right][1]  != 0 && Data[:right][0]  != 0; end
  def hold_middle?; Data[:middle][1] != 0 && Data[:middle][0] != 0; end
  def   up_left?  ; Data[:left][1]   != 0 && Data[:left][0]   == 0; end
  def   up_right? ; Data[:right][1]  != 0 && Data[:right][0]  == 0; end
  def   up_middle?; Data[:middle][1] != 0 && Data[:middle][0] == 0; end
  def hold?       ; hold_left? || hold_right? || hold_middle?     ; end
  def down?       ; down_left? || down_right? || down_middle?     ; end
  def up_all?     ;   up_left? &&   up_right? &&   up_middle?     ; end
  alias time timer
  alias dragging? hold_left?
  alias click? up_left?
  alias right_click? up_right?
  #--------------------------------------------------------------------------
  # ● Show/Hide the real mouse cursor
  #--------------------------------------------------------------------------
  def hide; ShowCursor.call(0); end
  def show; ShowCursor.call(1); end
  #--------------------------------------------------------------------------
  # ● Regist/Change infos in Drag
  #--------------------------------------------------------------------------
  def dref k, v = nil
    v ? (Drag[k] = v) : Drag[k]
  end
  alias []  dref
  alias []= dref
  #--------------------------------------------------------------------------
  # ● Judge whether pos in rect
  #--------------------------------------------------------------------------
  def area? *args
    args = args.flatten
    case args.size
    when 1
      x, y, w, h = args[0].x, args[0].y, args[0].width, args[0].height
    when 4
      x, y, w, h = *args
    else
      raise "Invalid argument: " + args.inspect
    end
    pos[0].between?(x, x + w) && pos[1].between?(y, y + h)
  end
  alias rect? area?
  #--------------------------------------------------------------------------
  # ● Judge down_left? with pos in rect
  #--------------------------------------------------------------------------
  def down_in? *args
    down_left? && area?(*args)
  end
  #--------------------------------------------------------------------------
  # ● Get dragging position for sym (see EXAMPLE for dragging)
  #  return nil if not found Drag[sym]
  #--------------------------------------------------------------------------
  def dx sym
    x = dref sym
    x ? x[0] + Data[:position][0] - Data[:dump_pos][0] : ()
  end
  def dy sym
    x = dref sym
    x ? x[1] + Data[:position][1] - Data[:dump_pos][1] : ()
  end
end
end

#==============================================================================
# ■ Mouse = M3L::Mouse
#==============================================================================
unless defined? Mouse
  Mouse = M3L::Mouse
  class << Input
    alias m3l_mouse_update update
    def update
      m3l_mouse_update
      Mouse.update
    end
  end
end

=begin # hhhh..
class Window_Base
  alias _update update
  def update
    _update
    M3L::Mouse[self] = [x, y] if M3L::Mouse.down_in?(x, y, width, height)
    self.x = M3L::Mouse.dx(self) if M3L::Mouse.dref self
    self.y = M3L::Mouse.dy(self) if M3L::Mouse.dref self
  end
end
=end
[/pre][/fold]
[fold=浴巾的Input][pre lang="ruby" line="0"]
#==============================================================================
# ■ Input
#------------------------------------------------------------------------------
#   处理键盘输入信息的模块。
#==============================================================================
module Input
  #--------------------------------------------------------------------------
  # ● 常量
  #--------------------------------------------------------------------------
  DOWN=[0x28,0x62];LEFT=[0x25,0x64];RIGHT=[0x27,0x66];UP=[0x26,0x68]
  A=[0x5A,0x10];B=[0x58,0x1B,0x60];C=[0x20,0x0D,0x43]
   X = 0x41;  Y = 0x53;  Z = 0x44;  L = 0x51;  R = 0x57
  F5 = 0x74; F6 = 0x75; F7 = 0x76; F8 = 0x77; F9 = 0x78
  LETTERS = {
    'A' => 0x41, 'B' => 0x42, 'C' => 0x43, 'D' => 0x44, 'E' => 0x45,
    'F' => 0x46, 'G' => 0x47, 'H' => 0x48, 'I' => 0x49, 'J' => 0x4A,
    'K' => 0x4B, 'L' => 0x4C, 'M' => 0x4D, 'N' => 0x4E, 'O' => 0x4F,
    'P' => 0x50, 'Q' => 0x51, 'R' => 0x52, 'S' => 0x53, 'T' => 0x54,
    'U' => 0x55, 'V' => 0x56, 'W' => 0x57, 'X' => 0x58, 'Y' => 0x59,
    'Z' => 0x5A                                          
  }            
  #             0     1     2     3     4     5     6     7     8     9
  NUMBERS = [0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39]
  NUMPAD  = [0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69]
  #             *           +                -              /
  Multiply = 0x6A; Add = 0x6B; Subtract = 0x6D; Divide = 0x6F;
  #              ,               .
  Separator = 0x6C; Decimal = 0x6E;
  #          ;             =             ,             -             .
  SCOLON = 186; EQUALS = 187; COMMA  = 188; USCORE = 189; PERIOD = 190;
  #          /             `             [             \             ]
  SLASH  = 191; TILDE  = 192; LBRACE = 219; BSLASH = 220; RBRACE = 221;
  #          '
  QUOTE  = 222;
  # ENDK for END!
  BACKSPACE    = 0x08; TAB       = 0x09; ENTER      = 0x0D; SHIFT       = 0x10;
  CTRL         = 0x11; ALT       = 0x12; PAUSE      = 0x13; CAPSLOCK    = 0x14;
  ESC          = 0x1B; SPACEBAR  = 0x20; PAGEUP     = 0x21; PAGEDOWN    = 0x22;
  ENDK         = 0x23; HOME      = 0x24; LEFTARROW  = 0x25; UPARROW     = 0x26;
  RIGHTARROW   = 0x27; DOWNARROW = 0x28; SELECT     = 0x29; PRINT       = 0x2A;
  PRINTSCREEN  = 0x2C; INS       = 0x2D; DEL        = 0x2E; NUMLOCK     = 0x90;
  SCROLLLOCK   = 0x91; LeftSHIFT = 0xA0; RightSHIFT = 0xA1; LeftCONTROL = 0xA2;
  RightCONTROL = 0xA3; LeftALT   = 0xA4; RightALT   = 0xA5; LeftWin     = 0x5B;
  RightWin     = 0x5C; App       = 0x5D;
  #    nil,  F1,  F2   F3,  F4,  F5,  F6,  F7,  F8,  F9, F10, F11, F12
  F = [nil,0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7A,0x7B]
  KeyRepeatCounter = {}
  # APIs
  GetAsyncKeyState = _api "user32|GetAsyncKeyState|i|i"
  GetKeyState      = _api "user32|GetKeyState|i|i"
class << self
  def update
    KeyRepeatCounter.each_key do |key|
      if GetAsyncKeyState.call(key).abs & 0x8000 == 0x8000
        KeyRepeatCounter[key] += 1
      else
        KeyRepeatCounter.delete(key)
      end
    end
  end
  def press? key
    if key.is_a? String
      return string_key(key, :press?)
    elsif key.is_a? Symbol
      return string_key(key.to_s, :press?)
    elsif key.is_a? Array
      return key.any?{|k| press? k }
    end
    return true unless KeyRepeatCounter[key].nil?
    return _press? key
  end
  def trigger? key
    if key.is_a? String
      return string_key(key, :trigger?)
    elsif key.is_a? Symbol
      return string_key(key.to_s, :trigger?)
    elsif key.is_a? Array
      return key.any?{|k| trigger? k }
    end
    count = KeyRepeatCounter[key]
    return count == 0 || (count.nil? ? _press?(key) : false)
  end
  def repeat? key
    if key.is_a? String
      return string_key(key, :repeat?)
    elsif key.is_a? Symbol
      return string_key(key.to_s, :repeat?)
    elsif key.is_a? Array
      return key.any?{|k| repeat? k }
    end
    count = KeyRepeatCounter[key]
    return true if count == 0
    return count.nil? ? _press?(key) : count >= 23 && (count - 23) % 6 == 0
  end
  def _press? key
    if GetAsyncKeyState.call(key).abs & 0x8000 == 0x8000
      KeyRepeatCounter[key] = 0
      return true
    end
    return false
  end
  def string_key key, sym
    if 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'.include? key
      method(sym).call LETTERS[key]
    elsif '0123456789'.include? key
      method(sym).call(NUMBERS[key.to_i]) || method(sym).call(NUMPAD[key.to_i])
    else
      case key.downcase
      when '*'; method(sym).call Multiply
      when '+'; method(sym).call(Add)       || method(sym).call(EQUALS)
      when '-'; method(sym).call(Subtract)  || method(sym).call(USCORE)
      when '/'; method(sym).call(Divide)    || method(sym).call(SLASH)
      when ','; method(sym).call(Separator) || method(sym).call(COMMA)
      when '.'; method(sym).call(Decimal)   || method(sym).call(PERIOD)
      when '<'; method(sym).call COMMA
      when '>'; method(sym).call PERIOD
      when '?'; method(sym).call SLASH
      when ';' , ':'; method(sym).call SCOLON
      when '\'', '"'; method(sym).call QUOTE
      when '[' , '{'; method(sym).call LBRACE
      when ']' , '}'; method(sym).call RBRACE
      when '`' , '~'; method(sym).call TILDE
      when '\\', '|'; method(sym).call BSLASH
      when '!'; method(sym).call NUMBERS[1]
      when '@'; method(sym).call NUMBERS[2]
      when '#'; method(sym).call NUMBERS[3]
      when '$'; method(sym).call NUMBERS[4]
      when '%'; method(sym).call NUMBERS[5]
      when '^'; method(sym).call NUMBERS[6]
      when '&'; method(sym).call NUMBERS[7]
      when '*'; method(sym).call NUMBERS[8]
      when '('; method(sym).call NUMBERS[9]
      when ')'; method(sym).call NUMBERS[0]
      when '_'; method(sym).call USCORE
      when '='; method(sym).call EQUALS
      when 'shift'      ; method(sym).call SHIFT
      when 'lshift'     ; method(sym).call LeftSHIFT
      when 'rshift'     ; method(sym).call RightSHIFT
      when 'ctrl'       ; method(sym).call CTRL
      when 'lctrl'      ; method(sym).call LeftCTRL
      when 'rctrl'      ; method(sym).call RightCTRL
      when 'alt'        ; method(sym).call ALT
      when 'lalt'       ; method(sym).call LeftALT
      when 'ralt'       ; method(sym).call RightALT
      when 'app'        ; method(sym).call App
      when 'tab'        ; method(sym).call TAB
      when 'capslock'   ; method(sym).call CAPSLOCK
      when 'numlock'    ; method(sym).call NUMLOCK
      when 'scrolllock' ; method(sym).call SCROLLLOCK
      when 'enter'      ; method(sym).call ENTER
      when 'backspace'  ; method(sym).call BACKSPACE
      when 'space'      ; method(sym).call SPACEBAR
      when 'ins'        ; method(sym).call INS
      when 'del'        ; method(sym).call DEL
      when 'home'       ; method(sym).call HOME
      when 'end'        ; method(sym).call ENDK
      when 'pageup'     ; method(sym).call PAGEUP
      when 'pagedown'   ; method(sym).call PAGEDOWN
      when 'esc'        ; method(sym).call ESC
      when 'uparrow'    ; method(sym).call UPARROW
      when 'downarrow'  ; method(sym).call DOWNARROW
      when 'leftarrow'  ; method(sym).call LEFTARROW
      when 'rightarrow' ; method(sym).call RIGHTARROW
      when 'printscreen'; method(sym).call PRINTSCREEN
      when 'select'     ; method(sym).call SELECT
      when 'print'      ; method(sym).call PRINT
      when 'lwin'       ; method(sym).call LeftWin
      when 'rwin'       ; method(sym).call RightWin
      when 'win'; method(sym).call(LeftWin) || method(sym).call(RightWin)
      else; key == key.slice(0, 1) ? false : string_key(key.slice(0, 1), sym)
      end
    end
  end
  def typing?
    repeat?(SPACEBAR) || LETTERS.any?{|l, c| repeat? c } ||
    NUMBERS.any?{|n| repeat? n } || NUMPAD.any?{|n| repeat? n } ||
    repeat?(Multiply) || repeat?(Decimal)|| repeat?(Divide)|| repeat?(COMMA) ||
    repeat?(Separator)|| repeat?(Add)    || repeat?(EQUALS)|| repeat?(SLASH) ||
    repeat?(SCOLON)   || repeat?(USCORE) || repeat?(PERIOD)|| repeat?(TILDE) ||
    repeat?(Subtract) || repeat?(LBRACE) || repeat?(BSLASH)|| repeat?(RBRACE)||
    repeat?(QUOTE)
  end
  def key_type
    return " " if repeat? SPACEBAR
    LETTERS.each{|l, c| return upcase? ? l.upcase : l.downcase if repeat? c }
    NUMPAD.each_with_index{|n, i| return i.to_s if repeat? n }
    if press? SHIFT
      NUMBERS.each_with_index do |n, i|
        next unless repeat? n
        case i
        when 1; return "!"
        when 2; return "@"
        when 3; return "#"
        when 4; return "$"
        when 5; return "%"
        when 6; return "^"
        when 7; return "&"
        when 8; return "*"
        when 9; return "("
        when 0; return ")"
        end
      end
    else
      NUMBERS.each_with_index{|n, i| return i.to_s if repeat? n }
    end
    return "*" if repeat? Multiply
    return "+" if repeat? Add
    return "-" if repeat? Subtract
    return "/" if repeat? Divide
    return "," if repeat? Separator
    return "." if repeat? Decimal
    return press?(SHIFT) ? ":" : ";"  if repeat? SCOLON
    return press?(SHIFT) ? "+" : "="  if repeat? EQUALS
    return press?(SHIFT) ? "<" : ","  if repeat? COMMA
    return press?(SHIFT) ? "_" : "-"  if repeat? USCORE
    return press?(SHIFT) ? ">" : "."  if repeat? PERIOD
    return press?(SHIFT) ? "?" : "/"  if repeat? SLASH
    return press?(SHIFT) ? "~" : "`"  if repeat? TILDE
    return press?(SHIFT) ? "{" : "["  if repeat? LBRACE
    return press?(SHIFT) ? "|" : "\\" if repeat? BSLASH
    return press?(SHIFT) ? "}" : "]"  if repeat? RBRACE
    return press?(SHIFT) ? '"' : "'"  if repeat? QUOTE
    return ""
  end
  def upcase?
    return press?(SHIFT) != (GetKeyState.call(CAPSLOCK) == 1)
  end
  private :_press?, :upcase?
end
end
[/pre][/fold]

评分

参与人数 4星屑 +330 收起 理由
余烬之中 + 80
taroxd + 100 精品文章
无脑之人 + 30 闲来无事冒个泡
喵呜喵5 + 120

查看全部评分


  -fk: -azogi:

【欧皇】

梦石
3
星屑
2055
在线时间
1004 小时
注册时间
2013-8-19
回帖
3040

开拓者

发表于 2015-1-7 19:05:18 | 显示全部楼层
xp可以用吗?还有说好的范例呢?

点评

都说通用了当然xp能用 以及你想要什么范例 懒人勿用系列【噗  发表于 2015-1-7 22:24
QQ:2223942063
Q群:365819625
贪吃方1.4
回复

使用道具 举报

…あたしは天

梦石
0
星屑
2308
在线时间
4033 小时
注册时间
2010-10-4
回帖
10548

开拓者贵宾

发表于 2015-1-8 12:55:21 | 显示全部楼层
本帖最后由 taroxd 于 2015-1-8 17:19 编辑

实现一下这个效果吧,以后用起来会舒服很多。以你现在写的东西来看应该往模块里写个 update 就可以了。
(回家有空的话我倒是想写着玩玩,顺便写个鼠标脚本啥的)

[pre lang="ruby" line="1"]# 一个可能的 Window_Dragable

class Window_Dragable < Window_Base
  include Mouse::Dragable
end

# 一个可能的 Sprite_Dragable

class Sprite_Dragable < Sprite
  include Mouse::Dragable
end[/pre]

点评

update是sysmod干的事,我都不写了  发表于 2015-1-9 01:25
其实我倒蛮想在window_base里直接写updade: update_dragging if @dragable  发表于 2015-1-8 22:32
回复

使用道具 举报

梦石
0
星屑
9292
在线时间
2504 小时
注册时间
2011-5-20
回帖
14521

开拓者

发表于 2015-1-9 22:16:58 | 显示全部楼层
F12还有用吗?其实我还想禁掉F12拿来做别的东西···

点评

F12没事的说~  发表于 2015-1-10 12:07
[img]http://service.t.sina.com.cn/widget/qmd/5339802982/c02e16bd/7.png
回复

使用道具 举报

头像被屏蔽
梦石
0
星屑
653
在线时间
3774 小时
注册时间
2011-2-26
回帖
1577

开拓者

发表于 2015-1-10 11:55:50 | 显示全部楼层
提示: 作者被禁止或删除 内容自动屏蔽
签名被屏蔽
回复

使用道具 举报

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

本版积分规则

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

在本版发帖返回顶部