Advertisement
pk3456

Window Preview

Feb 15th, 2023 (edited)
215
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. #a::WindowPreview("A")
  2.  
  3. #Requires AutoHotkey v2.0
  4. #DllLoad dwmapi
  5.  
  6. /**
  7.  * Creates a preview window of a window
  8.  * - drag to pan
  9.  * - scroll to zoom
  10.  * - click to restore original window
  11.  */
  12. class WindowPreview extends Gui {
  13.  
  14.     Ratio => this.SrW/this.SrH
  15.  
  16.     __New(win) {
  17.         this.HwndSource := WinExist(win)
  18.         super.__New("+AlwaysOnTop +ToolWindow +Resize", WinGetTitle(this.HwndSource), this)
  19.         this.BackColor := 0x1a1a1a
  20.         this.Thumbnail := Thumbnail(this, this.HwndSource, true)
  21.         WinGetPos(&sourceX, &sourceY, &sourceW, &sourceH, this.HwndSource)
  22.  
  23.         initialHeight := 400
  24.         iW := initialHeight * sourceW/sourceH
  25.         iH := initialHeight
  26.         iX := sourceX + sourceW - iW - 30
  27.         iY := sourceY + sourceH - iH - 50
  28.         this.Show("x" iX " y" iY " w" iW " h" iH)
  29.  
  30.         ; screen to client coords
  31.         POINT := Buffer(8, 0)
  32.         NumPut("int", sourceX, POINT, 0), NumPut("int", sourceY, POINT, 4)
  33.         DllCall("ScreenToClient", "ptr", this.HwndSource, "ptr", POINT)
  34.         sourceX := NumGet(POINT, 0, "int")
  35.         sourceY := NumGet(POINT, 4, "int")
  36.  
  37.         this.SrX := sourceX
  38.         this.SrY := sourceY
  39.         this.SrW := sourceW
  40.         this.SrH := sourceH
  41.         this.FillAll := true
  42.  
  43.         this.GetClientPos(,,&guiW, &guiH)
  44.         WinGetClientPos(,,&sourceW, &sourceH, this.HwndSource)
  45.         this.Thumbnail.SetSourceRegion(0, 0, sourceW, sourceH)
  46.         this.Thumbnail.SetThumbRegion(0,0, guiW, guiH)
  47.         this.Events := {
  48.             LBUTTONDOWN:ObjBindMethod(this, "WM_LBUTTONDOWN"),
  49.             MOUSEWHEEL:ObjBindMethod(this, "WM_MOUSEWHEEL")
  50.         }
  51.         OnMessage(0x201,  this.Events.LBUTTONDOWN)
  52.         OnMessage(0x020A, this.Events.MOUSEWHEEL)
  53.         this.OnEvent("Close", "GuiClose")
  54.         this.OnEvent("Size", "GuiSize")
  55.     }
  56.     WM_LBUTTONDOWN(wParam, lParam, msg, hwnd) {
  57.         if hwnd != this.hwnd
  58.             return
  59.         MouseGetPos(&oX, &oY)
  60.         static MouseState := "Click"
  61.         while GetKeyState("LButton", "P") {
  62.             MouseGetPos(&X, &Y)
  63.             if oX = X && oY = Y
  64.                 continue
  65.             if Abs(X - oX) > 4 || Abs(Y - oY) > 4 {
  66.                 MouseState := "Move"
  67.                 break
  68.             }
  69.             sleep 1
  70.         }
  71.         if MouseState = "Click" {
  72.             WinActivate this.HwndSource
  73.             return
  74.         }
  75.         if MouseState = "Move" {
  76.             MouseGetPos &lmX, &lmY
  77.             lXg := this.SrX, lYg := this.SrY
  78.             while GetKeyState("LButton", "P") {
  79.                 MouseGetPos(&mX, &mY)
  80.                 ; do nothing if mouse hasn't moved
  81.                 if lmX = mX && lmY = mY
  82.                     continue
  83.                 this.Thumbnail.GetSourceSize(&sourceW, &sourceH)
  84.                 this.GetClientPos(,,&guiW, &guiH)
  85.  
  86.                 guiRatio := guiW/guiH
  87.                 limit := 100
  88.  
  89.                 ; prevent dragging too far.
  90.                 xLeft := Max(-this.Srw + limit, -this.srh * guiRatio + limit)
  91.                 xdiff := mx - lmx
  92.                 this.SrX := Min(Max(xLeft, this.SrX - xdiff), SourceW-limit)
  93.  
  94.                 yUp := Max(-this.SrH + limit, -this.srw / guiRatio + limit)
  95.                 ydiff := my - lmy
  96.                 this.Sry := Min(Max(yUp, this.SrY - ydiff), SourceH-limit)
  97.  
  98.                 thumbW := Max(guiH * this.Ratio, guiW)
  99.                 thumbH := Max(guiW / this.Ratio, guiH)
  100.                 this.Thumbnail.SetSourceRegion(this.SrX, this.SrY, this.SrW, this.SrH)
  101.                 lmx := mx, lmy := my
  102.                 sleep 1
  103.             }
  104.         }
  105.         MouseState := "Click"
  106.     }
  107.     WM_MOUSEWHEEL(wParam, lParam, msg, hwnd) {
  108.         if hwnd != this.hwnd
  109.             return
  110.  
  111.         this.GetClientPos(,,&guiW, &guiH)
  112.  
  113.         wheel := Integer((wParam << 32 >> 48) / 120)
  114.  
  115.         restoreX := this.SrX
  116.         restoreY := this.Sry
  117.         restoreW := this.SrW
  118.         restoreH := this.SrH
  119.  
  120.         multiplier := 10
  121.         this.SrX += wheel * multiplier
  122.         this.SrY += wheel * multiplier
  123.         this.SrW -= wheel * multiplier * 2
  124.         this.SrH -= wheel * multiplier * 2
  125.         this.Thumbnail.GetSourceSize(&sourceW, &sourceH)
  126.  
  127.         ; prevent zooming in too close
  128.         if this.SrW/sourceW < 0.08
  129.         || this.SrH/sourceH < 0.08 {
  130.             this.SrX := restoreX
  131.             this.SrY := restoreY
  132.             this.SrW := restoreW
  133.             this.SrH := restoreH
  134.             return
  135.         }
  136.  
  137.         if this.SrW > sourceW
  138.         && this.SrH > sourceH {
  139.             this.SrX := restoreX
  140.             this.SrW := SourceW
  141.             this.SrY := restoreY
  142.             this.srH := SourceH
  143.         }
  144.  
  145.         this.FillAll := (this.SrW = sourceW && this.SrH = sourceH)
  146.  
  147.         this.Thumbnail.SetSourceRegion(this.SrX, this.SrY, this.SrW, this.SrH)
  148.  
  149.         thumbW := Max(guiH * this.Ratio, guiW)
  150.         thumbH := Max(guiW / this.Ratio, guiH)
  151.  
  152.         this.Thumbnail.SetThumbRegion(0, 0, thumbW, thumbH)
  153.     }
  154.     GuiClose() {
  155.         OnMessage 0x201, this.Events.LBUTTONDOWN, 0
  156.         OnMessage 0x020A, this.Events.MOUSEWHEEL, 0
  157.         this.Events := ""
  158.     }
  159.     GuiSize(MinMax, guiW, guiH) {
  160.         if this.FillAll {
  161.             this.Thumbnail.GetSourceSize(&sourceW, &sourceH)
  162.             this.Thumbnail.SetSourceRegion(0, 0, sourceW, sourceH)
  163.             thumbW := Min(guiH * this.Ratio, guiW)
  164.             thumbH := Min(guiW / this.Ratio, guiH)
  165.             ThumbX := 0 + (guiW - thumbW)/2
  166.             ThumbY := 0 + (guiH - thumbH)/2
  167.             this.Thumbnail.SetThumbRegion(ThumbX, ThumbY, ThumbW, ThumbH)
  168.         } else {
  169.             thumbW := Max(guiH * this.Ratio, guiW)
  170.             thumbH := Max(guiW / this.Ratio, guiH)
  171.             this.Thumbnail.SetThumbRegion(0,0,thumbW,thumbH)
  172.         }
  173.     }
  174. }
  175.  
  176. ; https://www.autohotkey.com/boards/viewtopic.php?p=432779#p432779
  177. class Thumbnail {
  178.  
  179.     __New(hGui, hSource:=WinExist("A"), clientOnly:=false) {
  180.  
  181.         this.ClientOnly := clientOnly
  182.         hSource := WinExist(hSource)
  183.         hGui := WinExist(hGui)
  184.         if hSource {
  185.             if DllCall("dwmapi\DwmRegisterThumbnail", "Ptr", hGui, "Ptr", hSource, "Ptr*", &hThumbnailId := 0, "HRESULT")
  186.                 throw Error("DwmRegisterThumbnail failed")
  187.             this.hwndSource := hSource
  188.             this.Gui := hGui
  189.             this.ThumbnailID := hThumbnailId
  190.         }
  191.     }
  192.     __Delete() {
  193.         if this.HasProp('ThumbnailID')
  194.             DllCall("Dwmapi\DwmUnregisterThumbnail", "ptr", this.ThumbnailID)
  195.     }
  196.     GetSourceSize(&width, &height) {
  197.         Size := Buffer(8, 0)
  198.         if DllCall("dwmapi.dll\DwmQueryThumbnailSourceSize", "Uint", this.ThumbnailID, "Ptr", Size) {
  199.             return false
  200.         }
  201.         width := NumGet(Size, 0, "int")
  202.         height := NumGet(Size, 4, "int")
  203.     }
  204.     SetSourceRegion(X, Y, W, H) {
  205.         ; DWM_TNP_RECTSOURCE
  206.         this.SetRegion(0x2, X, Y, W, H)
  207.     }
  208.     SetThumbRegion(X, Y, W, H) {
  209.         ; DWM_TNP_RECTDESTINATION
  210.         this.SetRegion(0x1, X, Y, W, H)
  211.     }
  212.     SetRegion(flag, X, Y, W, H) {
  213.         clientOnly := this.ClientOnly
  214.         static DWM_TNP_SOURCECLIENTAREAONLY := 0x10
  215.         , DWM_TNP_RECTDESTINATION := 0x1
  216.         , DWM_TNP_RECTSOURCE := 0x2
  217.         DWM_THUMBNAIL_PROPERTIES := Buffer(48, 0)
  218.         flags := flag | DWM_TNP_SOURCECLIENTAREAONLY*(flag = DWM_TNP_RECTSOURCE)
  219.         NumPut( "uint", flags     , DWM_THUMBNAIL_PROPERTIES)
  220.         NumPut( "int" , X         , DWM_THUMBNAIL_PROPERTIES , 4 + 16*(flag = DWM_TNP_RECTSOURCE) )
  221.         NumPut( "int" , Y         , DWM_THUMBNAIL_PROPERTIES , 8 + 16*(flag = DWM_TNP_RECTSOURCE) )
  222.         NumPut( "int" , X + W     , DWM_THUMBNAIL_PROPERTIES , 12 + 16*(flag = DWM_TNP_RECTSOURCE) )
  223.         NumPut( "int" , Y + H     , DWM_THUMBNAIL_PROPERTIES , 16 + 16*(flag = DWM_TNP_RECTSOURCE) )
  224.         NumPut( "UInt", clientOnly, DWM_THUMBNAIL_PROPERTIES , 44)
  225.         this.UpdateThumbnailProperties(DWM_THUMBNAIL_PROPERTIES)
  226.     }
  227.     UpdateThumbnailProperties(pProp) {
  228.         DllCall("dwmapi\DwmUpdateThumbnailProperties", "Ptr", this.ThumbnailId, "Ptr", pProp)
  229.     }
  230. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement