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

Project1

 找回密码
 注册会员
搜索
楼主: hongqizhen
打印 上一主题 下一主题

[已经解决] 如何在存读档窗口使用鼠标滚轮?

[复制链接]
头像被屏蔽

Lv1.梦旅人 (禁止发言)

梦石
0
星屑
80
在线时间
3 小时
注册时间
2006-10-4
帖子
199
11
 楼主| 发表于 2010-8-19 08:23:01 | 只看该作者
提示: 作者被禁止或删除 内容自动屏蔽
回复 支持 反对

使用道具 举报

Lv1.梦旅人

梦石
0
星屑
61
在线时间
24 小时
注册时间
2008-8-5
帖子
1924
12
发表于 2010-8-19 14:08:58 | 只看该作者
感谢,您的意思是必须把相应的功能封装在dll中,并在脚本中调用是吗?是否有具体的例子呢?
hongqizhen 发表于 2010-8-18 12:23

在脚本里还是在 DLL 里调用取决于设计者,通常在解释性语言里调用更方便维护和调试,所以可以采取这个选择,但是替换窗口过程的过程最好还是写在 DLL 里,因为如果要在 Ruby 里操作本地函数和函数指针,还需要进行一系列地址偏移的计算
如果目前 XP 的鼠标脚本里没有这个功能就说明没有人写过,要是不急可以等我明天下了 VS 再帮你写一个

点评

夏娜的鼠标工程写过 不知道好用不  发表于 2010-8-23 12:51
不急的,我手头汉化的游戏还得添加任务日志和测试,最快也要半个月后才能发布。 麻烦您了,辛苦了!  发表于 2010-8-19 16:43
回复 支持 反对

使用道具 举报

Lv5.捕梦者 (管理员)

老黄鸡

梦石
0
星屑
42404
在线时间
7602 小时
注册时间
2009-7-6
帖子
13506

开拓者贵宾

13
发表于 2010-8-19 16:00:59 | 只看该作者
我到现在也不知道滚轮的键值是多少。

点评

滚轮没有对应数值…… 数值对应表这里有: [url]http://zhidao.baidu.com/question/59675331[/url]  发表于 2010-8-19 17:00
RGDirect - DirectX驱动的RGSS,点我了解.
RM全系列成套系统定制请联系QQ1213237796
不接受对其他插件维护的委托
回复 支持 反对

使用道具 举报

Lv1.梦旅人

梦石
0
星屑
61
在线时间
24 小时
注册时间
2008-8-5
帖子
1924
14
发表于 2010-8-20 11:31:25 | 只看该作者
rm_mouse_wheel.rar (21.14 KB, 下载次数: 162)

附件里是预编译的 DLL,目标环境是 x86

将 DLL 放在游戏根目录,然后在 RM 里加入如下脚本:
  1. class Class
  2.   def ===(aClass)
  3.     return self == aClass
  4.   end
  5. end

  6. module Mouse
  7.   def self.on_wheel(delta, keys, x, y)
  8.     case $scene.class
  9.     when Scene_Title, Scene_End
  10.       command_window = $scene.instance_eval { @command_window }
  11.       item_max = command_window.instance_eval { @item_max }
  12.       command_window and
  13.       command_window.index =
  14.         [0, [item_max - 1, command_window.index - delta / 120].min].max
  15.     when Scene_Item
  16.       # ...
  17.     end
  18.   end
  19.   if !defined? Wheel
  20.     Wheel = Win32API.new('rm_mouse_wheel', 'intercept', 'v', 'v')
  21.     Wheel.call
  22.   end
  23. end
复制代码
其中 on_wheel 就是处理滚轮的回调函数,可以在里面扩充不同场景的处理,这里实现了在标题和结束场景时滚轮移动窗口光标的功能
参数列表中,delta 是滚动的范围;keys 是滚动同时还有什么虚拟键按下;x 是滚动时的屏幕鼠标 x 坐标;x 是滚动时的屏幕鼠标 y 坐标
具体用法可以参考:
http://msdn.microsoft.com/en-us/library/ms645617(VS.85).aspx

