GDIp and bitmap from window

Get help with using AutoHotkey (v1.1 and older) and its commands and hotkeys
sunevle
Posts: 1
Joined: 06 Oct 2015, 10:26

GDIp and bitmap from window

25 Nov 2015, 19:43

I need a script that will duplicate an image of the active window on a different part of the screen (top left side in this case)...
I've noticed that I have to activate two times the GUI otherwise it won't be shown the first time the hotkey is triggered... I mean:
At line #15 is the first it's displayed (although "invisible" at this point), then at line #37... if I delete the 15th line, the image will be shown the second time the function is executed, what's the reason behind this?

Right now the script only shows a static image, what about having the contents in semi-real time? I guess "Gdip_BitmapFromHWND" is not effective inside a loop?
Would "PrintWindow" and "BitBlt" be useful in this case? What's the approach in a nutshell?... Check the commented part where I tried to code

http://p.ahkscript.org/?p=a4f5753e

Code: Select all

#NoEnv  ; Recommended for performance and compatibility with future AutoHotkey releases.
; #Warn  ; Enable warnings to assist with detecting common errors.
SendMode Input  ; Recommended for new scripts due to its superior speed and reliability.
SetWorkingDir %A_ScriptDir%  ; Ensures a consistent starting directory.

#SingleInstance, Force
#Persistent

#include Gdip.ahk

pToken := Gdip_Startup()
OnExit, Exit
 
Gui, 1: -Caption +E0x80000 +LastFound +OwnDialogs +Owner +AlwaysOnTop
Gui, 1: Show, NA ;???
hwnd := WinExist()
hdc_gui := GetDC(hwnd)

space::
	id := WinExist("A")
	WinGetPos, x, y, w, h, ahk_id %id%
	
	;---
	pBitmap := Gdip_BitmapFromHWND(id)				;create Window Bitmap 
	hbm := Gdip_CreateHBITMAPFromBitmap(pBitmap)	;convert to GDI bmp
	
	hdc_bmp := CreateCompatibleDC()					;source DC
	obm := SelectObject(hdc_bmp, hbm)				;select converted GDI bmp into source DC
	G := Gdip_GraphicsFromHDC(hdc_bmp)				;get its Graphics
	
	Gdip_DrawImage(G, pBitmap)						;draw the captured bmp into it
	Gdip_DisposeImage(pBitmap)						;delete as is not longer used
	Gdip_DeleteGraphics(G)
	UpdateLayeredWindow(hwnd, hdc_bmp, 0, 0, w, h)
	;BitBlt(hdc_gui, 0, 0, w, h, hdc_bmp, 0, 0)

	Gui, 1: Show, NA ;???
	KeyWait, space
	Gui, 1: Cancel
	SelectObject(hdc_bmp, obm), DeleteObject(hbm)
	DeleteDC(hdc_bmp)
	

	/*
	hbm := CreateDIBSection(w, h), hdc := CreateCompatibleDC(), obm := SelectObject(hdc, hbm)
	G := Gdip_GraphicsFromHDC(hdc)
	Loop
	{
		if (first)
		{
			first := !first
			Gui, 1: Show, NA ;???
		}
		if (!Mod(A_Index, 50))
		{
			;PrintWindow(hwnd, hdc)
			pBitmap := Gdip_BitmapFromHWND(id) ; ----> ???
			Gdip_DrawImage(G, pBitmap)
			
			BitBlt(hdc_gui, 0, 0, w, h, hdc, 0, 0)
			Gdip_DisposeImage(pBitmap)
		}
		if (!GetKeyState("space", "P"))
			break
	}
	
	Gui, 1: Cancel
	Gdip_DeleteGraphics(G)
	SelectObject(hdc, obm), DeleteObject(hbm)
	DeleteDC(hdc)
	*/
return

Exit:
	DeleteDC(hdc_gui)
	Gdip_Shutdown(pToken)
	ExitApp
return
iPhilip
Posts: 817
Joined: 02 Oct 2013, 12:21

