设为首页收藏本站|繁體中文

Project1

 找回密码
 注册会员
搜索
查看: 2490|回复: 3
打印 上一主题 下一主题

[已经解决] PeekMessage获取鼠标滚轮状态的问题

 关闭 [复制链接]

Lv1.梦旅人

梦石
0
星屑
100
在线时间
169 小时
注册时间
2007-8-12
帖子
203
跳转到指定楼层
1
发表于 2011-8-17 15:03:35 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 心雪 于 2011-8-17 15:19 编辑

  1. #==============================================================================
  2. # ■ Kernel
  3. #------------------------------------------------------------------------------
  4. #  该模块中定义了可供所有类使用的方法。Object 类中包含了该模块。
  5. #==============================================================================
  6. module Kernel
  7.   #--------------------------------------------------------------------------
  8.   # ● 需要的 Windows API 函数
  9.   #--------------------------------------------------------------------------
  10.   GetWindowThreadProcessId = Win32API.new("user32", "GetWindowThreadProcessId", "LP", "L")
  11.   GetWindow = Win32API.new("user32", "GetWindow", "LL", "L")
  12.   GetClassName = Win32API.new("user32", "GetClassName", "LPL", "L")
  13.   GetWindowText = Win32API.new("user32", "GetWindowText", "LPL", "L")
  14.   GetCurrentThreadId = Win32API.new("kernel32", "GetCurrentThreadId", "V", "L")
  15.   GetForegroundWindow = Win32API.new("user32", "GetForegroundWindow", "V", "L")
  16.   #--------------------------------------------------------------------------
  17.   # ● 获取窗口句柄
  18.   #--------------------------------------------------------------------------
  19.   def get_window_handle
  20.     # 获取调用线程(RM 的主线程)的进程标识
  21.     threadID = GetCurrentThreadId.call
  22.     # 获取 Z 次序中最靠前的窗口
  23.     hWnd = GetWindow.call(GetForegroundWindow.call, 0)
  24.     # 枚举所有窗口
  25.     while hWnd != 0
  26.       # 如果创建该窗口的线程标识匹配本线程标识
  27.       if threadID == GetWindowThreadProcessId.call(hWnd, 0)
  28.         # 分配一个 11 个字节的缓冲区
  29.         className = " " * 11
  30.         # 获取该窗口的类名
  31.         GetClassName.call(hWnd, className, 12)
  32.         # 如果匹配 RGSS Player 则跳出循环
  33.         break if className == "RGSS Player"
  34.       end
  35.       # 获取下一个窗口
  36.       hWnd = GetWindow.call(hWnd, 2)
  37.     end
  38.     return hWnd
  39.   end
  40. end




  41. $peekmessage = Win32API.new("user32","PeekMessageA","pllll","l")
  42. module Input
  43.   class << self
  44.     alias old_update update
  45.     def update
  46.       old_update
  47.       point = [0,0].pack("ll")
  48.       a = [0,0,0,0,0,point].pack("l5a*")
  49.       if $peekmessage.call(a,get_window_handle,522,522,1) != 0
  50.         arr = a.unpack("l5a*")
  51.         @wheel = arr[2]
  52.       else
  53.         @wheel = 0
  54.       end
  55.     end
  56.     def wheel
  57.       if @wheel.nil?
  58.         return 0
  59.       else
  60.         return @wheel
  61.       end
  62.     end
  63.   end
  64. end
复制代码
代码如上,现在的问题是……只有当鼠标坐标发生改变的时候,滚轮消息才能被处理……否则的话无效……这到底是啥米诡异情况= =
利用PeekMessage处理滚轮消息的VB范例:
http://djrm.blogbus.com/logs/53774033.html

Lv3.寻梦者

宛若

梦石
0
星屑
1553
在线时间
526 小时
注册时间
2007-8-19
帖子
1493

极短24参与开拓者