DLL 源代码:

  1. #include <windows.h>
  2. #include <stdio.h>

  3. typedef DWORD (*EVALFUNC)(LPCSTR);

  4. LONG oldWndProc;
  5. EVALFUNC eval;

  6. LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
  7.     switch(uMsg) {
  8.     case WM_MOUSEWHEEL:
  9.         char buf[128];
  10.         sprintf(buf, "Mouse.respond_to? :on_wheel and Mouse.on_wheel(%hd,%hd,%hd,%hd)",
  11.             wParam >> 16 & 0xffff, wParam & 0xffff, lParam & 0xffff, lParam >> 16 & 0xffff);
  12.         eval(buf);
  13.         return TRUE;
  14.     default:
  15.         return CallWindowProc((WNDPROC)oldWndProc, hWnd, uMsg, wParam, lParam);
  16.     }
  17. }

  18. void intercept() {
  19.     HMODULE hRGSS;
  20.     DWORD threadId = GetCurrentThreadId();
  21.     HWND hWnd = GetWindow(GetForegroundWindow(), GW_HWNDFIRST);
  22.     do {
  23.         if(threadId == GetWindowThreadProcessId(hWnd, NULL)) {
  24.             char className[12];
  25.             GetClassName(hWnd, className, 12);
  26.             if(!strcmp(className, "RGSS Player")) break;
  27.         }
  28.         hWnd = GetWindow(hWnd, GW_HWNDNEXT);
  29.     } while(hWnd);
  30.     oldWndProc = SetWindowLong(hWnd, GWL_WNDPROC, (LONG)WindowProc);
  31.     if(!(hRGSS = LoadLibrary("rgss102j.dll")))
  32.         hRGSS = LoadLibrary("rgss103j.dll");
  33.     eval = (EVALFUNC)GetProcAddress(hRGSS, "RGSSEval");
  34. }
复制代码

点评

还要麻烦你一下,鼠标滚轮在开始选单使用正常,但存取档窗口依然不行,该怎么做呢?  发表于 2010-8-23 11:14
辛苦了!非常感谢!  发表于 2010-8-23 10:32
回复 支持 反对

使用道具 举报

头像被屏蔽

Lv1.梦旅人 (禁止发言)

梦石
0
星屑
80
在线时间
3 小时
注册时间
2006-10-4
帖子
199
15
 楼主| 发表于 2010-8-23 11:13:45 | 只看该作者
提示: 作者被禁止或删除 内容自动屏蔽
回复 支持 反对

使用道具 举报

Lv1.梦旅人

梦石
0
星屑
61
在线时间
24 小时
注册时间
2008-8-5
帖子
1924
16
发表于 2010-8-23 12:50:34 | 只看该作者
本帖最后由 紫苏 于 2010-8-24 12:51 编辑

