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

Project1

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

[有事请教] RGSS能处理窗口自定义消息吗?

[复制链接]

Lv5.捕梦者 (版主)

遠航の猫咪

梦石
3
星屑
22432
在线时间
2335 小时
注册时间
2005-10-15
帖子
1160

开拓者

跳转到指定楼层
1
发表于 2018-1-12 15:07:22 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式

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

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

x
照着vb处理的方法用rgss写了一段,无法运行……

有对api比较了解的大牛看看什么情况……?

RUBY 代码复制
  1. module Kernel
  2.   class << self
  3.  
  4.     GetWindowLong = Win32API.new("user32", "GetWindowLong", "ii", "i")
  5.     SetWindowLong = Win32API.new("user32", "SetWindowLong", "iii", "i")
  6.     CallWindowProc = Win32API.new("user32", "CallWindowProc", "iiiii", "i")
  7.  
  8.  
  9.     def hwnd
  10.       Win32API.new("user32", "GetActiveWindow", "", "i").call
  11.     end
  12.  
  13.     def wm_proc(hwnd, msg, wparam, lparam)
  14.       if msg == 522 # WM_MOUSEWHEEL
  15.         p 1
  16.       else
  17.         CallWindowProc.call(@old_proc_addr, hwnd, msg, wparam, lparam)
  18.       end
  19.     end
  20.  
  21.     def handle
  22.       @old_proc_addr = GetWindowLong.call(hwnd, -4)
  23.       @new_proc_addr = method(:wm_proc).object_id * 2
  24.       SetWindowLong.call(hwnd, -4, @new_proc_addr)
  25.     end
  26.  
  27.     def unhandle
  28.       SetWindowLong.call(hwnd, -4, @old_proc_addr)
  29.     end
  30.   end
  31. end
  32.  
  33. Kernel.handle
SailCat (小猫子·要开心一点) 共上站 24 次,发表过 11 篇文章 上 次 在: [2006年01月28日11:41:18 星期六] 从 [162.105.120.91] 到本站一游。

Lv5.捕梦者 (管理员)

老黄鸡

梦石
0
星屑
39645
在线时间
7484 小时
注册时间
2009-7-6
帖子
13483

开拓者贵宾

2
发表于 2018-1-12 15:32:43 | 只看该作者
啊,其实方法倒是对了,但是ruby的函数肯定不能用来做回调函数的……
https://rpg.blue/thread-370060-1-1.html
具体使用方法参考本文即可。
上面的方法是根据yangff的无DLL鼠标修改而来,过滤了消息类型。

点评

我惊了,忘了撤销售价  发表于 2018-1-12 16:29
竟然回调函数要写成二进制代码才行……没法,一写汇编脑仁儿疼……上次写那个RGBA-BGRA的代码折腾了我快一个星期……  发表于 2018-1-12 16:09
这附件也太贵了……!!!  发表于 2018-1-12 15:43
RGDirect - DirectX驱动的RGSS,点我了解.
RM全系列成套系统定制请联系QQ1213237796
不接受对其他插件维护的委托
回复 支持 反对

使用道具 举报

头像被屏蔽

Lv2.观梦者 (禁止发言)

梦石
0
星屑
653
在线时间
3774 小时
注册时间
2011-2-26
帖子
1839

开拓者

3
发表于 2018-1-12 18:24:54 | 只看该作者
提示: 作者被禁止或删除 内容自动屏蔽
回复 支持 反对

使用道具 举报

Lv3.寻梦者

梦石
0
星屑
1803
在线时间
133 小时
注册时间
2013-10-6
帖子
193
4
发表于 2018-1-13 23:52:53 | 只看该作者
本帖最后由 不死鸟之翼 于 2018-1-13 23:54 编辑

这是一个典型的脚本语言和原生代码的互操作问题,回调参数一定需要是原生代码。
因为Win32 API层是C/C++的天下,所以我们用C/C++处理这类问题显然比手写机器指令舒服得多(我特么也脑仁儿疼啊)。
主要思路是Ruby到C++用Win32API call通信,回来就用RGSSEval。

大概写了一段,编译成DLL并导出Inject函数即可。