2
发表于 2011-8-17 19:06:15 | 只看该作者
6R神码时候还带度娘自动吞贴功能了
重新补充:
  1. #==============================================================================
  2. # ■ Kernel
  3. #------------------------------------------------------------------------------
  4. #  该模块中定义了可供所有类使用的方法。Object 类中包含了该模块。
  5. #==============================================================================
  6. module Kernel
  7.   #--------------------------------------------------------------------------
  8.   # ● 需要的 Windows API 函数
  9.   #--------------------------------------------------------------------------
  10.   GetWindowThreadProcessId = Win32API.new("user32", "GetWindowThreadProcessId", "LP", "L")
  11.   GetWindow = Win32API.new("user32", "GetWindow", "LL", "L")
  12.   GetClassName = Win32API.new("user32", "GetClassName", "LPL", "L")
  13.   GetWindowText = Win32API.new("user32", "GetWindowText", "LPL", "L")
  14.   GetCurrentThreadId = Win32API.new("kernel32", "GetCurrentThreadId", "V", "L")
  15.   GetForegroundWindow = Win32API.new("user32", "GetForegroundWindow", "V", "L")
  16.   #--------------------------------------------------------------------------
  17.   # ● 获取窗口句柄
  18.   #--------------------------------------------------------------------------
  19.   def get_window_handle
  20.     # 获取调用线程(RM 的主线程)的进程标识
  21.     threadID = GetCurrentThreadId.call
  22.     # 获取 Z 次序中最靠前的窗口
  23.     hWnd = GetWindow.call(GetForegroundWindow.call, 0)
  24.     # 枚举所有窗口
  25.     while hWnd != 0
  26.       # 如果创建该窗口的线程标识匹配本线程标识
  27.       if threadID == GetWindowThreadProcessId.call(hWnd, 0)
  28.         # 分配一个 11 个字节的缓冲区
  29.         className = " " * 11
  30.         # 获取该窗口的类名
  31.         GetClassName.call(hWnd, className, 12)
  32.         # 如果匹配 RGSS Player 则跳出循环
  33.         break if className == "RGSS Player"
  34.       end
  35.       # 获取下一个窗口
  36.       hWnd = GetWindow.call(hWnd, 2)
  37.     end
  38.     return hWnd
  39.   end
  40. end


  41. $peekmessage = Win32API.new("user32","PeekMessageA","pllll","l")
  42. module Input
  43.   class << self
  44.     alias old_update update
  45.     def update
  46.       old_update
  47.       point = [0,0].pack("ll")
  48.       a = [0,0,0,0,0,point].pack("l5a*")
  49.       if $peekmessage.call(a,get_window_handle,522,522,1) != 0
  50.         arr = a.unpack("l5a*")
  51.         @wheel = arr[2]
  52.       else
  53.         @wheel = 0
  54.       end
  55.     end
  56.     def wheel
  57.       if @wheel.nil?
  58.         return 0
  59.       else
  60.         return @wheel
  61.       end
  62.     end
  63.   end
  64. end
复制代码
就是这样的代码……错误状况是只有鼠标在移动的时候才可以处理滚轮滚动的消息……求解此诡异问题……
[url=http://rpg.blue/thread-219730-1-1.html]http://unhero.sinaapp.com/wi.php[/url]
[color=Red]如你所见这是个死坑,没错这就是打我的脸用的[/color]
回复

使用道具 举报

Lv1.梦旅人

梦石
0
星屑
110
在线时间
953 小时
注册时间
2007-4-25
帖子
805
3
发表于 2011-8-18 08:28:44 | 只看该作者
本帖最后由 苏小脉 于 2011-8-18 09:08 编辑

RM 的 Graphics.update 有处理消息的过程,队列中有一部分消息会直接被 RM 内核取走,而且 FPS 越高处理消息的频率就越高。鼠标移动时 OS 会发送各种和 WM_MOUSEMOVE 相关联的消息,队列长度陡增,Graphics.update 调用一次后取走的就不像没有鼠标移动消息时那样多了,所以有时可能就可以被 Ruby 层的 PeekMessage 拿到,但这样的行为是不可预知的,所以不可依赖。

更好的处理消息的方法自然还是通过本地代码 SetWindowsHookEx 安装钩子过程或是 SetWindowLong 直接拦截窗口过程函数。参考 http://rpg.blue/thread-147594-2-1.html 13~15 楼。

编辑:

而且 FPS 越处理消息的频率就越高。

应为:

而且 FPS 越低在一帧间处理的消息的数量就越多。
[email protected]:~> repeat 1 fortune
Matz is nice, so we are nice.
回复

使用道具 举报

Lv1.梦旅人

梦石
0
星屑
100
在线时间
169 小时
注册时间
2007-8-12
帖子
203
4
 楼主| 发表于 2011-8-18 11:22:10 | 只看该作者
受教了……
回复

使用道具 举报

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

本版积分规则

拿上你的纸笔,建造一个属于你的梦想世界,加入吧。
 注册会员
找回密码

站长信箱:[email protected]|手机版|小黑屋|无图版|Project1游戏制作

GMT+8, 2024-4-20 21:02

Powered by Discuz! X3.1

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表