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

Project1

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

[RMVX发布] 解决脚本改分辨率潜在问题(欢迎进入讨论)

[复制链接]

Lv1.梦旅人

梦石
0
星屑
110
在线时间
953 小时
注册时间
2007-4-25
帖子
805
1
发表于 2011-4-11 03:41:55 | 显示全部楼层
精准获取窗口句柄 其中API牵涉到前台(焦点)窗口,
当没把窗口显示出来的时候,会否一直停在获取窗口句柄中呢? (希望你能帮我求证下.)

当 Ruby 脚本开始被 RM 嵌入的解释器执行时,窗口已经显示了,除非之后又刻意让它隐藏。GetWindow 应该能获取到隐藏的窗口,毕竟隐藏窗口并不会改变其 Z 次序,而且连被销毁的窗口的句柄都能引用到,又何况只是被隐藏的。

不过没有测试过,不敢下定论。

“精确获取窗口句柄”这个脚本有以下问题,虽然出现概率极低:
1、GetWindow 可能导致无限循环,或是获取到已经被销毁的窗口句柄(这个在 MSDN 的文档里有说明);
2、由于是从前台窗口开始查找,如果前台窗口的类型不同,就可能找不到 RM 的窗口(比如前台窗口是“总在最上”的窗口,但 RM 窗口不是);
3、只进行了线程标识的匹配,然后一个线程可以创建多个窗口。如果 RM 主线程被用来创建别的(辅助)窗口,很可能就匹配不到预期的主窗口了;
4、只进行了窗口类名的匹配,而多个窗口可以是同一类(即属于一种窗口实例,有相同的窗口类名,比如 "RGSS Player")。

相比之下更好的办法 MSDN 也提到了,就是使用 EnumWindows,但 EnumWindows 只能解决上述第一个问题。同时由于 EnumWindows 需要回调函数,而 RM 默认无法编写本地代码,所以纯 Ruby 只能用 GetWindow。真·后台运行用的就是 EnumWindows,因为是 DLL 管理的。

现在看来,这个脚本离精确还差得远。真正意义上的精确这两种方法做到了:
http://rpg.blue/forum.php?mod=viewthread&tid=157287
http://rpg.blue/forum.php?mod=viewthread&tid=160672
前者是劫持 CreateWindow,后者是逆向工程。



还是等真正的XP游戏窗口启动控制移植VX吧。。。

本来我都移植了一半了,但后来因为全屏那块和 XP 不太一样就放弃了,以后也不打算继续弄,反正最重要的分辨率功能 David、神思、八云等人都发过逆向的方法了嘛。
[email protected]:~> repeat 1 fortune
Matz is nice, so we are nice.
回复 支持 反对

使用道具 举报

Lv1.梦旅人

梦石
0
星屑
110
在线时间
953 小时
注册时间
2007-4-25
帖子
805
2
发表于 2011-4-12 02:43:00 | 显示全部楼层
回复 一箭烂YiJL 的帖子
while是RGSS开始且窗口最小化时停下,这写法似乎不太好,有更好的写法么?

处理 WM_SYSCOMMAND 消息,当 wParam 是 SC_MINIMIZE 的时候就是一个最小化事件发生之后。不过……在没有扩展的情况下纯 Ruby 并不能良好地消息处理。
[email protected]:~> repeat 1 fortune
Matz is nice, so we are nice.
回复 支持 反对

使用道具 举报

Lv1.梦旅人

梦石
0
星屑
110
在线时间
953 小时
注册时间
2007-4-25
帖子
805
3
发表于 2011-4-12 14:43:24 | 显示全部楼层
回复 summer92 的帖子
应该是Rgss又把分辨率改回来了?

是 VX 在渲染的时候按照窗口的实际矩形尺寸在渲染(通过 GetWindowRect 之类的),这一点和 XP 固定在一个预设的矩形中渲染不同。
[email protected]:~> repeat 1 fortune
Matz is nice, so we are nice.
回复 支持 反对

使用道具 举报

Lv1.梦旅人

梦石
0
星屑
110
在线时间
953 小时
注册时间
2007-4-25
帖子
805
4
发表于 2011-4-13 06:16:43 | 显示全部楼层
回复 一箭烂YiJL 的帖子
那么也就是一定要修改WindowProc函数了。

不一定,可以通过SetWindowsHookEx注册一个窗口消息的过滤器,不过本质上还是和替换 WIndowProc 一样是建立了一个自己的钩子函数。

听您说Graphics.update会导致GetMessage无法获得,那么纯Ruby就不可能了。(PeekMessage貌似不是好的办法。)

GetMessage 可以获得,但不会获得全部,有相当一部分消息会被 RGSS 底层的消息循环取走,这个在沉影的鼠标贴里和她讨论过。PeekMessage 只是不从消息队列拿走消息,仍然不能让消息掠夺的现象改观。