Re: GDIp and bitmap from window

28 Oct 2021, 11:04

Hi @sunevle,

I realize this is 6 years late but I came across this post yesterday and was curious about what you were trying to do. I came up with the following code which works for me. Let me know if you have any questions.

Code: Select all

#NoEnv
#Include *i Gdip.ahk

Scale := 2

Gui, +AlwaysOnTop +Hwndhwnd +Owner +E0x80000
Gui, Show, NA
pToken := Gdip_Startup()
hbm := CreateDIBSection(A_ScreenWidth, A_ScreenHeight)
hdc := CreateCompatibleDC()
obm := SelectObject(hdc, hbm)
G := Gdip_GraphicsFromHDC(hdc)
OnExit("ExitFunc")
return

Space::
   pBitmap := Gdip_BitmapFromHWND(WinExist("A"))
   Gdip_GetImageDimensions(pBitmap, Width, Height)
   sWidth := Width // Scale, sHeight := Height // Scale
   Gdip_DrawImage(G, pBitmap, 0, 0, sWidth, sHeight, 0, 0, Width, Height)
   Gdip_DisposeImage(pBitmap)
   UpdateLayeredWindow(hwnd, hdc, 0, 0, sWidth, sHeight)
   KeyWait, % A_ThisHotkey
   Gdip_GraphicsClear(G)
   UpdateLayeredWindow(hwnd, hdc, 0, 0, sWidth, sHeight)
return

Esc::ExitApp

ExitFunc() {
   global
   SelectObject(hdc, obm)
   DeleteObject(hbm)
   DeleteDC(hdc)
   Gdip_DeleteGraphics(G)
   Gdip_Shutdown(pToken)
}
Note: For multi-monitor configurations, this only works if the DPI of the monitor where the window is located matches the DPI of the primary monitor.
Windows 10 Pro (64 bit) - AutoHotkey v2.0+ (Unicode 64-bit)
malcev
Posts: 1769
Joined: 12 Aug 2014, 12:37

Re: GDIp and bitmap from window

28 Oct 2021, 12:48

Better use dwm thumbnail api for such tasks.
iPhilip
Posts: 817
Joined: 02 Oct 2013, 12:21

Re: GDIp and bitmap from window

28 Oct 2021, 13:24

@malcev - Thank you for that suggestion. I just found @cyruz's LiveThumb class (link). I will look into it.
Windows 10 Pro (64 bit) - AutoHotkey v2.0+ (Unicode 64-bit)
malcev
Posts: 1769
Joined: 12 Aug 2014, 12:37

Re: GDIp and bitmap from window

28 Oct 2021, 13:41

You can look at example by teadrinker here:
viewtopic.php?f=76&t=94376
iPhilip
Posts: 817
Joined: 02 Oct 2013, 12:21

Re: GDIp and bitmap from window

28 Oct 2021, 14:04

Thank you. :)
Windows 10 Pro (64 bit) - AutoHotkey v2.0+ (Unicode 64-bit)
iPhilip
Posts: 817
Joined: 02 Oct 2013, 12:21

Re: GDIp and bitmap from window

28 Oct 2021, 16:54

Here is an improved version of my earlier post using @teadrinker's ThumbnailGui class:

Code: Select all

#NoEnv

Scale := 2

Gui, +AlwaysOnTop -Caption -DpiScale +HwndhThumb +Owner
Return

Space::
   hwnd := WinExist("A")
   WinGetPos, X0, Y0
   Pos := WinGetPosEx(hwnd)
   X := Pos.Left - X0
   Y := Pos.Top - Y0
   W := Pos.Right - Pos.Left
   H := Pos.Bottom - Pos.Top
   sW := W // Scale, sH := H // Scale
   Thumb := new ThumbnailGui(hThumb, sW, sH, hwnd, X, Y, W, H)
   Gui, Show, x0 y0 w%sW% h%sH%
   KeyWait, % A_ThisHotkey
   Gui, Hide
return

