#==============================================================================
# ★ Fullscreen++ Multi-Monitor Edition v2.32
# 멀티모니터에서 검은 배경도 정확히 현재 모니터에만 적용
# F5 = 전체화면 토글 F6 = 창 모드 배율 변경
#==============================================================================
$imported ||= {}
$imported[:Zeus_Fullscreen_MultiMonitor] = true
class << Graphics
Disable_VX_Fullscreen = false
# Win32API (중복 방지)
unless defined?(CreateWindowEx)
CreateWindowEx = Win32API.new('user32', 'CreateWindowEx', 'ippiiiiiiiii', 'i')
GetClientRect = Win32API.new('user32', 'GetClientRect', 'ip', 'i')
GetDC = Win32API.new('user32', 'GetDC', 'i', 'i')
GetSystemMetrics = Win32API.new('user32', 'GetSystemMetrics', 'i', 'i')
GetWindowRect = Win32API.new('user32', 'GetWindowRect', 'ip', 'i')
FillRect = Win32API.new('user32', 'FillRect', 'ipi', 'i')
FindWindow = Win32API.new('user32', 'FindWindow', 'pp', 'i')
ReleaseDC = Win32API.new('user32', 'ReleaseDC', 'ii', 'i')
SendInput = Win32API.new('user32', 'SendInput', 'ipi', 'i')
SetWindowLong = Win32API.new('user32', 'SetWindowLong', 'iii', 'i')
SetWindowPos = Win32API.new('user32', 'SetWindowPos', 'iiiiiii', 'i')
ShowWindow = Win32API.new('user32', 'ShowWindow', 'ii', 'i')
SystemParametersInfo = Win32API.new('user32', 'SystemParametersInfo', 'iipi', 'i')
UpdateWindow = Win32API.new('user32', 'UpdateWindow', 'i', 'i')
GetPrivateProfileString = Win32API.new('kernel32', 'GetPrivateProfileString', 'ppppip', 'i')
WritePrivateProfileString = Win32API.new('kernel32', 'WritePrivateProfileString', 'pppp', 'i')
CreateSolidBrush = Win32API.new('gdi32', 'CreateSolidBrush', 'i', 'i')
DeleteObject = Win32API.new('gdi32', 'DeleteObject', 'i', 'i')
MonitorFromRect = Win32API.new('user32', 'MonitorFromRect', 'pi', 'i')
GetMonitorInfoA = Win32API.new('user32', 'GetMonitorInfoA', 'lp', 'i')
end
HWND = FindWindow.call('RGSS Player', 0)
BackHWND = CreateWindowEx.call(0x08000008, 'Static', '', 0x80000000, 0, 0, 0, 0, 0, 0, 0, 0)
unless method_defined?(:zeus_fullscreen_update)
alias zeus_fullscreen_resize_screen resize_screen
alias zeus_fullscreen_update update
end
#==========================================================================
# ● 현재 모니터 정보 (full_rect = 전체화면용)
#==========================================================================
def current_monitor_info
rect_buf = " " * 4
GetWindowRect.call(HWND, rect_buf)
left, top, right, bottom = rect_buf.unpack('l4')
rect_struct = [left, top, right, bottom].pack('l4')
hmonitor = MonitorFromRect.call(rect_struct, 2)
mi = [40, 0,0,0,0, 0,0,0,0, 0,0,0,0].pack('l*') + "\0"*32
GetMonitorInfoA.call(hmonitor, mi)
mon_l, mon_t, mon_r, mon_b = mi[4, 16].unpack('l4')
work_l, work_t, work_r, work_b = mi[20, 16].unpack('l4')
{
full_rect: Rect.new(mon_l, mon_t, mon_r - mon_l, mon_b - mon_t),
work_rect: Rect.new(work_l, work_t, work_r - work_l, work_b - work_t)
}
end
private
def initialize_fullscreen_rects
@borders_size ||= borders_size
info = current_monitor_info
@fullscreen_rect = info[:full_rect]
@workarea_rect = info[:work_rect]
end
def borders_size
GetWindowRect.call(HWND, wrect = [0,0,0,0].pack('l4'))
GetClientRect.call(HWND, crect = [0,0,0,0].pack('l4'))
w = wrect.unpack('l4')
c = crect.unpack('l4')
Rect.new(0, 0, w[2]-w[0]-c[2], w[3]-w[1]-c[3])
end
# ★★★ 핵심 수정: BackHWND를 현재 모니터 전체로 정확히 이동 ★★★
def position_back_window
return unless @fullscreen && @fullscreen_rect
info = current_monitor_info
x, y = info[:full_rect].x, info[:full_rect].y
w, h = info[:full_rect].width, info[:full_rect].height
# BackHWND를 현재 모니터 전체 영역으로 이동 + 크기 조정
SetWindowPos.call(BackHWND, HWND, x, y, w, h, 0x0004) # SWP_NOZORDER + SWP_NOACTIVATE
end
def hide_borders() SetWindowLong.call(HWND, -16, 0x14000000) end
def show_borders() SetWindowLong.call(HWND, -16, 0x14CA0000) end
def hide_back() ShowWindow.call(BackHWND, 0) end
def show_back
ShowWindow.call(BackHWND, 3)
UpdateWindow.call(BackHWND)
dc = GetDC.call(BackHWND)
rect = [0, 0, @fullscreen_rect.width, @fullscreen_rect.height].pack('l4')
brush = CreateSolidBrush.call(0) # 검은색 브러시
FillRect.call(dc, rect, brush)
ReleaseDC.call(BackHWND, dc)
DeleteObject.call(brush)
position_back_window # ← 여기서 위치 보정
end
def resize_window(w, h)
info = current_monitor_info
@fullscreen_rect = info[:full_rect]
@workarea_rect = info[:work_rect]
if @fullscreen
x = @fullscreen_rect.x + (@fullscreen_rect.width - w) / 2
y = @fullscreen_rect.y + (@fullscreen_rect.height - h) / 2
z = -1
position_back_window # 전체화면일 때 BackHWND도 다시 위치
else
w += @borders_size.width
h += @borders_size.height
x = @workarea_rect.x + (@workarea_rect.width - w) / 2
y = @workarea_rect.y + (@workarea_rect.height - h) / 2
z = -2
hide_back()
end
SetWindowPos.call(HWND, z, x.to_i, y.to_i, w.to_i, h.to_i, 0)
end
def release_alt
inputs = [1,18,2, 1,164,2, 1,165,2].pack('LSx2Lx16'*3)
SendInput.call(3, inputs, 28)
end
public
def load_fullscreen_settings
buffer = [].pack('x256')
section = 'Fullscreen++'
filename = './Game.ini'
get_option = Proc.new do |key, default|
l = GetPrivateProfileString.call(section, key, default.to_s, buffer, buffer.size, filename)
buffer[0, l]
end
@fullscreen = get_option.call('Fullscreen', '0') == '1'
@fullscreen_ratio = get_option.call('FullscreenRatio', '0').to_i
@windowed_ratio = get_option.call('WindowedRatio', '1').to_i
toggle_vx_fullscreen if Disable_VX_Fullscreen && vx_fullscreen?
fullscreen? ? fullscreen_mode : windowed_mode
end
def save_fullscreen_settings
section = 'Fullscreen++'
filename = './Game.ini'
set = Proc.new { |k, v| WritePrivateProfileString.call(section, k, v.to_s, filename) }
set.call('Fullscreen', @fullscreen ? 1 : 0)
set.call('FullscreenRatio', @fullscreen_ratio)
set.call('WindowedRatio', @windowed_ratio)
end
def fullscreen?
def vx_fullscreen?
@fullscreen_rect && @fullscreen_rect.width == 640 && @fullscreen_rect.height == 480
end
def toggle_fullscreen
fullscreen? ? windowed_mode : fullscreen_mode
end
def toggle_vx_fullscreen
windowed_mode if @fullscreen && !vx_fullscreen?
inputs = [1,18,0, 1,13,0, 1,13,2, 1,18,2].pack('LSx2Lx16'*4)
SendInput.call(4, inputs, 28)
zeus_fullscreen_update
self.ratio += 0
end
def fullscreen_mode
return if vx_fullscreen?
initialize_fullscreen_rects
show_back
hide_borders
@fullscreen = true
self.ratio += 0
end
def windowed_mode
toggle_vx_fullscreen if vx_fullscreen?
initialize_fullscreen_rects
hide_back
show_borders
@fullscreen = false
self.ratio += 0
end
def toggle_ratio
return if vx_fullscreen?
self.ratio += 1
end
def ratio
return 1 if vx_fullscreen?
@fullscreen ? @fullscreen_ratio : @windowed_ratio
end
def ratio=(r)
return if vx_fullscreen?
initialize_fullscreen_rects
r = 0 if r < 0
if @fullscreen
@fullscreen_ratio = r
w_max = @fullscreen_rect.width
h_max = @fullscreen_rect.height
else
@windowed_ratio = r
w_max = @workarea_rect.width - @borders_size.width
h_max = @workarea_rect.height - @borders_size.height
end
if r == 0
w = w_max
h = (w_max * height.to_f / width).to_i
if h > h_max
h = h_max
w = (h_max * width.to_f / height).to_i
end
else
w = width * r
h = height * r
return self.ratio = 0 if w > w_max || h > h_max
end
resize_window(w, h)
save_fullscreen_settings
end
def update
release_alt if Disable_VX_Fullscreen && Input.trigger?(Input::ALT)
zeus_fullscreen_update
toggle_fullscreen if Input.trigger?(Input::F5)
toggle_ratio if Input.trigger?(Input::F6)
end
def resize_screen(width, height)
zeus_fullscreen_resize_screen(width, height)
self.ratio += 0
end
end
Graphics.load_fullscreen_settings
p "OK: Fullscreen++ Multi-Monitor v2.32 (검은 배경 멀티모니터 완전 수정)"