实际上我想问的是while的语法,我用while的目的是让RGSS暂停,当RM窗口为前台窗口的时候,才继续(才Graphics.resize_screen)。Ruby有一个能够暂停的方法么?一直循环在这个空的循环中似乎不是太好。

这个和后台运行的判断方法一样,后台运行是处理 WM_ACTIVATEAPP——一个当窗口获得键盘焦点时系统会发送的消息。要是纯 Ruby 能做到,后台运行就不需要 DLL 了。纯 Ruby 的话只能使用 WaitForSingleObject 或类似的函数,但 NT 并没有预设类似得到焦点的事件供 WaitForSingleObject 使用。

在 Ruby 中可以通过睡眠线程让当前线程的执行暂停。

  1. sleep(0.02)
复制代码
可以考虑在空的循环中添上 sleep 让线程睡眠,这是以判断的敏感度换取了 CPU 时间——在线程睡眠的时候 CPU 可以去干别的事,但同时这个判断相比之前敏感度降低了。这之间的差别在单核 CPU 架构下尤为明显,CPU 唯一内核的大部分时间都被这个空循环占用,在处理系统中其它程序的时候就没那么敏感了,对于最终用户来说,他们感觉到的就是一个字:“卡”。
[email protected]:~> repeat 1 fortune
Matz is nice, so we are nice.
回复 支持 反对

使用道具 举报

Lv1.梦旅人

梦石
0
星屑
110
在线时间
953 小时
注册时间
2007-4-25
帖子
805
5
发表于 2011-4-15 00:40:09 | 显示全部楼层
回复 一箭烂YiJL 的帖子
表示纯sleep无参数

无参数时使用默认值 0,表示永远睡眠。

由于我这台机是双核,在有sleep的情况下,第一的CPU(单核的反应?)的反应比第二的CPU使用量较为高,反而不用时第一的CPU(单核的反应?)的反应比第二的CPU使用量较为低。

没看明白什么意思,你是说添加了 sleep 反而提高了 CPU 使用率?断无这个道理,不知道你是怎么测试的。
[email protected]:~> repeat 1 fortune
Matz is nice, so we are nice.
回复 支持 反对

使用道具 举报

Lv1.梦旅人

梦石
0
星屑
110
在线时间
953 小时
注册时间
2007-4-25
帖子
805
6
发表于 2011-4-16 01:41:35 | 显示全部楼层
一箭烂YiJL 发表于 2011-4-15 15:05
回复 苏小脉 的帖子

测了一下,sleep 默认参数为 0 这个好像是《Programming Ruby》的文档失误,为 0 时 sleep 应该是立即返回,昨天我是依据这个说的,很明显错了。

但如果没有传递 sleep 参数,那确实是表示永久睡眠,这是各种文档都明确说明的。process.c 中 sleep 的实现也是如此显示:
  1. static VALUE
  2. rb_f_sleep(int argc, VALUE *argv)
  3. {
  4.     time_t beg, end;

  5.     beg = time(0);
  6.     if (argc == 0) {
  7.         rb_thread_sleep_forever();
  8.     }
  9.     else if (argc == 1) {
  10.         rb_thread_wait_for(rb_time_interval(argv[0]));
  11.     }
  12.     else {
  13.         rb_raise(rb_eArgError, "wrong number of arguments (%d for 0..1)", argc);
  14.     }

  15.     end = time(0) - beg;

  16.     return INT2FIX(end);
  17. }
复制代码
当没有参数时调用 rb_thread_sleep_forever。

RM 要么是刻意做了什么手脚,要么就是在嵌入解释器的时候没考虑周全产生了 BUG。

我双核,任务管理器的时候会有两个CPU显示块,用sleep和不用sleep都各有高低,分别相反。

CPU 在执行 Ruby 程序的时候如果得到空闲,自然又跑去执行别的程序了。Ruby 睡眠了线程就相当于自动放弃了当前的时间片。你应该看的是 ruby.exe (或者 Game.exe,如果用的是 RM)这个进程的 CPU 使用率。

点评

嗯,无论是嵌入 Ruby 还是做本地扩展,最需要考虑的问题就是并发(线程)问题了。  发表于 2011-4-17 00:36
RM F1手册也这么写,但不能排除其它线程的因素。我这台电脑如见资源贫乏,没有Ruby.exe。上述其余的都没什么认识...┘口└  发表于 2011-4-16 20:45
[email protected]:~> repeat 1 fortune
Matz is nice, so we are nice.
回复 支持 反对

使用道具 举报

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

本版积分规则

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

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

GMT+8, 2024-5-27 08:33

Powered by Discuz! X3.1

© 2001-2013 Comsenz Inc.

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