#SingleInstance Force
#NoEnv
#Persistent
SetBatchLines, -1
ListLines, Off
OnMessage(0x0020, "WM_SETCURSOR")
OnMessage(0x201, "LBUTTONDOWN") ; WM_LBUTTONDOWN
OnMessage(0xA1, "LBUTTONDOWN") ; WM_NCLBUTTONDOWN
DetectHiddenWindows, On
CoordMode, Mouse, Screen
OnExit, Exit
If !pToken := GdipStartup()
{
MsgBox, 4112, Gdiplus Error, Gdiplus failed to start. Please ensure you have Gdiplus on your system.
ExitApp
}
Global oZoom := {}
ZoomCreate()
ZoomShow(1)
Magnify()
oZoom.Start := 1
Return
1:: ; переместить окно к мыши
MouseGetPos, X, Y
hDWP := DllCall("BeginDeferWindowPos", "Int", 2)
hDWP := DllCall("DeferWindowPos"
, "Ptr", hDWP, "Ptr", oZoom.hLW, "UInt", 0
, "Int", X + 1 + 12
, "Int", Y + 46 + 12, "Int", 0, "Int", 0
, "UInt", 0x0011) ; 0x0010 := SWP_NOACTIVATE | 0x0001 := SWP_NOSIZE
hDWP := DllCall("DeferWindowPos"
, "Ptr", hDWP, "Ptr", oZoom.hGui, "UInt", 0
, "Int", X + 12, "Int", Y + 12, "Int", 0, "Int", 0
, "UInt", 0x0011) ; 0x0010 := SWP_NOACTIVATE | 0x0001 := SWP_NOSIZE
DllCall("EndDeferWindowPos", "Ptr", hDWP)
return
2:: oZoom.Pause := !oZoom.Pause
3:: ; показать скрыть окно
ZoomHide:
ZoomShow(oZoom.Show := !oZoom.Show)
return
Escape:: ExitApp
ZoomCreate() {
oZoom.Zoom := 8
oZoom.Mark := "Cross"
oZoom.MemoryZoomSize := 0
oZoom.GuiMinW := 306
oZoom.GuiMinH := 351
FontSize := (A_ScreenDPI = 120 ? 10 : 12)
GuiW := 306, GuiH := 351
Gui, Zoom: -DPIScale +Border +LabelZoomOn +HWNDhGui +AlwaysOnTop -Caption +E0x08000000 ;
Gui, Zoom: Color, F0F0F0
Gui, Zoom: Add, Text, hwndhStatic +Border
DllCall("SetClassLong", "Ptr", hGui, "int", -26
, "int", DllCall("GetClassLong", "Ptr", hGui, "int", -26) | 0x20000)
Gui, LW: -Caption +E0x80000 +AlwaysOnTop +ToolWindow +HWNDhLW +Owner%hGui% +E0x08000000 ; +E0x08000000 E0x20
Gui, LW: Show, NA w0 h0
Gui, ZoomTB: +HWNDhTBGui -Caption -DPIScale +Parent%hGui% +E0x08000000 +0x40000000 -0x80000000
Gui, ZoomTB: Color, F0F0F0
Gui, ZoomTB: Font, s%FontSize%
Gui, ZoomTB: Add, Slider, hwndhSliderZoom gSliderZoom x8 Range1-50 w152 Center AltSubmit NoTicks, % oZoom.Zoom
Gui, ZoomTB: Add, Text, hwndhTextZoom Center x+10 yp+3 w36, % oZoom.Zoom
Gui, ZoomTB: Font
Gui, ZoomTB: Add, Button, hwndhChangeMark gChangeMark x+10 yp w52, % oZoom.Mark
Gui, ZoomTB: Add, Button, hwndhZoomHideBut gZoomHide x+10 yp, X
Gui, ZoomTB: Show, NA x0 y0
Gui, Zoom: Show, % "NA Hide xCenter yCenter w" GuiW " h" GuiH, AhkSpyZoom
Gui, Zoom: +MinSize
oZoom.hdcSrc := DllCall("GetDC", "UPtr", 0, "UPtr")
oZoom.hDCBuf := CreateCompatibleDC()
oZoom.hdcMemory := CreateCompatibleDC()
oZoom.hGui := hGui
oZoom.hStatic := hStatic
oZoom.hTBGui := hTBGui
oZoom.hLW := hLW
oZoom.vTextZoom := hTextZoom
oZoom.vChangeMark := hChangeMark
oZoom.vZoomHideBut := hZoomHideBut
oZoom.vSliderZoom := hSliderZoom
SetSize()
}
ChangeMark() {
Static Mark := {"Cross":"Square","Square":"Grid","Grid":"None","None":"Cross","":"None"}
oZoom.Mark := Mark[oZoom.Mark], ChangeMarker(), Redraw()
GuiControl, ZoomTB:, % oZoom.vChangeMark, % oZoom.Mark
GuiControl, ZoomTB:, -0x0001, % oZoom.vChangeMark
GuiControl, ZoomTB:, Focus, % oZoom.vTextZoom
}
SliderZoom() {
SetTimer, ChangeZoom, -1
}
ChangeZoom(Val = "") {
If Val =
GuiControlGet, Val, ZoomTB:, % oZoom.vSliderZoom
If (Val < 1 || Val > 50)
Return
GuiControl, ZoomTB:, % oZoom.vSliderZoom, % oZoom.Zoom := Val
GuiControl, ZoomTB:, % oZoom.vTextZoom, % oZoom.Zoom
SetSize()
Redraw()
}
SetSize() {
Static Top := 45, Left := 0, Right := 6, Bottom := 6
Width := oZoom.LWWidth := oZoom.GuiWidth - Left - Right
Height := oZoom.LWHeight := oZoom.GuiHeight - Top - Bottom
Zoom := oZoom.Zoom
conW := Mod(Width, Zoom) ? Width - Mod(Width, Zoom) + Zoom : Width
conW := Mod(conW // Zoom, 2) ? conW : conW + Zoom
conH := Mod(Height, Zoom) ? Height - Mod(Height, Zoom) + Zoom : Height
conH := Mod(conH // Zoom, 2) ? conH : conH + Zoom
oZoom.conX := (((conW - Width) // 2)) * -1
oZoom.conY := (((conH - Height) // 2)) * -1
hDWP := DllCall("BeginDeferWindowPos", "Int", 2)
hDWP := DllCall("DeferWindowPos"
, "Ptr", hDWP, "Ptr", oZoom.hStatic, "UInt", 0
, "Int", Left , "Int", Top, "Int", Width + 2, "Int", Height + 2
, "UInt", 0x0010) ; 0x0010 := SWP_NOACTIVATE
hDWP := DllCall("DeferWindowPos"
, "Ptr", hDWP, "Ptr", oZoom.hTBGui, "UInt", 0
, "Int", (oZoom.GuiWidth - oZoom.GuiMinW) / 2
, "Int", 0, "Int", 0, "Int", 0
, "UInt", 0x0011) ; 0x0010 := SWP_NOACTIVATE | 0x0001 := SWP_NOSIZE
DllCall("EndDeferWindowPos", "Ptr", hDWP)
oZoom.nWidthSrc := conW // Zoom
oZoom.nHeightSrc := conH // Zoom
oZoom.nXOriginSrcOffset := oZoom.nWidthSrc//2
oZoom.nYOriginSrcOffset := oZoom.nHeightSrc//2
oZoom.nWidthDest := conW
oZoom.nHeightDest := conH
oZoom.xCenter := Round(Width / 2 - Zoom / 2)
oZoom.yCenter := Round(Height / 2 - Zoom / 2)
ChangeMarker()
}
ChangeMarker() {
Try GoTo % "Marker" oZoom.Mark
MarkerCross:
oZoom.oMarkers["Cross"] := [{x:0,y:oZoom.yCenter - 1,w:oZoom.nWidthDest,h:1}
, {x:0,y:oZoom.yCenter + oZoom.Zoom,w:oZoom.nWidthDest,h:1}
, {x:oZoom.xCenter - 1,y:0,w:1,h:oZoom.nHeightDest}
, {x:oZoom.xCenter + oZoom.Zoom,y:0,w:1,h:oZoom.nHeightDest}]
Return
MarkerSquare:
oZoom.oMarkers["Square"] := [{x:oZoom.xCenter - 1,y:oZoom.yCenter,w:oZoom.Zoom + 2,h:1}
, {x:oZoom.xCenter - 1,y:oZoom.yCenter + oZoom.Zoom + 1,w:oZoom.Zoom + 2,h:1}
, {x:oZoom.xCenter - 1,y:oZoom.yCenter + 1,w:1,h:oZoom.Zoom}
, {x:oZoom.xCenter + oZoom.Zoom,y:oZoom.yCenter + 1,w:1,h:oZoom.Zoom}]
Return
MarkerGrid:
If (oZoom.Zoom = 1) {
Gosub MarkerSquare
Return oZoom.oMarkers["Grid"] := oZoom.oMarkers["Square"]
}
oZoom.oMarkers["Grid"] := [{x:oZoom.xCenter - oZoom.Zoom,y:oZoom.yCenter - oZoom.Zoom,w:oZoom.Zoom * 3,h:1}
, {x:oZoom.xCenter - oZoom.Zoom,y:oZoom.yCenter,w:oZoom.Zoom * 3,h:1}
, {x:oZoom.xCenter - oZoom.Zoom,y:oZoom.yCenter + oZoom.Zoom,w:oZoom.Zoom * 3,h:1}
, {x:oZoom.xCenter - oZoom.Zoom,y:oZoom.yCenter + oZoom.Zoom * 2,w:oZoom.Zoom * 3,h:1}
, {x:oZoom.xCenter - oZoom.Zoom,y:oZoom.yCenter - oZoom.Zoom,w:1,h:oZoom.Zoom * 3}
, {x:oZoom.xCenter,y:oZoom.yCenter - oZoom.Zoom,w:1,h:oZoom.Zoom * 3}
, {x:oZoom.xCenter + oZoom.Zoom,y:oZoom.yCenter - oZoom.Zoom,w:1,h:oZoom.Zoom * 3}
, {x:oZoom.xCenter + oZoom.Zoom * 2,y:oZoom.yCenter - oZoom.Zoom,w:1,h:oZoom.Zoom * 3}]
Return
}
Magnify(one = 0) {
Static New
If (oZoom.Show && oZoom.SIZING != 2 && !oZoom.Pause)
{
MouseGetPos, mX, mY, WinID
If (WinID != oZoom.hLW && WinID != oZoom.hGui)
{
New := 1, oZoom.MouseX := mX, oZoom.MouseY := mY
UpdateWindow(oZoom.hdcSrc, mX - oZoom.nXOriginSrcOffset, mY - oZoom.nYOriginSrcOffset)
}
}
Else If New
Memory(), New := 0
SetTimer, Magnify, -10
}
Exit:
ReleaseDC(oZoom.hdcSrc)
DeleteDC(oZoom.hdcSrc)
DeleteDC(oZoom.hDCBuf)
DeleteDC(oZoom.hdcMemory)
GdipShutdown(pToken)
ExitApp
ZoomShow(Show) {
oZoom.Show := Show
If Show {
WinGetPos, WinX, WinY, WinW, , % "ahk_id" oZoom.hGui
oZoom.LWX := WinX + 1, oZoom.LWY := WinY + 46
Gui, Zoom: Show, % "NA Hide x" WinX " y" WinY
Gui, LW: Show, % "NA x" oZoom.LWX " y" oZoom.LWY " w" 0 " h" 0
Gui, Zoom: Show, NA
try Gui, LW: Show, % "NA x" oZoom.LWX " y" oZoom.LWY " w" oZoom.LWWidth " h" oZoom.LWHeight
Return
}
Gui, LW: Show, % "NA w" 0 " h" 0 ; нельзя применять Hide, иначе после появления и ресайза остаётся прозрачный след
; Gui, LW: Show, NA Hide
Gui, Zoom: Show, NA Hide
}
ZoomOnSize() {
If A_EventInfo != 0
Return
oZoom.GuiWidth := A_GuiWidth
oZoom.GuiHeight := A_GuiHeight
SetSize()
Redraw()
}
; _________________________________________________ Sizing _________________________________________________
WM_SETCURSOR(W, L, M, H) {
Static SIZENWSE := DllCall("User32.dll\LoadCursor", "Ptr", NULL, "Int", 32642, "UPtr")
, SIZENS := DllCall("User32.dll\LoadCursor", "Ptr", NULL, "Int", 32645, "UPtr")
, SIZEWE := DllCall("User32.dll\LoadCursor", "Ptr", NULL, "Int", 32644, "UPtr")
If (oZoom.SIZING = 2)
Return
If (W = oZoom.hGui)
{
MouseGetPos, mX, mY
WinGetPos, WinX, WinY, WinW, WinH, % "ahk_id " oZoom.hLW
If (mX > WinX && mY > WinY)
{
If (mX < WinX + WinW - 10)
DllCall("User32.dll\SetCursor", "Ptr", SIZENS), oZoom.SIZINGType := "NS"
Else If (mY < WinY + WinH - 10)
DllCall("User32.dll\SetCursor", "Ptr", SIZEWE), oZoom.SIZINGType := "WE"
Else
DllCall("User32.dll\SetCursor", "Ptr", SIZENWSE), oZoom.SIZINGType := "NWSE"
Return oZoom.SIZING := 1
}
}
Else
oZoom.SIZING := 0, oZoom.SIZINGType := ""
}
LBUTTONDOWN(W, L, M, H) {
If oZoom.SIZING
{
oZoom.SIZING := 2
SetSystemCursor("SIZE" oZoom.SIZINGType)
SetTimer, Sizing, -1
KeyWait LButton
SetTimer, Sizing, Off
RestoreCursors()
oZoom.SIZING := 0, oZoom.SIZINGType := ""
}
}
Sizing() {
MouseGetPos, mX, mY
WinGetPos, WinX, WinY, , , % "ahk_id " oZoom.hGui
If (oZoom.SIZINGType = "NWSE" || oZoom.SIZINGType = "WE")
Width := " w" (mX - WinX < oZoom.GuiMinW ? oZoom.GuiMinW : mX - WinX)
If (oZoom.SIZINGType = "NWSE" || oZoom.SIZINGType = "NS")
Height := " h" (mY - WinY < oZoom.GuiMinH ? oZoom.GuiMinH : mY - WinY)
Gui, Zoom:Show, % "NA" Width . Height
SetTimer, Sizing, -1
}
SetSystemCursor(CursorName, cx = 0, cy = 0) {
Static SystemCursors := {ARROW:32512, IBEAM:32513, WAIT:32514, CROSS:32515, UPARROW:32516, SIZE:32640, ICON:32641, SIZENWSE:32642
, SIZENESW:32643, SIZEWE:32644 ,SIZENS:32645, SIZEALL:32646, NO:32648, HAND:32649, APPSTARTING:32650, HELP:32651}
Local CursorHandle, hImage, Name, ID
If (CursorHandle := DllCall("LoadCursor", Uint, 0, Int, SystemCursors[CursorName]))
For Name, ID in SystemCursors
hImage := DllCall("CopyImage", Ptr, CursorHandle, Uint, 0x2, Int, cx, Int, cy, Uint, 0)
, DllCall("SetSystemCursor", Ptr, hImage, Int, ID)
}
RestoreCursors() {
DllCall("SystemParametersInfo", UInt, 0x57, UInt, 0, UInt, 0, UInt, 0) ; SPI_SETCURSORS := 0x57
}
; _________________________________________________ Gdip _________________________________________________
Memory() {
SysGet, VSX, 76
SysGet, VSY, 77
SysGet, VSWidth, 78
SysGet, VSHeight, 79
oZoom.nXOriginSrc := oZoom.MouseX - VSX, oZoom.nYOriginSrc := oZoom.MouseY - VSY
hBM := DllCall("Gdi32.Dll\CreateCompatibleBitmap", "Ptr", oZoom.hdcSrc, "Int", VSWidth, "Int", VSHeight)
DllCall("Gdi32.Dll\SelectObject", "Ptr", oZoom.hdcMemory, "Ptr", hBM), DllCall("DeleteObject", "Ptr", hBM)
StretchBlt(oZoom.hdcMemory, 0, 0, VSWidth, VSHeight, oZoom.hdcSrc, VSX, VSY, VSWidth, VSHeight)
}
Redraw() {
If oZoom.Start
UpdateWindow(oZoom.hdcMemory, oZoom.nXOriginSrc - oZoom.nXOriginSrcOffset, oZoom.nYOriginSrc - oZoom.nYOriginSrcOffset)
}
UpdateWindow(Src, X, Y) {
WinGetPos, WinX, WinY, , , % "ahk_id" oZoom.hGui
oZoom.LWX := WinX + 1, oZoom.LWY := WinY + 46
hbm := CreateDIBSection(oZoom.nWidthDest, oZoom.nHeightDest, oZoom.hDCBuf)
DllCall("SelectObject", "UPtr", oZoom.hDCBuf, "UPtr", hbm)
StretchBlt(oZoom.hDCBuf, oZoom.conX, oZoom.conY, oZoom.nWidthDest, oZoom.nHeightDest
, Src, X, Y, oZoom.nWidthSrc, oZoom.nHeightSrc)
For k, v In oZoom.oMarkers[oZoom.Mark]
StretchBlt(oZoom.hDCBuf, v.x, v.y, v.w, v.h, oZoom.hDCBuf, v.x, v.y, v.w, v.h, 0x5A0049) ; PATINVERT
DllCall("gdiplus\GdipCreateBitmapFromHBITMAP", "UPtr", hbm, "UPtr", 0, "UPtr*", pBitmap)
DllCall("SelectObject", "UPtr", oZoom.hDCBuf, "UPtr", hbm)
DllCall("gdiplus\GdipCreateFromHDC", "UPtr", oZoom.hDCBuf, "UPtr*", G)
DrawImage(G, pBitmap, 0, 0, oZoom.LWWidth, oZoom.LWHeight)
If oZoom.Show
UpdateLayeredWindow(oZoom.hLW, oZoom.hDCBuf, oZoom.LWX, oZoom.LWY, oZoom.LWWidth, oZoom.LWHeight)
DllCall("DeleteObject", "UPtr", hbm)
DllCall("gdiplus\GdipDeleteGraphics", "UPtr", G)
DllCall("gdiplus\GdipDisposeImage", "UPtr", pBitmap)
}
GdipStartup() {
if !DllCall("GetModuleHandle", "str", "gdiplus", UPtr)
DllCall("LoadLibrary", "str", "gdiplus")
VarSetCapacity(si, A_PtrSize = 8 ? 24 : 16, 0), si := Chr(1)
DllCall("gdiplus\GdiplusStartup", A_PtrSize ? "UPtr*" : "uint*", pToken, UPtr, &si, UPtr, 0)
Return pToken
}
GdipShutdown(pToken) {
DllCall("gdiplus\GdiplusShutdown", UPtr, pToken)
if hModule := DllCall("GetModuleHandle", "str", "gdiplus", UPtr)
DllCall("FreeLibrary", UPtr, hModule)
Return 0
}
UpdateLayeredWindow(hwnd, hdc, x, y, w, h) {
Static pt, _ := VarSetCapacity(pt, 8)
NumPut(x, pt, 0, "UInt"), NumPut(y, pt, 4, "UInt")
Return DllCall("UpdateLayeredWindow"
, UPtr, hwnd
, UPtr, 0
, UPtr, &pt
, "int64*", w|h<<32
, UPtr, hdc
, "int64*", 0
, "uint", 0
, "UInt*", 33488896 ; (Alpha := 255)<<16|1<<24
, "uint", 2)
}
StretchBlt(ddc, dx, dy, dw, dh, sdc, sx, sy, sw, sh, Raster=0x40CC0020) { ; 0x00CC0020|0x40000000
Return DllCall("gdi32\StretchBlt"
, UPtr, ddc
, "int", dx
, "int", dy
, "int", dw
, "int", dh
, UPtr, sdc
, "int", sx
, "int", sy
, "int", sw
, "int", sh
, "uint", Raster)
}
CreateDIBSection(w, h, hdc) {
Static bi, _ := VarSetCapacity(bi, 40, 0)
NumPut(w, bi, 4, "uint")
NumPut(h, bi, 8, "uint")
NumPut(40, bi, 0, "uint")
NumPut(1, bi, 12, "ushort")
NumPut(0, bi, 16, "uInt")
NumPut(32, bi, 14, "ushort")
Return DllCall("CreateDIBSection"
, "UPtr", hdc
, "UPtr", &bi
, "uint", 0
, "UPtr*",
, "UPtr", 0
, "uint", 0, "UPtr")
}
DrawImage(pGraphics, pBitmap, dx, dy, dw, dh) {
Return DllCall("gdiplus\GdipDrawImageRectRect"
, "UPtr", pGraphics
, "UPtr", pBitmap
, "float", dx
, "float", dy
, "float", dw
, "float", dh
, "float", dx
, "float", dy
, "float", dw
, "float", dh
, "int", 2
, "UPtr",
, "UPtr", 0
, "UPtr", 0)
}
ReleaseDC(hdc, hwnd=0) {
Return DllCall("ReleaseDC", "UPtr", hwnd, "UPtr", hdc)
}
DeleteDC(hdc) {
Return DllCall("DeleteDC", "UPtr", hdc)
}
CreateCompatibleDC(hdc=0) {
Return DllCall("CreateCompatibleDC", "UPtr", hdc)
}
С AnimateWindow тоже нужен костыль в виде подмены картинкой, ведь теперь 2 окна. А вот для минимизации и восстановления оказывается достаточно +Owner, но только после восстановления, Layered начинает отбрасывать тень, так что тоже понадобится костыль. Для демо, можно у Gui Zoom убрать E0x08000000.