Project1

标题: RGSS能处理窗口自定义消息吗? [打印本页]

作者: SailCat    时间: 2018-1-12 15:07
标题: RGSS能处理窗口自定义消息吗?
照着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

作者: fux2    时间: 2018-1-12 15:32
啊,其实方法倒是对了,但是ruby的函数肯定不能用来做回调函数的……
https://rpg.blue/thread-370060-1-1.html
具体使用方法参考本文即可。
上面的方法是根据yangff的无DLL鼠标修改而来,过滤了消息类型。
作者: 晴兰    时间: 2018-1-12 18:24
提示: 作者被禁止或删除 内容自动屏蔽
作者: 不死鸟之翼    时间: 2018-1-13 23:52
本帖最后由 不死鸟之翼 于 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 星屑  [记录]


作者: 不死鸟之翼    时间: 2018-1-14 00:16
如果不要DLL的话也很好搞 编译完了之后拿一个反汇编器(比如OD)把核心代码copy走,然后Ruby里申请一块内存填进去,给EXECUTE权限就完了。传回数据也是RGSSEval。

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




欢迎光临 Project1 (https://rpg.blue/) Powered by Discuz! X3.1