最小化ウィンドウは意外と奥が深い。
最小化される直前の状態が普通だったか最大化だったかを調べなければいけない。 つまり、普通→最大化→最小化の場合、WinRestore を 2回撃たなきゃ普通にならない。
もちろん毎秒 WinRestore できるわけもないので、ループはやめた。notify されたときだけ動作するようにした。
#Requires AutoHotkey v2.0 #Warn #SingleInstance Force ; A simple workaround for the Rapid HPD problem ; https://devblogs.microsoft.com/directx/avoid-unexpected-app-rearrangement/ ; https://superuser.com/questions/1292435 Persistent(true) registerpower() return ; https://www.autohotkey.com/boards/viewtopic.php?p=539708 registerpower() { CLSID := Buffer(16) if (res := DllCall("ole32\CLSIDFromString", ; GUID_CONSOLE_DISPLAY_STATE_ "WStr", "{6FE69556-704A-47A0-8F24-C28D936FDA47}", "Ptr", CLSID, "UInt") ) { throw (Error("CLSIDFromString failed. Error: " . Format("{:#x}", res))) } if (! ;hPowerNotify := DllCall('RegisterPowerSettingNotification', 'Ptr', A_ScriptHwnd, 'Ptr', CLSID, 'UInt', 0, 'Ptr') ) { throw (OSError(A_LastError, -1, 'RegisterPowerSettingNotification')) } Sleep(1) ; a notification is always emitted immediately after registering for it for some reason. this prevents seeing it OnMessage(0x218, _WM_POWERBROADCAST) } _WM_POWERBROADCAST(wParam, lParam, msg, hwnd) { Critical(1000) static oldpower := 1 static newpower static wins := Map() if (wParam = 0x8013) { ; PBT_POWERSETTINGCHANGE newpower := NumGet(lParam, 20, 'UChar') ; 0 (off) or 1 (on). switch { case (oldpower and !newpower): savewins(&wins) case (!oldpower and newpower): restorewins(wins) } oldpower := newpower } return (true) } savewins(&winmap) { winmap.Clear() MouseGetPos(&mx, &my) winmap["mouse"] := { x: mx, y: my } for (this_id in WinGetList(, , "Program Manager")) { try { minmax := WinGetminmax(this_id) } catch (TargetError) { continue } WinRestore(this_id) if (1 = WinGetminmax(this_id)) { minmax := -2 WinRestore(this_id) } WinGetPos(&x, &y, &w, &h, this_id) winmap[this_id] := { x: x, y: y, w: w, h: h, minmax: minmax } } } restorewins(winmap) { for (this_id, d in winmap) { if (this_id = "mouse") { MouseMove(d.x, d.y, 0) continue } try { minmax := WinGetMinMax(this_id) } catch (TargetError) { continue } WinGetPos(&x, &y, , , this_id) if (d.x = x && d.y = y && d.minmax = minmax) { continue } WinMove(d.x, d.y, d.w, d.h, this_id) switch (d.minmax) { case (1): WinMaximize(this_id) case (-1): WinMinimize(this_id) case (-2): WinMaximize(this_id) WinMinimize(this_id) } } }