赞 | 3 |
VIP | 1 |
好人卡 | 40 |
积分 | 1 |
经验 | 93188 |
最后登录 | 2020-7-27 |
在线时间 | 1379 小时 |
Lv1.梦旅人
- 梦石
- 0
- 星屑
- 76
- 在线时间
- 1379 小时
- 注册时间
- 2012-7-5
- 帖子
- 1698
|
本帖最后由 kuerlulu 于 2016-5-25 22:32 编辑
- #--------------------------------------------------------------------------
- # ● 紫苏前辈的获取窗口句柄
- # 部分细节已修改( by 晴兰 )
- #--------------------------------------------------------------------------
- module Kernel
- #--------------------------------------------------------------------------
- # ● 需要的 Windows API 函数
- #--------------------------------------------------------------------------
- GetWindowThreadProcessId = Win32API.new("user32", "GetWindowThreadProcessId", "LP", "L")
- GetWindow = Win32API.new("user32", "GetWindow", "LL", "L")
- GetClassName = Win32API.new("user32", "GetClassName", "LPL", "L")
- GetCurrentThreadId = Win32API.new("kernel32", "GetCurrentThreadId", "V", "L")
- GetForegroundWindow = Win32API.new("user32", "GetForegroundWindow", "V", "L")
- #--------------------------------------------------------------------------
- # ● 获取窗口句柄
- #--------------------------------------------------------------------------
- def hwnd
- # 获取调用线程(RM 的主线程)的进程标识
- threadID = GetCurrentThreadId.call
- # 获取 Z 次序中最靠前的窗口
- hWnd = GetWindow.call(GetForegroundWindow.call, 0)
- # 枚举所有窗口
- while hWnd != 0
- # 如果创建该窗口的线程标识匹配本线程标识
- if threadID == GetWindowThreadProcessId.call(hWnd, 0)
- # 分配一个 12 个字节的缓冲区
- className = " " * 12 # ●
- # 获取该窗口的类名
- GetClassName.call(hWnd, className, 12) # ●
- # 如果匹配 RGSS Player 则跳出循环
- break if className[0, 11] == "RGSS Player"
- end
- # 获取下一个窗口
- hWnd = GetWindow.call(hWnd, 2)
- end
- return hWnd
- end
- end
- HWND = hwnd
- #--------------------------------------------------------------------------
- # ● RMXP用 Graphics.snap_to_bitmap
- # 就算窗口被遮盖或者显示不全也可以正常截图
- # 附赠: Graphics.snap_to_clipboard
- # 截图到剪贴板
- # ● 作者:晴兰 @ rpg.blue
- # 使用到紫苏前辈的获取窗口句柄脚本,其他部分为原创
- #--------------------------------------------------------------------------
- module SAFX
- module_function
- class ::Integer; def pack; self; end; def to_param; 'i'; end; def ord; self; end; end
- class ::String;def pack; [self].pack('p').unpack('L').first; end; def to_param; 'p'; end; end
- def api(dll,func)
- lambda{|*args|
- Win32API.new(dll,func,args.map{|x|x.to_param}, 'i').call *args
- }
- end
- def callproc(addr, type = :cdecl)
- stdcall = type == :stdcall
- raise "addr == 0 " if addr.pack == 0
- apicall = api('user32', 'CallWindowProcW')
- lambda{|*args|apicall.call((code=[0x55,0xe589].pack('CS')+args.map{|x| [0x68, x.pack].pack('CL')}.reverse.join+[0xb8, addr.pack, 0xD0FF, 0xc481, (stdcall ? 0 : args.length*4) , 0x10c2c9].pack('CLSSLL')),0,0,0,0)}
- end
- LL = api("kernel32", "LoadLibrary")
- GPA = api("kernel32", "GetProcAddress")
- def funcaddr(dll, func)
- x = GPA.call(LL.call(dll), func)
- x == 0 ? nil : x
- end
- def readmem(start, len)
- api('kernel32', 'RtlMoveMemory').call buf = "\0"*len, start, len
- buf
- end
- def writemem(start, len, value)
- api('kernel32', 'RtlMoveMemory').call start, value, [len, value.length].min
- end
- end
- class << Graphics
- SetWindowPos = SAFX.api("user32", "SetWindowPos")
- GetSystemMetrics = SAFX.api("user32", "GetSystemMetrics")
- CAPTION_HEIGHT = GetSystemMetrics.call(4)
- CX_FRAME, CY_FRAME = GetSystemMetrics.call(32), GetSystemMetrics.call(33)
- SIZE = {:width => 640, :height => 480}
- def resize_screen(width, height)
- SetWindowPos.call(HWND, 0, 0, 0,
- width + CX_FRAME - 2, height + CAPTION_HEIGHT + CY_FRAME - 1, 2)
- SIZE[:width], SIZE[:height] = width, height
- end
- def width
- SIZE[:width]
- end
- def height
- SIZE[:height]
- end
- def do_screen_stuff
- hwnd = self.hwnd
- src = SAFX.api('user32', 'GetDC').call(hwnd)
- memdc = SAFX.api('gdi32', 'CreateCompatibleDC').call(src)
- hb = SAFX.api('gdi32', 'CreateCompatibleBitmap').call(src, width, height)
- ho = SAFX.api('gdi32', 'SelectObject').call(memdc, hb)
- bp = SAFX.funcaddr("user32", "GetDC")
- ov = "\0"*4
- str = [0xb8, memdc, 0xc2, 0x04, 0x00].pack("CLC*") # magic, touch
- SAFX.api('Kernel32', 'VirtualProtect').call(bp, str.length, 0x40, ov)
- oldstr = SAFX.readmem(bp, str.length)
- SAFX.writemem bp, str.length, str
- SAFX.api('user32', 'UpdateWindow').call(hwnd)
- Graphics.update
- SAFX.writemem bp, str.length, oldstr
- yield hb
- ensure
- SAFX.api('user32', 'ReleaseDC').call(hwnd, src)
- hb = SAFX.api('gdi32', 'SelectObject').call(memdc, ho)
- SAFX.api('gdi32', 'DeleteObject').call(ho)
- SAFX.api('gdi32', 'DeleteDC').call(memdc)
- end
- def snap_to_bitmap
- bm = Bitmap.new(width, height)
- addr = bm.object_id * 2
- addr, = SAFX.readmem(addr + 16, 4).unpack("L")
- addr, = SAFX.readmem(addr + 8, 4).unpack("L")
- addr, = SAFX.readmem(addr + 16, 4).unpack("L")
- do_screen_stuff do |hb|
- bits = "\0"*(width * height * 4)
- SAFX.api('gdi32', 'GetBitmapBits').call(hb, bits.length, bits)
- r = SAFX.api('kernel32', 'RtlMoveMemory')
- a = bits.pack
- stride = width * 4
- h = height
- (h-1).downto(0){|i|
- r.call addr + i * stride, a + (h - i - 1)*stride, stride
- }
- bm
- end
- end
- def snap_to_clipboard
- return false if SAFX.api('user32', 'OpenClipboard').call(hwnd) == 0
- do_screen_stuff do |hb|
- SAFX.api('user32', 'SetClipboardData').call(2, hb)
- SAFX.api('user32', 'CloseClipboard').call
- true
- end
- end
- end
- #==============================================================================
- # ■ Bitmap
- #------------------------------------------------------------------------------
- # 位图的类。所谓位图即表示图像其本身。
- #==============================================================================
- class Bitmap
- def blur(str = 3, rect = Rect.new(0, 0, self.width, self.height))
- if str < 1
- str = 1
- elsif str > 5
- str = 5
- end
- for x in -str..str
- for y in -str..str
- next if x == 0 and y == 0
- self.blt(x + rect.x, y + rect.y, self, Rect.new(rect.x, rect.y, rect.width - x, rect.height - y), 10)
- end
- end
- return self
- end
- end
- module M3L
- module Snaps
- Stack = []
- def self.<< bmp
- Stack << bmp
- self
- end
- def self.>> spr
- spr.bitmap = Stack.pop
- self
- end
- class ::Scene_Map
- alias ori_call_menu call_menu
- def call_menu
- M3L::Snaps.<< Graphics.snap_to_bitmap.blur 2
- ori_call_menu
- end
- end
- end
- end
- class Scene_Menu
- def initialize(*)
- end
- def main
- @background = Sprite.new
- M3L::Snaps >> @background
- @command_window = Window_Command.new(192, ["退到主界面", "结束游戏"])
- @command_window.x = 320 - @command_window.width / 2
- @command_window.y = 240 - @command_window.height / 2
- Graphics.transition
- loop do
- Graphics.update
- Input.update
- update
- break unless $scene == self
- end
- Graphics.freeze
- @command_window.dispose
- @background.bitmap.dispose
- @background.dispose
- end
- def update
- @command_window.update
- if Input.trigger?(Input::B)
- $game_system.se_play($data_system.cancel_se)
- $scene = Scene_Map.new
- return
- end
- if Input.trigger?(Input::C)
- case @command_window.index
- when 0 then command_to_title
- when 1 then command_shutdown
- end
- end
- end
- def command_to_title
- $game_system.se_play($data_system.decision_se)
- Audio.bgm_fade(800)
- Audio.bgs_fade(800)
- Audio.me_fade(800)
- $scene = Scene_Title.new
- end
- def command_shutdown
- $game_system.se_play($data_system.decision_se)
- Audio.bgm_fade(800)
- Audio.bgs_fade(800)
- Audio.me_fade(800)
- $scene = nil
- end
- end
复制代码 即插即用 |
|