Project1
标题:
如何在存读档窗口使用鼠标滚轮?
[打印本页]
作者:
hongqizhen
时间:
2010-8-18 11:06
提示:
作者被禁止或删除 内容自动屏蔽
作者:
306329484
时间:
2010-8-18 11:43
完整鼠标系统(四方向).rar
(248.72 KB, 下载次数: 104)
2010-8-18 11:38 上传
点击文件名下载附件
这是我在以前的66中无意中找到的
很方便
另外给你八方向的
完整鼠标系统(八方向)V2.0.rar
(502.99 KB, 下载次数: 109)
2010-8-18 11:41 上传
点击文件名下载附件
还有记得,把"\Graphics\Icons"中的文件全拿出来
这可是绝种的东西
作者:
hongqizhen
时间:
2010-8-18 12:23
提示:
作者被禁止或删除 内容自动屏蔽
作者:
hongqizhen
时间:
2010-8-18 17:18
提示:
作者被禁止或删除 内容自动屏蔽
作者:
BBBBB6
时间:
2010-8-18 17:19
怎样做啊,那太技术性了吧。。。
键盘党表示莫名其妙地飘过。。。
作者:
紫苏
时间:
2010-8-19 01:37
鼠标滚轮滚动事件会发送 WM_MOUSEWHEEL 消息到焦点窗口中,在 RM 中可以:
1、在 DLL 里使用系统钩子拦截 WM_MOUSEWHEEL 并处理
2、在 DLL 里替换默认的窗口过程函数,单独处理 WM_MOUSEWHEEL 消息
两种方法都不是像判断按键那样每帧进行,而是以操作系统在滚轮实际滚动时通知你的形式进行
可以在处理 WM_MOUSEWHEEL 消息时判断场景是否为存档场景,然后执行一段代码,这段代码可以在 RM 里使用 Proc 维护,并在 DLL 里通过 RGSSEval 调用
作者:
暗夜惊戈
时间:
2010-8-19 08:13
提示:
作者被禁止或删除 内容自动屏蔽
作者:
暗夜惊戈
时间:
2010-8-19 08:14
提示:
作者被禁止或删除 内容自动屏蔽
作者:
暗夜惊戈
时间:
2010-8-19 08:16
提示:
作者被禁止或删除 内容自动屏蔽
作者:
暗夜惊戈
时间:
2010-8-19 08:16
提示:
作者被禁止或删除 内容自动屏蔽
作者:
hongqizhen
时间:
2010-8-19 08:23
提示:
作者被禁止或删除 内容自动屏蔽
作者:
紫苏
时间:
2010-8-19 14:08
感谢,您的意思是必须把相应的功能封装在dll中,并在脚本中调用是吗?是否有具体的例子呢?
hongqizhen 发表于 2010-8-18 12:23
在脚本里还是在 DLL 里调用取决于设计者,通常在解释性语言里调用更方便维护和调试,所以可以采取这个选择,但是替换窗口过程的过程最好还是写在 DLL 里,因为如果要在 Ruby 里操作本地函数和函数指针,还需要进行一系列地址偏移的计算
如果目前 XP 的鼠标脚本里没有这个功能就说明没有人写过,要是不急可以等我明天下了 VS 再帮你写一个
作者:
fux2
时间:
2010-8-19 16:00
我到现在也不知道滚轮的键值是多少。
作者:
紫苏
时间:
2010-8-20 11:31
rm_mouse_wheel.rar
(21.14 KB, 下载次数: 166)
2010-8-20 11:15 上传
点击文件名下载附件
附件里是预编译的 DLL,目标环境是 x86
将 DLL 放在游戏根目录,然后在 RM 里加入如下脚本:
class Class
def ===(aClass)
return self == aClass
end
end
module Mouse
def self.on_wheel(delta, keys, x, y)
case $scene.class
when Scene_Title, Scene_End
command_window = $scene.instance_eval { @command_window }
item_max = command_window.instance_eval { @item_max }
command_window and
command_window.index =
[0, [item_max - 1, command_window.index - delta / 120].min].max
when Scene_Item
# ...
end
end
if !defined? Wheel
Wheel = Win32API.new('rm_mouse_wheel', 'intercept', 'v', 'v')
Wheel.call
end
end
复制代码
其中 on_wheel 就是处理滚轮的回调函数,可以在里面扩充不同场景的处理,这里实现了在标题和结束场景时滚轮移动窗口光标的功能
参数列表中,delta 是滚动的范围;keys 是滚动同时还有什么虚拟键按下;x 是滚动时的屏幕鼠标 x 坐标;x 是滚动时的屏幕鼠标 y 坐标
具体用法可以参考:
http://msdn.microsoft.com/en-us/library/ms645617
(VS.85).aspx
DLL 源代码:
#include <windows.h>
#include <stdio.h>
typedef DWORD (*EVALFUNC)(LPCSTR);
LONG oldWndProc;
EVALFUNC eval;
LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
switch(uMsg) {
case WM_MOUSEWHEEL:
char buf[128];
sprintf(buf, "Mouse.respond_to? :on_wheel and Mouse.on_wheel(%hd,%hd,%hd,%hd)",
wParam >> 16 & 0xffff, wParam & 0xffff, lParam & 0xffff, lParam >> 16 & 0xffff);
eval(buf);
return TRUE;
default:
return CallWindowProc((WNDPROC)oldWndProc, hWnd, uMsg, wParam, lParam);
}
}
void intercept() {
HMODULE hRGSS;
DWORD threadId = GetCurrentThreadId();
HWND hWnd = GetWindow(GetForegroundWindow(), GW_HWNDFIRST);
do {
if(threadId == GetWindowThreadProcessId(hWnd, NULL)) {
char className[12];
GetClassName(hWnd, className, 12);
if(!strcmp(className, "RGSS Player")) break;
}
hWnd = GetWindow(hWnd, GW_HWNDNEXT);
} while(hWnd);
oldWndProc = SetWindowLong(hWnd, GWL_WNDPROC, (LONG)WindowProc);
if(!(hRGSS = LoadLibrary("rgss102j.dll")))
hRGSS = LoadLibrary("rgss103j.dll");
eval = (EVALFUNC)GetProcAddress(hRGSS, "RGSSEval");
}
复制代码
作者:
hongqizhen
时间:
2010-8-23 11:13
提示:
作者被禁止或删除 内容自动屏蔽
作者:
紫苏
时间:
2010-8-23 12:50
本帖最后由 紫苏 于 2010-8-24 12:51 编辑
因为我只顺手写了两个比较简单的 o(╯□╰)o
用这个替换好了,顺便改进了一下代码,这样一来所有 Window_Selectable 都能响应滚轮了:
class Class
def ===(aClass)
return self == aClass
end
end
module Mouse
# 累积 delta 值上限
ACC_DELTA = 120
def self.on_wheel(delta, keys, x, y)
# 此次滚动是否产生了效果
effect = false
# 累积 delta
@delta += delta
if @delta.abs >= ACC_DELTA
delta_idx = - @delta / ACC_DELTA
# 进行特定场景的特殊处理
case $scene.class
when Scene_Save, Scene_Load
savefile_windows = $scene.instance_eval {
@savefile_windows[@file_index].selected = false
@file_index = (@file_index + delta_idx) % 4
@savefile_windows[@file_index].selected = true
}
effect = true
end
# 枚举 Window_Selectable 可选择窗口对象
ObjectSpace.each_object(Window_Selectable) { |o|
# 光标索引上限
limit = o.instance_eval { @item_max }
# 如果可选择窗口未被释放、已激活、可见
if not o.disposed? and o.active and o.visible
# 移动光标
o.index = (o.index + delta_idx) % limit
effect = true
end
}
# 如果产生了效果就播放移动光标 SE
effect and $game_system.se_play($data_system.cursor_se)
# 清空累积的 delta
@delta = 0
end
end
# 如果第一次定义 Wheel 常量
if !defined? Wheel
# 初始化滚轮相关数据
Wheel = Win32API.new('rm_mouse_wheel', 'intercept', 'v', 'v')
Wheel.call
@delta = 0
end
end
复制代码
以上代码作废,如果要用于默认工程可以用以下代码(20 楼给出的代码是针对楼主的存取档脚本所写的):
module Mouse
# 累积 delta 值上限
WHEEL_DELTA = 120
def self.on_wheel(delta, keys, x, y)
# 此次滚动是否产生了效果
effect = false
# 累积 delta
@@delta += delta
if @@delta.abs >= WHEEL_DELTA
delta_idx = - @@delta / WHEEL_DELTA
# 进行特定场景的特殊处理
case $scene
when Scene_File
savefile_windows = $scene.instance_eval {
@savefile_windows[@file_index].selected = false
@file_index = (@file_index + delta_idx) % 4
@savefile_windows[@file_index].selected = true
}
effect = true
end
# 枚举 Window_Selectable 可选择窗口对象
ObjectSpace.each_object(Window_Selectable) { |o|
# 光标索引上限
limit = o.instance_eval { @item_max }
# 如果可选择窗口未被释放、已激活、可见
if not o.disposed? and o.active and o.visible
# 移动光标
o.index = (o.index + delta_idx) % limit
effect = true
end
}
# 如果产生了效果就播放移动光标 SE
effect and $game_system.se_play($data_system.cursor_se)
# 重新累积 delta
@@delta %= WHEEL_DELTA
end
end
# 如果第一次定义 Wheel 常量
if !defined? Wheel
# 初始化滚轮相关数据
Wheel = Win32API.new('rm_mouse_wheel', 'intercept', 'v', 'v')
Wheel.call
@@delta = 0
end
end
复制代码
作者:
hongqizhen
时间:
2010-8-23 13:48
提示:
作者被禁止或删除 内容自动屏蔽
作者:
紫苏
时间:
2010-8-23 14:24
*需求*存档改为 16 个的脚本
作者:
hongqizhen
时间:
2010-8-23 14:36
提示:
作者被禁止或删除 内容自动屏蔽
作者:
紫苏
时间:
2010-8-24 12:40
经测试发现退出游戏(不过是否异常退出)时卡死是由于我那个根除 Hangup 的脚本没有捕获到异常导致的,原因是这个脚本修改了 Class#===,而这个继承自 Module#=== 的方法是被 Ruby 的异常处理机制使用了的(可能是获取回溯信息),这个脚本的重载方法使得 Module#=== 失去了原有的效果,导致异常处理不正常
最后更新版:
module Mouse
# 累积 delta 值上限
WHEEL_DELTA = 120
def self.on_wheel(delta, keys, x, y)
# 此次滚动是否产生了效果
effect = false
# 累积 delta
@@delta += delta
if @@delta.abs >= WHEEL_DELTA
delta_idx = - @@delta / WHEEL_DELTA
# 进行特定场景的特殊处理
case $scene
when Scene_File
savefile_windows = $scene.instance_eval {
@savefile_windows[@file_index - @offset].selected = false
@file_index = (@file_index + delta_idx) % System::SAVEFILE_AMOUNT
# 更新存档页面偏移量
if @file_index - @offset >= 4
@offset = @file_index - 3
refresh_savefile_windows
elsif @offset - @file_index >= 1
@offset = @file_index
refresh_savefile_windows
end
@savefile_windows[@file_index - @offset].selected = true
}
effect = true
end
# 枚举 Window_Selectable 可选择窗口对象
ObjectSpace.each_object(Window_Selectable) { |o|
# 光标索引上限
limit = o.instance_eval { @item_max }
# 如果可选择窗口未被释放、已激活、可见
if not o.disposed? and o.active and o.visible
# 移动光标
o.index = (o.index + delta_idx) % limit
effect = true
end
}
# 如果产生了效果就播放移动光标 SE
effect and $game_system.se_play($data_system.cursor_se)
# 重新累积 delta
@@delta %= WHEEL_DELTA
end
end
# 如果第一次定义 Wheel 常量
if !defined? Wheel
# 初始化滚轮相关数据
Wheel = Win32API.new('rm_mouse_wheel', 'intercept', 'v', 'v')
Wheel.call
@@delta = 0
end
end
复制代码
作者:
hongqizhen
时间:
2010-8-24 13:54
提示:
作者被禁止或删除 内容自动屏蔽
欢迎光临 Project1 (https://rpg.blue/)
Powered by Discuz! X3.1