RUBY 代码复制
  1. using RGSSEval_t = int(__cdecl*)(const char*);
  2.  
  3. RGSSEval_t RGSSEval = nullptr;
  4. WNDPROC OldWindowProc = nullptr;
  5. string rubyCallbackFunc;
  6.  
  7. LRESULT CALLBACK CustomWindowsProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  8. {
  9.         switch (uMsg) {
  10.         case WM_MOUSEWHEEL: {
  11.                 int zDelta = GET_WHEEL_DELTA_WPARAM(wParam);
  12.                 int xPos = GET_X_LPARAM(lParam);
  13.                 int yPos = GET_Y_LPARAM(lParam);
  14.                 int fwKeys = GET_KEYSTATE_WPARAM(wParam);
  15.                 POINT clientPt = { xPos,yPos };
  16.                 ScreenToClient(hWnd, &clientPt);
  17.                 stringstream expr;
  18.                 expr << rubyCallbackFunc << "(" << zDelta << "," << clientPt.x << "," << clientPt.y << "," << fwKeys << ")";
  19.                 RGSSEval(expr.str().c_str());
  20.                 return CallWindowProcA(OldWindowProc, hWnd, uMsg, wParam, lParam);
  21.         }
  22.         default:
  23.                 return CallWindowProcA(OldWindowProc, hWnd, uMsg, wParam, lParam);
  24.         }
  25. }
  26.  
  27. INT WINAPI Inject(const char* callbackName)
  28. {
  29.         HMODULE hModule=GetModuleHandleA("RGSS202E.dll"); //Change this if necessary
  30.         if (hModule) {
  31.                 RGSSEval = (RGSSEval_t)GetProcAddress(hModule, "RGSSEval");
  32.                 if (RGSSEval) {
  33.                         HWND hWnd = GetActiveWindow();
  34.                         if (hWnd) {
  35.                                 OldWindowProc = (WNDPROC)SetWindowLongA(hWnd, GWL_WNDPROC, (LONG)CustomWindowsProc);
  36.                                 rubyCallbackFunc = callbackName;
  37.                                 return TRUE;
  38.                         }
  39.                 }
  40.         }
  41.         return FALSE;
  42. }


Ruby侧提供回调函数

RUBY 代码复制
  1. def on_mouse_wheel(zDelta,xPos,yPos,fwKeys)
  2.   p "delta=#{zDelta} mouse_x=#{xPos} mouse_y=#{yPos} modifiers=#{fwKeys}"
  3. end
  4.  
  5. fun=Win32API.new('WndProc.dll','Inject','p','i')
  6. if fun.call('on_mouse_wheel')==0
  7.   p 'Failed'
  8. end


fwKeys当特定键按下时特定位为1,详情参考MSDN。

效果图



如果需要处理其他消息的话在窗口过程里增加即可。
因为窗口过程是在主消息循环中分发消息时调用的,所以不会有线程同步问题。

WNDPROC.zip

101.49 KB, 下载次数: 2

售价: 5 星屑  [记录]

点评

虽然同一个线程,但是还是有可能会碰到GVML(GIL)  发表于 2018-1-14 20:38
感谢解决,但是“编译成DLL”……这不是我写插件的初衷了……我还是自己研究下无DLL的方案吧  发表于 2018-1-14 00:09
←你看到一只经常潜水的萌新。
回复 支持 反对

使用道具 举报

Lv3.寻梦者

梦石
0
星屑
1803
在线时间
133 小时
注册时间
2013-10-6
帖子
193
5
发表于 2018-1-14 00:16:01 | 只看该作者
如果不要DLL的话也很好搞 编译完了之后拿一个反汇编器(比如OD)把核心代码copy走,然后Ruby里申请一块内存填进去,给EXECUTE权限就完了。传回数据也是RGSSEval。

另外 我点评我自己的帖子之后,其他点评了的人是否会收到通知?麻烦告知

点评

已收到通知,哈哈  发表于 2018-1-14 09:51
thx&test  发表于 2018-1-14 04:04
应该是会有的吧,就是“XXX和您在同一层点评了……”那个通知,我收到过。  发表于 2018-1-14 00:39
←你看到一只经常潜水的萌新。
回复 支持 反对

使用道具 举报

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

本版积分规则

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

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

GMT+8, 2024-4-24 20:06

Powered by Discuz! X3.1

© 2001-2013 Comsenz Inc.

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