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

Project1

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

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

[复制链接]

Lv3.寻梦者

梦石
0
星屑
1803
在线时间
133 小时
注册时间
2013-10-6
帖子
193
1
发表于 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
2
发表于 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-5-6 07:09

Powered by Discuz! X3.1

© 2001-2013 Comsenz Inc.

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