因为我只顺手写了两个比较简单的 o(╯□╰)o
用这个替换好了,顺便改进了一下代码,这样一来所有 Window_Selectable 都能响应滚轮了:
  1. class Class
  2.   def ===(aClass)
  3.     return self == aClass
  4.   end
  5. end

  6. module Mouse
  7.   # 累积 delta 值上限
  8.   ACC_DELTA = 120
  9.   def self.on_wheel(delta, keys, x, y)
  10.     # 此次滚动是否产生了效果
  11.     effect = false
  12.     # 累积 delta
  13.     @delta += delta
  14.     if @delta.abs >= ACC_DELTA
  15.       delta_idx = - @delta / ACC_DELTA
  16.       # 进行特定场景的特殊处理
  17.       case $scene.class
  18.       when Scene_Save, Scene_Load
  19.         savefile_windows = $scene.instance_eval {
  20.           @savefile_windows[@file_index].selected = false
  21.           @file_index = (@file_index + delta_idx) % 4
  22.           @savefile_windows[@file_index].selected = true
  23.         }
  24.         effect = true
  25.       end
  26.       # 枚举 Window_Selectable 可选择窗口对象
  27.       ObjectSpace.each_object(Window_Selectable) { |o|
  28.         # 光标索引上限
  29.         limit = o.instance_eval { @item_max }
  30.         # 如果可选择窗口未被释放、已激活、可见
  31.         if not o.disposed? and o.active and o.visible
  32.           # 移动光标
  33.           o.index = (o.index + delta_idx) % limit
  34.           effect = true
  35.         end
  36.       }
  37.       # 如果产生了效果就播放移动光标 SE
  38.       effect and $game_system.se_play($data_system.cursor_se)

  39.       # 清空累积的 delta
  40.       @delta = 0
  41.     end
  42.   end
  43.   # 如果第一次定义 Wheel 常量
  44.   if !defined? Wheel
  45.     # 初始化滚轮相关数据
  46.     Wheel = Win32API.new('rm_mouse_wheel', 'intercept', 'v', 'v')
  47.     Wheel.call
  48.     @delta = 0
  49.   end
  50. end
复制代码
以上代码作废,如果要用于默认工程可以用以下代码(20 楼给出的代码是针对楼主的存取档脚本所写的):
  1. module Mouse
  2.   # 累积 delta 值上限
  3.   WHEEL_DELTA = 120
  4.   def self.on_wheel(delta, keys, x, y)
  5.     # 此次滚动是否产生了效果
  6.     effect = false
  7.     # 累积 delta
  8.     @@delta += delta
  9.     if @@delta.abs >= WHEEL_DELTA
  10.       delta_idx = - @@delta / WHEEL_DELTA
  11.       # 进行特定场景的特殊处理
  12.       case $scene
  13.       when Scene_File
  14.         savefile_windows = $scene.instance_eval {
  15.           @savefile_windows[@file_index].selected = false
  16.           @file_index = (@file_index + delta_idx) % 4
  17.           @savefile_windows[@file_index].selected = true
  18.         }
  19.         effect = true
  20.       end
  21.       # 枚举 Window_Selectable 可选择窗口对象
  22.       ObjectSpace.each_object(Window_Selectable) { |o|
  23.         # 光标索引上限
  24.         limit = o.instance_eval { @item_max }
  25.         # 如果可选择窗口未被释放、已激活、可见
  26.         if not o.disposed? and o.active and o.visible
  27.           # 移动光标
  28.           o.index = (o.index + delta_idx) % limit
  29.           effect = true
  30.         end
  31.       }
  32.       # 如果产生了效果就播放移动光标 SE
  33.       effect and $game_system.se_play($data_system.cursor_se)

  34.       # 重新累积 delta
  35.       @@delta %= WHEEL_DELTA
  36.     end
  37.   end
  38.   # 如果第一次定义 Wheel 常量
  39.   if !defined? Wheel
  40.     # 初始化滚轮相关数据
  41.     Wheel = Win32API.new('rm_mouse_wheel', 'intercept', 'v', 'v')
  42.     Wheel.call
  43.     @@delta = 0
  44.   end
  45. end
复制代码

点评

呜,又有疑问了…………  发表于 2010-8-23 13:49
膜拜ing…………大人真乃神速啊!  发表于 2010-8-23 13:37
看得我目瞪口呆,难怪称你为“大人”…(一种敬佩感油然而生 - -b)  发表于 2010-8-23 12:55
回复 支持 反对

使用道具 举报

头像被屏蔽

Lv1.梦旅人 (禁止发言)

梦石
0
星屑
80
在线时间
3 小时
注册时间
2006-10-4
帖子
199
17
 楼主| 发表于 2010-8-23 13:48:50 | 只看该作者
提示: 作者被禁止或删除 内容自动屏蔽
回复 支持 反对

