Last active
February 8, 2020 14:57
-
-
Save skymonsters-Ks/ccea0d954992cc5be23672ce72931593 to your computer and use it in GitHub Desktop.
ウィンドウとフルスクリーンの切替
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
; #include "hgimg4.as" ; HGIMG4 は HSP3.6b2 以降 | |
#include "user32.as" | |
#module | |
#const GWL_STYLE -16 | |
#const WS_POPUP $80000000 | |
#const WS_VISIBLE $10000000 | |
#const WM_KILLFOCUS $8 | |
#const WM_GETMINMAXINFO $24 | |
#const WM_WINDOWPOSCHANGED $47 | |
#const SM_CMONITORS 80 | |
#const HWND_NOTOPMOST -2 | |
#const HWND_TOPMOST -1 | |
#const SWP_FRAMECHANGED $20 | |
#const SWP_SHOWWINDOW $40 | |
#const CDS_TEST $2 | |
#const CDS_FULLSCREEN $4 | |
#const ENUM_CURRENT_SETTINGS -1 | |
#const MONITOR_DEFAULTTONEAREST 2 | |
; モジュール初期化 | |
; 対象ウィンドウが選択された状態で呼び出して | |
; 内で oncmd いくつか使っているので重複注意 | |
#deffunc fw_init | |
dim dmode, 40 ; DEVMODE | |
dim minfo, 18 ; MONITORINFOEX | |
minfo = 72 ; cbSize | |
full = 0 | |
mmw = ginfo_sizex | |
mmh = ginfo_sizey | |
oncmd gosub *wmGetMinMaxInfo, WM_GETMINMAXINFO | |
oncmd gosub *wmWindowPosChanged, WM_WINDOWPOSCHANGED | |
oncmd gosub *wmKillFocus, WM_KILLFOCUS | |
return | |
; ウィンドウサイズ上限解除とモニター間移動時のリサイズ防止 | |
*wmGetMinMaxInfo | |
dupptr mmi, lparam + 24, 16 ; MINMAXINFO ptMinTrackSize, ptMaxTrackSize | |
mmi = mmw, mmh, mmw, mmh | |
return 0 | |
; フルスクリーンモードでウィンドウ移動が起こったとき用 | |
; 本当はモニター間移動時のメッセージとかがほしい… | |
*wmWindowPosChanged | |
if full { | |
dupptr wp, lparam, 28 ; WINDOWPOS | |
if wp(2) != monix || wp(3) != moniy { | |
winx = wp(2) | |
winy = wp(3) | |
fw_change 0 | |
fw_change 1 | |
} | |
} | |
return 0 | |
; フルスクリーンモードでフォーカス失ったとき用 | |
; シングルモニタ環境下ではフルスクリーン解除した方がいいと思う | |
*wmKillFocus | |
if full : if GetSystemMetrics(SM_CMONITORS) == 1 : fw_change 0 | |
return 0 | |
; モード変更。0 でウィンドウモード、1 でフルスクリーンモードに。stat 0 で変更成功、1 で失敗。 | |
#deffunc fw_change int _m, local _mh | |
if _m { | |
if full == 1 : return 1 | |
winx = ginfo_wx1 | |
winy = ginfo_wy1 | |
winw = ginfo_sizex | |
winh = ginfo_sizey | |
winstyle = GetWindowLong(hwnd, GWL_STYLE) | |
_mh = MonitorFromWindow(hwnd, MONITOR_DEFAULTTONEAREST) | |
mname = getMoniName(_mh) | |
chgDispEx mname, ginfo_sx, ginfo_sy | |
if stat : return 1 | |
mmw = ginfo_sx | |
mmh = ginfo_sy | |
getMoniPos monix, moniy, _mh | |
chgWin HWND_TOPMOST, monix, moniy, mmw, mmh, WS_POPUP | WS_VISIBLE | |
full = 1 | |
} else { | |
if full == 0 : return 1 | |
mmw = winw | |
mmh = winh | |
full = 0 ; 直後の chgDispEx, chgWin で何度かウィンドウメッセージが来て wmWindowPosChanged を通過するので先に変更しておく | |
chgDispEx mname | |
chgWin HWND_NOTOPMOST, winx, winy, winw, winh, winstyle | |
} | |
return 0 | |
; モード取得。0 ウィンドウモード、1 フルスクリーンモード | |
#defcfunc fw_stat | |
return full | |
#deffunc local chgWin int _z, int _x, int _y, int _w, int _h, int _s | |
SetWindowLong hwnd, GWL_STYLE, _s | |
SetWindowPos hwnd, _z, _x, _y, _w, _h, SWP_FRAMECHANGED | SWP_SHOWWINDOW | |
return | |
#defcfunc local getMoniName int _mh, local _mn | |
GetMonitorInfo _mh, varptr(minfo) | |
getstr _mn, minfo, 40 ; szDevice | |
return _mn | |
#deffunc local getMoniPos var _x, var _y, int _mh | |
GetMonitorInfo _mh, varptr(minfo) | |
_x = minfo(1) | |
_y = minfo(2) | |
return | |
; 指定デバイスモードが対応しているかを取得。0 対応、1 未対応 | |
#defcfunc local chkDisp str _name, int _w, int _h, int _fr | |
EnumDisplaySettings _name, ENUM_CURRENT_SETTINGS, varptr(dmode) | |
dmode(27) = _w ; dmPelsWidth | |
dmode(28) = _h ; dmPelsHeight | |
if _fr > 0 { | |
dmode(30) = _fr ; dmDisplayFrequency | |
} | |
ChangeDisplaySettingsEx _name, varptr(dmode), 0, CDS_TEST, 0 | |
return stat < 0 | |
; デバイスモード変更。_w に 0 指定でモードを戻す。stat 0 で成功、1 で失敗 | |
#deffunc local chgDispEx str _name, int _w, int _h, int _fr | |
if _w > 0 { | |
if chkDisp(_name, _w, _h, _fr) : return 1 | |
ChangeDisplaySettingsEx _name, varptr(dmode), 0, CDS_FULLSCREEN, 0 | |
} else { | |
ChangeDisplaySettingsEx _name, 0, 0, CDS_FULLSCREEN, 0 | |
} | |
return 0 | |
#global | |
screen 0, 800, 600 | |
#ifdef _HGIMG4 | |
gpreset | |
#endif | |
fw_init | |
sx = ginfo_sx | |
sy = ginfo_sy | |
px = sx / 2 | |
py = sy / 2 | |
vx = 3 | |
vy = 3 | |
sz = 200 | |
szh = sz / 2 | |
*mainLoop | |
gosub *checkKey | |
gosub *move | |
gosub *draw | |
await 15 | |
goto *mainLoop | |
*checkKey | |
stick key | |
if key & 128 : end ; [Esc] | |
if key & 32 { ; [Enter] | |
fw_change fw_stat() ^ 1 | |
if stat { | |
ffc = 200 | |
} | |
} | |
return | |
*move | |
px += vx | |
py += vy | |
if px < szh : px = sz - px : vx = -vx | |
if py < szh : py = sz - py : vy = -vy | |
if px > sx - szh : px = 2 * (sx - szh) - px : vx = -vx | |
if py > sy - szh : py = 2 * (sy - szh) - py : vy = -vy | |
return | |
*draw | |
redraw 0 | |
color 50, 0, 100 | |
boxf | |
color 250, 50, 150 | |
grect px, py, 0, sz, sz | |
line rnd(sx), sy, rnd(sx), 0 | |
pos 10, 10 | |
color 200, 200, 200 | |
if fw_stat() { | |
mes "Fullscreen Mode" | |
} else { | |
mes "Window Mode" | |
} | |
if ffc { | |
mes strf("[%dx%d] incompatible mode", sx, sy) | |
ffc-- | |
} | |
redraw 1 | |
return |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
; #include "hgimg4.as" ; HGIMG4 は HSP3.6b2 以降 | |
#include "user32.as" | |
#include "gdi32.as" | |
#module | |
#const GWL_STYLE -16 | |
#const BLACK_BRUSH 4 | |
#const WS_POPUP $80000000 | |
#const WS_VISIBLE $10000000 | |
#const SRCCOPY $00cc0020 | |
#const WM_KILLFOCUS $8 | |
#const WM_GETMINMAXINFO $24 | |
#const WM_WINDOWPOSCHANGED $47 | |
#const SM_CMONITORS 80 | |
#const HWND_NOTOPMOST -2 | |
#const HWND_TOPMOST -1 | |
#const SWP_FRAMECHANGED $20 | |
#const SWP_SHOWWINDOW $40 | |
#const MONITOR_DEFAULTTONEAREST 2 | |
; モジュール初期化 | |
; 対象ウィンドウが選択された状態で呼び出して | |
; 内で oncmd いくつか使っているので重複注意 | |
; HGIMG4 使用時は _id にモジュール内で使うウィンドウID指定可、省略すると呼び出し時点での未使用IDを使用、stat にIDが返る | |
#deffunc fw_init int _id | |
dim point, 2 ; POINT | |
dim minfo, 18 ; MONITORINFOEX | |
minfo = 72 ; cbSize | |
rate = 100 | |
full = 0 | |
destw = ginfo_sx | |
desth = ginfo_sy | |
mmw = ginfo_sizex | |
mmh = ginfo_sizey | |
ncw = mmw - destw | |
nch = mmh - desth | |
#ifdef _HGIMG4 | |
winid = ginfo_sel | |
if _id <= 0 { | |
bufid = ginfo_newid | |
} else { | |
bufid = _id | |
} | |
buffer bufid, destw, desth, screen_offscreen | |
gsel winid | |
setcls 1, $000000 | |
#else | |
bufid = ginfo_sel | |
#endif | |
oncmd gosub *wmGetMinMaxInfo, WM_GETMINMAXINFO | |
oncmd gosub *wmWindowPosChanged, WM_WINDOWPOSCHANGED | |
oncmd gosub *wmKillFocus, WM_KILLFOCUS | |
return bufid | |
; ウィンドウサイズ上限解除とモニター間移動時のリサイズ防止 | |
*wmGetMinMaxInfo | |
dupptr mmi, lparam + 24, 16 ; MINMAXINFO ptMinTrackSize, ptMaxTrackSize | |
mmi = mmw, mmh, mmw, mmh | |
return 0 | |
; フルスクリーンモードでウィンドウ移動が起こったとき用 | |
; 本当はモニター間移動時のメッセージとかがほしい… | |
*wmWindowPosChanged | |
if full { | |
dupptr wp, lparam, 28 ; WINDOWPOS | |
if wp(2) != monix || wp(3) != moniy { | |
winx = wp(2) | |
winy = wp(3) | |
fw_change 0 | |
fw_change 1 | |
} | |
} | |
return 0 | |
; フルスクリーンモードでフォーカス失ったとき用 | |
; シングルモニタ環境下ではフルスクリーン解除した方がいいと思う | |
*wmKillFocus | |
if full : if GetSystemMetrics(SM_CMONITORS) == 1 : fw_change 0 | |
return 0 | |
; redraw の代わりに使用する(メイン画面のみ)、buffer で作成したウィンドウIDには通常通り redraw を使用する。 | |
; パラメータ省略時は挙動が違うので注意 | |
#deffunc fw_redraw int _m, local _dc | |
#ifdef _HGIMG4 | |
if full || rate != 100 { | |
if _m { | |
redraw 1 | |
gsel winid | |
redraw 0 | |
gpviewport destx, desty, destw, desth | |
gmode 0 | |
gmulcolor | |
pos 0, 0 | |
celput bufid | |
redraw 1 | |
} else { | |
gsel bufid | |
redraw 0 | |
gpviewport 0, 0, ginfo_sx, ginfo_sy | |
; gfilter 1 | |
} | |
} else { | |
redraw _m | |
gpviewport 0, 0, ginfo_sx, ginfo_sy | |
} | |
#else | |
if full || rate != 100 { | |
if _m { | |
_dc = GetDC(hwnd) | |
StretchBlt _dc, destx, desty, destw, desth, hdc, 0, 0, ginfo_sx, ginfo_sy, SRCCOPY | |
ReleaseDC hwnd, _dc | |
} else { | |
redraw 0 | |
} | |
} else { | |
redraw _m | |
} | |
#endif | |
return | |
; モード変更。0 でウィンドウモード、1 でフルスクリーンモードに | |
#deffunc fw_change int _m, local _mh, local _dc | |
if _m { | |
if full == 1 : return | |
winx = ginfo_wx1 | |
winy = ginfo_wy1 | |
winw = ginfo_sizex | |
winh = ginfo_sizey | |
winstyle = GetWindowLong(hwnd, GWL_STYLE) | |
_mh = MonitorFromWindow(hwnd, MONITOR_DEFAULTTONEAREST) | |
getMoniPos monix, moniy, _mh | |
getMoniSize mmw, mmh, _mh | |
; スクリーンを中央に配置するための計算 | |
if mmw * ginfo_sy < mmh * ginfo_sx { | |
destw = mmw | |
desth = mmw * ginfo_sy / ginfo_sx | |
destx = 0 | |
desty = (mmh - desth) / 2 | |
} else { | |
destw = mmh * ginfo_sx / ginfo_sy | |
desth = mmh | |
destx = (mmw - destw) / 2 | |
desty = 0 | |
} | |
chgWin HWND_TOPMOST, monix, moniy, mmw, mmh, WS_POPUP | WS_VISIBLE | |
full = 1 | |
} else { | |
if full == 0 : return | |
destx = 0 | |
desty = 0 | |
destw = ginfo_sx * rate / 100 | |
desth = ginfo_sy * rate / 100 | |
mmw = winw | |
mmh = winh | |
full = 0 ; 直後の chgWin でウィンドウメッセージが来て wmWindowPosChanged を通過するので先に変更しておく | |
chgWin HWND_NOTOPMOST, winx, winy, winw, winh, winstyle | |
} | |
#ifndef _HGIMG4 | |
; '画面外' の塗りつぶしとHSPバッファのちらつき低減 | |
ValidateRect hwnd, 0 | |
color : boxf : redraw 1 | |
_dc = GetDC(hwnd) | |
SelectObject _dc, GetStockObject(BLACK_BRUSH) | |
Rectangle _dc, 0, 0, mmw, mmh | |
ReleaseDC hwnd, _dc | |
#endif | |
return | |
; スクリーンリサイズ、_r は%指定、100 でオリジナル倍率 | |
#deffunc fw_resize int _r | |
if full == 0 { | |
if _r < 10 { | |
rate = 10 | |
} else { | |
rate = _r | |
} | |
destx = 0 | |
desty = 0 | |
destw = ginfo_sx * rate / 100 | |
desth = ginfo_sy * rate / 100 | |
mmw = destw + ncw | |
mmh = desth + nch | |
winx = ginfo_wx1 | |
winy = ginfo_wy1 | |
chgWin HWND_NOTOPMOST, winx, winy, mmw, mmh, GetWindowLong(hwnd, GWL_STYLE) | |
#ifndef _HGIMG4 | |
ValidateRect hwnd, 0 | |
color : boxf : redraw 1 | |
#endif | |
} | |
return | |
; 状態取得 | |
#defcfunc fw_stat int _m | |
switch _m | |
case 1 : return rate ; スクリーン倍率 | |
case 2 : return destw ; スクリーン幅 | |
case 3 : return desth ; スクリーン高さ | |
swend | |
return full ; 0 ウィンドウモード、1 フルスクリーンモード | |
#defcfunc fw_mousex | |
GetCursorPos varptr(point) | |
ScreenToClient hwnd, varptr(point) | |
return limit((point(0) - destx) * ginfo_sx / destw, 0, ginfo_sx - 1) | |
#defcfunc fw_mousey | |
GetCursorPos varptr(point) | |
ScreenToClient hwnd, varptr(point) | |
return limit((point(1) - desty) * ginfo_sy / desth, 0, ginfo_sy - 1) | |
#undef mousex | |
#define global mousex fw_mousex() | |
#undef mousey | |
#define global mousey fw_mousey() | |
#deffunc local chgWin int _z, int _x, int _y, int _w, int _h, int _s | |
SetWindowLong hwnd, GWL_STYLE, _s | |
SetWindowPos hwnd, _z, _x, _y, _w, _h, SWP_FRAMECHANGED | SWP_SHOWWINDOW | |
return | |
#deffunc local getMoniPos var _x, var _y, int _mh | |
GetMonitorInfo _mh, varptr(minfo) | |
_x = minfo(1) | |
_y = minfo(2) | |
return | |
#deffunc local getMoniSize var _w, var _h, int _mh | |
GetMonitorInfo _mh, varptr(minfo) | |
_w = minfo(3) - minfo(1) | |
_h = minfo(4) - minfo(2) | |
return | |
#global | |
; screen 0, 256, 240 | |
#ifdef _HGIMG4 | |
gpreset | |
#endif | |
fw_init ; HGIMG4 使用時は buffer, celload など他で使用しない0以外のウィンドウIDを指定する | |
sx = ginfo_sx | |
sy = ginfo_sy | |
px = sx / 2 | |
py = sy / 2 | |
vx = 3 | |
vy = 3 | |
sz = 200 | |
szh = sz / 2 | |
*mainLoop | |
gosub *checkKey | |
gosub *move | |
gosub *draw | |
await 15 | |
goto *mainLoop | |
*checkKey | |
stick key | |
if key & 128 : end ; [Esc] | |
if key & 32 : fw_change fw_stat() ^ 1 ; [Enter] | |
if key & 1 : fw_resize fw_stat(1) - 10 ; [left] | |
if key & 4 : fw_resize fw_stat(1) + 10 ; [right] | |
if key & 2 : fw_resize fw_stat(1) + 100 ; [up] | |
if key & 8 : fw_resize fw_stat(1) - 100 ; [down] | |
return | |
*move | |
px += vx | |
py += vy | |
if px < szh : px = sz - px : vx = -vx | |
if py < szh : py = sz - py : vy = -vy | |
if px > sx - szh : px = 2 * (sx - szh) - px : vx = -vx | |
if py > sy - szh : py = 2 * (sy - szh) - py : vy = -vy | |
return | |
*draw | |
fw_redraw 0 | |
color 50, 0, 100 | |
boxf | |
color 250, 50, 150 | |
grect px, py, 0, sz, sz | |
line rnd(sx), sy, rnd(sx), 0 | |
pos 10, 10 | |
color 200, 200, 200 | |
if fw_stat() { | |
mes "Fullscreen Mode" | |
} else { | |
mes "Window Mode" | |
mes strf("Size: %dx%d (%d%%)", fw_stat(2), fw_stat(3), fw_stat(1)) | |
} | |
mes strf("Mouse X:%d, Y:%d", mousex, mousey) | |
fw_redraw 1 | |
return |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Qiitaの記事:https://qiita.com/skymonsters_Ks/items/00fdb67d6518eb8b2cc5