WinGetPosEx(hwnd) {
   static DWMWA_EXTENDED_FRAME_BOUNDS := 9  ; Gets the extended frame bounds rectangle in screen space (dwmapi.h)
   VarSetCapacity(RECT, 16, 0)
   if DllCall("Dwmapi\DwmGetWindowAttribute", "Ptr", hwnd, "UInt", DWMWA_EXTENDED_FRAME_BOUNDS, "Ptr", &RECT, "UInt", 16, "Int")
      DllCall("User32\GetWindowRect", "Ptr", hwnd, "Ptr", &RECT, "Int")
   return {Left:NumGet(RECT, 0, "Int"), Top:NumGet(RECT, 4, "Int"), Right:NumGet(RECT, 8, "Int"), Bottom:NumGet(RECT, 12, "Int")}
}

Esc::ExitApp

; https://www.autohotkey.com/boards/viewtopic.php?p=418848#p418848

class ThumbnailGui
{
   __New(hWndThumb, thumbW, thumbH, hWndSource, sourceX, sourceY, sourceW, sourceH, clientOnly := false) {
      this.hLib := DllCall("LoadLibrary", "Str", "dwmapi.dll")
      if DllCall("dwmapi\DwmRegisterThumbnail", "Ptr", hWndThumb, "Ptr", hWndSource, "PtrP", hThumbnailId) != 0
         throw "DwmRegisterThumbnail failed"
      this.ThumbnailId := hThumbnailId
      this.SetSourceRegion(sourceX, sourceY, sourceW, sourceH, clientOnly)
      this.SetThumbRegion(thumbW, thumbH)
   }
   __Delete() {
      DllCall("dwmapi\DwmUnregisterThumbnail", "Ptr", this.ThumbnailId)
      DllCall("FreeLibrary", "Ptr", this.hLib)
   }
   SetSourceRegion(X, Y, W, H, clientOnly) {
      this.SetRegion(DWM_TNP_RECTSOURCE := 0x2, X, Y, W, H, clientOnly)
   }
   SetThumbRegion(W, H) {
      this.SetRegion(DWM_TNP_RECTDESTINATION := 0x1, 0, 0, W, H)
   }
   SetRegion(flag, X, Y, W, H, clientOnly := false) {
      static DWM_TNP_SOURCECLIENTAREAONLY := 0x10
           , DWM_TNP_RECTDESTINATION := 0x1
           , DWM_TNP_RECTSOURCE := 0x2
      VarSetCapacity(DWM_THUMBNAIL_PROPERTIES, 48, 0)
      flags := flag | DWM_TNP_SOURCECLIENTAREAONLY*(flag = DWM_TNP_RECTSOURCE)
      NumPut( flags     , DWM_THUMBNAIL_PROPERTIES)
      NumPut( X         , DWM_THUMBNAIL_PROPERTIES,  4 + 16*(flag = DWM_TNP_RECTSOURCE) )
      NumPut( Y         , DWM_THUMBNAIL_PROPERTIES,  8 + 16*(flag = DWM_TNP_RECTSOURCE) )
      NumPut( X + W     , DWM_THUMBNAIL_PROPERTIES, 12 + 16*(flag = DWM_TNP_RECTSOURCE) )
      NumPut( Y + H     , DWM_THUMBNAIL_PROPERTIES, 16 + 16*(flag = DWM_TNP_RECTSOURCE) )
      NumPut( clientOnly, DWM_THUMBNAIL_PROPERTIES, 44, "UInt")
      this.UpdateThumbnailProperties(&DWM_THUMBNAIL_PROPERTIES)
   }
   UpdateThumbnailProperties(pProp) {
      DllCall("dwmapi\DwmUpdateThumbnailProperties", "Ptr", this.ThumbnailId, "Ptr", pProp)
   }
}
Windows 10 Pro (64 bit) - AutoHotkey v2.0+ (Unicode 64-bit)

Return to “Ask for Help (v1)”

Who is online

Users browsing this forum: Anput, ArkuS, Google [Bot], mikeyww, Nerafius and 79 guests