使用道具 举报

Lv1.梦旅人

梦石
0
星屑
61
在线时间
24 小时
注册时间
2008-8-5
帖子
1924
18
发表于 2010-8-23 14:24:38 | 只看该作者
*需求*存档改为 16 个的脚本
回复 支持 反对

使用道具 举报

头像被屏蔽

Lv1.梦旅人 (禁止发言)

梦石
0
星屑
80
在线时间
3 小时
注册时间
2006-10-4
帖子
199
19
 楼主| 发表于 2010-8-23 14:36:13 | 只看该作者
提示: 作者被禁止或删除 内容自动屏蔽
回复 支持 反对

使用道具 举报

Lv1.梦旅人

梦石
0
星屑
61
在线时间
24 小时
注册时间
2008-8-5
帖子
1924
20
发表于 2010-8-24 12:40:26 | 只看该作者
经测试发现退出游戏(不过是否异常退出)时卡死是由于我那个根除 Hangup 的脚本没有捕获到异常导致的,原因是这个脚本修改了 Class#===,而这个继承自 Module#=== 的方法是被 Ruby 的异常处理机制使用了的(可能是获取回溯信息),这个脚本的重载方法使得 Module#=== 失去了原有的效果,导致异常处理不正常
最后更新版:
  1. module Mouse
  2.   # 累积 delta 值上限
  3.   WHEEL_DELTA = 120
  4.   def self.on_wheel(delta, keys, x, y)
  5.     # 此次滚动是否产生了效果
  6.     effect = false
  7.     # 累积 delta
  8.     @@delta += delta
  9.     if @@delta.abs >= WHEEL_DELTA
  10.       delta_idx = - @@delta / WHEEL_DELTA
  11.       # 进行特定场景的特殊处理
  12.       case $scene
  13.       when Scene_File
  14.         savefile_windows = $scene.instance_eval {
  15.           @savefile_windows[@file_index - @offset].selected = false
  16.           @file_index = (@file_index + delta_idx) % System::SAVEFILE_AMOUNT
  17.           # 更新存档页面偏移量
  18.           if @file_index - @offset >= 4
  19.             @offset = @file_index - 3
  20.             refresh_savefile_windows
  21.           elsif @offset - @file_index >= 1
  22.             @offset = @file_index
  23.             refresh_savefile_windows
  24.           end
  25.           @savefile_windows[@file_index - @offset].selected = true
  26.         }
  27.         effect = true
  28.       end
  29.       # 枚举 Window_Selectable 可选择窗口对象
  30.       ObjectSpace.each_object(Window_Selectable) { |o|
  31.         # 光标索引上限
  32.         limit = o.instance_eval { @item_max }
  33.         # 如果可选择窗口未被释放、已激活、可见
  34.         if not o.disposed? and o.active and o.visible
  35.           # 移动光标
  36.           o.index = (o.index + delta_idx) % limit
  37.           effect = true
  38.         end
  39.       }
  40.       # 如果产生了效果就播放移动光标 SE
  41.       effect and $game_system.se_play($data_system.cursor_se)

  42.       # 重新累积 delta
  43.       @@delta %= WHEEL_DELTA
  44.     end
  45.   end
  46.   # 如果第一次定义 Wheel 常量
  47.   if !defined? Wheel
  48.     # 初始化滚轮相关数据
  49.     Wheel = Win32API.new('rm_mouse_wheel', 'intercept', 'v', 'v')
  50.     Wheel.call
  51.     @@delta = 0
  52.   end
  53. end
复制代码

评分

参与人数 2星屑 +500 收起 理由
IamI + 486 认可答案
hongqizhen + 14 认可答案

查看全部评分

回复 支持 反对

使用道具 举报

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

本版积分规则

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

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

GMT+8, 2024-11-24 03:20

Powered by Discuz! X3.1

© 2001-2013 Comsenz Inc.

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