[CLASS] LiveThumb - DWM thumbnail implementation

Post your working scripts, libraries and tools for AHK v1.1 and older
User avatar
cyruz
Posts: 346
Joined: 30 Sep 2013, 13:31

[CLASS] LiveThumb - DWM thumbnail implementation

28 Jul 2019, 05:06

Hello guys,

this is an implementation of the DWM api part related to the thumbnail management.

Thanks to maul-esel that already implemented something similar (https://github.com/maul-esel/AeroThumbnail) but I wanted and implementation that would reflect the API usage patterns, so here we are.

* Fixed Destructor bug noticed by Helgef *
* Fixed missing return type noticed by Helgef *
* Fixed HRESULT return code potential issue *
* Replaced LocalAlloc for Object.SetCapacity/GetAddress *
* Fixed Object.SetCapacity not 0-filling dwFlags memory, causing inconsistent results *
* Fixed DWM_THUMB_PROPERTIES structure offsets thanks to swagfag *

LAST UPDATE: Nov. 15th, 2022

Code: Select all

; ----------------------------------------------------------------------------------------------------------------------
; Name .........: LiveThumb class library
; Description ..: Windows live thumbnails implementation (requires AERO to be enabled).
; AHK Version ..: AHK_L 1.1.30.01 x32/64 ANSI/Unicode
; Author .......: cyruz - http://ciroprincipe.info
; Thanks .......: maul-esel - https://github.com/maul-esel/AeroThumbnail
; License ......: WTFPL - http://www.wtfpl.net/txt/copying/
; Changelog ....: Feb. 21, 2019 - v0.1.0 - First version.
; ..............: Mar. 04, 2019 - v0.1.1 - Added active properties management and propertes getters.
; ..............: Jul. 28, 2019 - v0.1.2 - Added "Discard" method. Fixed LoadLibrary return type and a wrong behavior
; ..............:                          when returning false from the constructor (thanks Helgef).
; ..............: Sep. 21, 2019 - v0.1.3 - Fixed potential issue with HRESULT return code. Used internal memory
; ..............:                          management instead of LocalAlloc.
; ..............: Sep. 21, 2019 - v0.1.4 - Fixed Object.SetCapacity not zero-filling allocated memory.
; ..............: Nov. 15, 2022 - v0.1.5 - Fixed DWM_THUMB_PROPERTIES structure offsets (thanks swagfag).
; Remarks ......: The class registers a thumbnail and waits for properties update. When all the desired properties have
; ..............: been updated, the "Update()" method should be called to submit the properties. Getting a property
; ..............: when an update has not been performed before, will result in the string "NOT UPDATED" to be returned.
; ..............: Due to some internal unknown reason, the instantiated object must be in the global namespace to work.
; Info .........: Implements the following functions and structures from Win32 API.
; ..............: "DwmRegisterThumbnail" Win32 function:
; ..............: https://docs.microsoft.com/en-us/windows/desktop/api/dwmapi/nf-dwmapi-dwmregisterthumbnail
; ..............: "SIZE" Win32 structure:
; ..............: https://docs.microsoft.com/en-us/previous-versions//dd145106(v=vs.85)
; ..............: "DwmQueryThumbnailSourceSize" Win32 function:
; ..............: https://docs.microsoft.com/en-us/windows/desktop/api/dwmapi/nf-dwmapi-dwmquerythumbnailsourcesize
; ..............: "DWM_THUMB_PROPERTIES" Win32 structure:
; ..............: https://docs.microsoft.com/en-us/windows/desktop/api/dwmapi/ns-dwmapi-_dwm_thumbnail_properties
; ..............: "DWM_TNP" Constants for the dwFlags field:
; ..............: https://docs.microsoft.com/en-us/windows/desktop/dwm/dwm-tnp-constants
; ..............: "DwmUpdateThumbnailProperties" Win32 function:
; ..............: https://docs.microsoft.com/en-us/windows/desktop/api/dwmapi/nf-dwmapi-dwmupdatethumbnailproperties
; ..............: "DwmUnregisterThumbnail" Win32 function:
; ..............: https://docs.microsoft.com/en-us/windows/desktop/api/dwmapi/nf-dwmapi-dwmunregisterthumbnail
; ----------------------------------------------------------------------------------------------------------------------

/*

* How to use:
-------------

Instantiate the object:

    thumb := New LiveThumb(hSource, hDestination)

Modify its properties:

    thumb.Source := [0, 0, 300, 300]
    thumb.Destination := [0, 0, 500, 500]
    thumb.Visible := True

Update the properties:

    thumb.Update()

Get a property:

    aProp := thumb.Visible


* Example:
----------

#SingleInstance Force
#Include <LiveThumb>

Run, mspaint.exe,,, nPid
WinWaitActive, ahk_pid %nPid%

WinGet, hPaint, ID, ahk_pid %nPid%
WinGetPos,,, nW, nH, ahk_pid %nPid%

Gui, +HwndhGui

hLT := new LiveThumb(hPaint, hGui)
hLT.Source      := [0, 0, nW, nH]
hLT.Destination := [0, 0, nW, nH]
hLT.Visible     := True
hLT.Update()

Gui, Show, w%nW% h%nH%

*/

; Name .........: LiveThumb - PUBLIC CLASS
; Description ..: Manages thumbnails creation and destruction.
Class LiveThumb
{
    Static DLL_MODULE  :=                                 0
         , OBJ_COUNTER :=                                 0
         , DTP_SIZE    :=                                48
         , DTP_DWFLAGS := { "Destination"          : 0x0001
                          , "Source"               : 0x0002
                          , "Opacity"              : 0x0004
                          , "Visible"              : 0x0008
                          , "SourceClientAreaOnly" : 0x0010 }
         , DTP_OFFSETS := { "dwFlags"              :      0
                          , "Destination"          :      4
                          , "Source"               :     20
                          , "Opacity"              :     36
                          , "Visible"              :     37
                          , "SourceClientAreaOnly" :     41 }
                                 
    ; Name .........: __New - PRIVATE CONSTRUCTOR
    ; Description ..: Initialize the object, registering a new thumbnail and allocating the memory.
    ; Parameters ...: hSource = Handle to the window to be previewed.
    ; ..............: hDest   = Handle to the window containing the live preview.
    ; Return .......: LiveThumb object on success - False on error.
    __New( hSource, hDest )
    {
        ; Load the library on first run.
        If ( !LiveThumb.DLL_MODULE )
            LiveThumb.DLL_MODULE := DllCall("LoadLibrary", "Str","dwmapi.dll", "Ptr")

        LiveThumb.OBJ_COUNTER += 1

        ; Register a thumbnail to get an ID.
        If ( DllCall( "dwmapi.dll\DwmRegisterThumbnail"
                    , "Ptr",  hDest
                    , "Ptr",  hSource
                    , "Ptr*", phThumb
                    , "UPtr" ) )
            Return False
        
        this.THUMB_ID      := phThumb
        this.THUMB_UPDATED := False

        ; We define 2 portions of memory used for properties update and active properties tracking.
        this.SetCapacity("THUMB_UPD_PROP", LiveThumb.DTP_SIZE)
        this.SetCapacity("THUMB_ACT_PROP", LiveThumb.DTP_SIZE)
        this.THUMB_UPD_PROP_PTR := this.GetAddress("THUMB_UPD_PROP")
        this.THUMB_ACT_PROP_PTR := this.GetAddress("THUMB_ACT_PROP")

        ; Object.SetCapacity doesn't zero-fill the allocated memory so we call the Discard method.
        this.Discard( )
        
        Return this
    }

    ; Name .........: __Delete - PRIVATE DESTRUCTOR
    ; Description ..: Unregister the thumbnail and deallocate memory.
    __Delete( )
    {
        ; Unregister thumbnail ID.
        If ( this.THUMB_ID )
            DllCall( "dwmapi.dll\DwmUnregisterThumbnail"
                   , "Ptr", this.THUMB_ID )  
            
        ; If it's last instantiated object, free the library.
        If ( LiveThumb.DLL_MODULE && !(LiveThumb.OBJ_COUNTER -= 1) )
        {
            DllCall("FreeLibrary", "Ptr",LiveThumb.DLL_MODULE)
            LiveThumb.DLL_MODULE := 0
        }
    }

    ; Name .........: __Get - PRIVATE META FUNCTION
    ; Description ..: Return the string "NOT UPDATED" if properties have not been updated on each property get request.
    __Get( aName )
    {
        If ( LiveThumb.DTP_DWFLAGS[aName] && !this.THUMB_UPDATED )
            Return "NOT UPDATED"
    }

    ; Name .........: __Set - PRIVATE META FUNCTION
    ; Description ..: Update the dwFlags field of the structure on each property update.
    __Set( aName, aVal )
    {
        If ( LiveThumb.DTP_DWFLAGS[aName] )
        {
            NumPut( NumGet( this.THUMB_UPD_PROP_PTR+0
                          , LiveThumb.DTP_OFFSETS.dwFlags
                          , "UInt" ) | LiveThumb.DTP_DWFLAGS[aName]
                  , this.THUMB_UPD_PROP_PTR+0
                  , LiveThumb.DTP_OFFSETS.dwFlags
                  , "UInt" )
            this.THUMB_PENDING_UPDATE := True
        }
    }

    ; Name .........: QuerySourceSize - PUBLIC METHOD
    ; Description ..: Return the size (width/height) of the source thumbnail.
    ; Return .......: Array with width and height values - False on error.
    QuerySourceSize( )
    {
        VarSetCapacity(SIZE, 8, 0)
        If ( DllCall( "dwmapi.dll\DwmQueryThumbnailSourceSize"
                    , "Ptr", this.THUMB_ID
                    , "Ptr", &SIZE
                    , "UPtr" ) )
            Return False, VarSetCapacity(SIZE, 0)
        Return [NumGet(SIZE, 0, "Int"), NumGet(SIZE, 4, "Int")], VarSetCapacity(SIZE, 0)
    }

    ; Name .........: Update - PUBLIC METHOD
    ; Description ..: Update thumbnail properties and zero fill the dwFlags memory to be ready for next update.
    ; Return .......: True on success - False on error.
    Update( )
    {
        ; If no update is pending, return false.
        If ( !this.THUMB_PENDING_UPDATE )
            Return False

        ; Update properties.
        If ( DllCall( "dwmapi.dll\DwmUpdateThumbnailProperties"
                    , "Ptr", this.THUMB_ID
                    , "Ptr", this.THUMB_UPD_PROP_PTR
                    , "UPtr" ) )
            Return False
        
        ; Flag as updated and copy memory so that we can use this portion to track active properties with getters.
        this.THUMB_UPDATED := True
        DllCall( "NtDll.dll\RtlCopyMemory"
               , "Ptr",  this.THUMB_ACT_PROP_PTR
               , "Ptr",  this.THUMB_UPD_PROP_PTR
               , "UInt", LiveThumb.DTP_SIZE )
        
        ; Use the "Discard" method to reset dwFlags and return.
        this.Discard( )
        Return True
    }

    ; Name .........: Discard - PUBLIC METHOD
    ; Description ..: Discard set properties, resetting dwFlags memory.
    Discard( )
    {
        ; Zero-fill dwFlags memory in the properties update memory portion.
        NumPut(0, this.THUMB_UPD_PROP_PTR+0, LiveThumb.DTP_OFFSETS.dwFlags, "UInt")
        this.THUMB_PENDING_UPDATE := False
    }

    ; Name .........: Destination - PUBLIC PROPERTY
    ; Description ..: The area in the destination window where the thumbnail will be rendered.  
    ; Value ........: Array with 4 client related coordinates [ left, top, right, bottom ].
    ; Remarks ......: "Destination" property is of "RECT" type (16 bytes structure) and starts from offset 4.
    Destination[] {
        Get {
            arrRet := []
            Loop 4
                arrRet.Push(NumGet(this.THUMB_ACT_PROP_PTR+0, LiveThumb.DTP_OFFSETS.Destination * A_Index, "Int"))
            Return arrRet
        }
        Set {
            Loop 4
                NumPut(value[A_Index], this.THUMB_UPD_PROP_PTR+0, LiveThumb.DTP_OFFSETS.Destination * A_Index, "Int")
        }
    }

    ; Name .........: Source - PUBLIC PROPERTY
    ; Description ..: The region of the source window to use as the thumbnail. Default is the entire window.    
    ; Value ........: Array with 4 client related coordinates [ left, top, right, bottom ].
    ; Remarks ......: "Source" property is of "RECT" type (16 bytes structure) and starts from offset 20.
    Source[] {
        Get {
            arrRet := []
            Loop 4
                arrRet.Push(NumGet(this.THUMB_ACT_PROP_PTR+0, LiveThumb.DTP_OFFSETS.Source + 4*(A_Index-1), "Int"))
            Return arrRet   
        }
        Set {
            Loop 4
                NumPut(value[A_Index], this.THUMB_UPD_PROP_PTR+0, LiveThumb.DTP_OFFSETS.Source + 4*(A_Index-1), "Int")
        }
    }

    ; Name .........: Opacity - PUBLIC PROPERTY
    ; Description ..: The opacity with which to render the thumbnail. 0: transparent - 255: opaque. Default is 255.
    ; Value ........: Integer value from 0 to 255.
    ; Remarks ......: "Opacity" property is of "BYTE" type (1 byte + 3 padding) and starts from offset 36.
    Opacity[] {
        Get {
            Return NumGet(this.THUMB_ACT_PROP_PTR+0, LiveThumb.DTP_OFFSETS.Opacity, "UChar")
        }
        Set {
            NumPut(value, this.THUMB_UPD_PROP_PTR+0, LiveThumb.DTP_OFFSETS.Opacity, "UChar")
        }
    }

    ; Name .........: Visible - PUBLIC PROPERTY
    ; Description ..: True to make the thumbnail visible, otherwise False. Default is False.
    ; Value ........: Boolean True/False or integer 1/0 value.
    ; Remarks ......: "Visible" property is of "BOOL" type (4 bytes) and starts from offset 40.
    Visible[] {
        Get {
            Return NumGet(this.THUMB_ACT_PROP_PTR+0, LiveThumb.DTP_OFFSETS.Visible, "Int")
        }
        Set {
            NumPut(value, this.THUMB_UPD_PROP_PTR+0, LiveThumb.DTP_OFFSETS.Visible, "Int")
        }
    }

    ; Name .........: SourceClientAreaOnly - PUBLIC PROPERTY
    ; Description ..: True to use only the thumbnail source's client area, otherwise False. Default is False.
    ; Value ........: Boolean True/False or integer 1/0 value.
    ; Remarks ......: "SourceClientAreaOnly" property is of "BOOL" type (4 bytes) and starts from offset 44.
    SourceClientAreaOnly[] {
        Get {
            Return NumGet(this.THUMB_ACT_PROP_PTR+0, LiveThumb.DTP_OFFSETS.SourceClientAreaOnly, "Int")
        }
        Set {
            NumPut(value, this.THUMB_UPD_PROP_PTR+0, LiveThumb.DTP_OFFSETS.SourceClientAreaOnly, "Int")
        }
    }
}

An example...

Code: Select all

#SingleInstance Force
#Include <LiveThumb>

Run, mspaint.exe,,, nPid
WinWaitActive, ahk_pid %nPid%

WinGet, hPaint, ID, ahk_pid %nPid%
WinGetPos,,, nW, nH, ahk_pid %nPid%

Gui, +HwndhGui

hLT := new LiveThumb(hPaint, hGui)
hLT.Source      := [0, 0, nW, nH]
hLT.Destination := [0, 0, nW, nH]
hLT.Visible     := True
hLT.Update()

Gui, Show, w%nW% h%nH%

Cheers :beer:
Last edited by cyruz on 14 Nov 2022, 20:56, edited 13 times in total.
ABCza on the old forum.
My GitHub.
Helgef
Posts: 4709
Joined: 17 Jul 2016, 01:02
Contact:

Re: [CLASS] LiveThumb - DWM thumbnail implementation

28 Jul 2019, 09:08

Nice :thumbup: .

A few notes.
  • When you return false from the constructor, the destructor will be called and you will call LocalFree regardless of whether these have been allocated or not. You will also do LiveThumb.OBJ_COUNTER -= 1 without the corresponing increment, so you will mess up your count.
  • The return type for LoadLibrary should be ptr, it could be significant on 64 bit builds.
  • On win10, the example doesn't work because :arrow: the calculator is weird on win10. So win10 users can use Run, mspaint.exe,,, nPid instead.
Thanks for sharing, cheers.
User avatar
cyruz
Posts: 346
Joined: 30 Sep 2013, 13:31

Re: [CLASS] LiveThumb - DWM thumbnail implementation

28 Jul 2019, 10:07

Helgef wrote:
28 Jul 2019, 09:08
Nice :thumbup: .

A few notes.
  • When you return false from the constructor, the destructor will be called and you will call LocalFree regardless of whether these have been allocated or not. You will also do LiveThumb.OBJ_COUNTER -= 1 without the corresponing increment, so you will mess up your count.
  • The return type for LoadLibrary should be ptr, it could be significant on 64 bit builds.
  • On win10, the example doesn't work because :arrow: the calculator is weird on win10. So win10 users can use Run, mspaint.exe,,, nPid instead.
Thanks for sharing, cheers.

Oh! Thank you very much for taking your time to review the code... That destructor thing blew my mind, I was unaware of that behavior (I guess I need to double check some of my scripts for this).

I updated the code.

Thanks and cheers :D
ABCza on the old forum.
My GitHub.
neogna2
Posts: 591
Joined: 15 Sep 2016, 15:44

Re: [CLASS] LiveThumb - DWM thumbnail implementation

29 Jul 2019, 03:46

This is great! Is it possible to make a LiveThumb out of one whole screen (include all the windows visible on that screen) or out of one XYWH rectangle area of a screen? To display on another screen also connected to the PC.
Helgef
Posts: 4709
Joined: 17 Jul 2016, 01:02
Contact:

Re: [CLASS] LiveThumb - DWM thumbnail implementation

29 Jul 2019, 04:03

@neogna2, if I recall correctly, no.
@cyruz, the calls to LocalAlloc need return type ptr

Cheers.
User avatar
cyruz
Posts: 346
Joined: 30 Sep 2013, 13:31

Re: [CLASS] LiveThumb - DWM thumbnail implementation

29 Jul 2019, 05:08

neogna2 wrote:
29 Jul 2019, 03:46
This is great! Is it possible to make a LiveThumb out of one whole screen (include all the windows visible on that screen) or out of one XYWH rectangle area of a screen? To display on another screen also connected to the PC.
No, you must choose a top level window and you can eventually request an area of that window.
Helgef wrote:
29 Jul 2019, 04:03
@neogna2, if I recall correctly, no.
@cyruz, the calls to LocalAlloc need return type ptr

Cheers.
Done, thanks!
ABCza on the old forum.
My GitHub.
neogna2
Posts: 591
Joined: 15 Sep 2016, 15:44

Re: [CLASS] LiveThumb - DWM thumbnail implementation

24 Sep 2020, 06:35

@cyruz Could this be extended to include the mouse pointer or something representing the mouse pointer position?

edit

I extended the example script to transfer left mouse button clicks on LiveThumb to the same position on the source window.

Code: Select all

#SingleInstance force
#Include LiveThumb.ahk

Run, mspaint.exe,,, nPid
WinWaitActive, ahk_pid %nPid%

WinGet, hPaint, ID, ahk_pid %nPid%
WinGetPos,,, nW, nH, ahk_pid %nPid%

Gui, +HwndhGui

hLT := new LiveThumb(hPaint, hGui)
hLT.Source      := [0, 0, nW, nH]
hLT.Destination := [0, 0, nW, nH]
hLT.Visible     := True
hLT.Update()

Gui, Show, w%nW% h%nH%, LiveThumb

;transfer clicks on LiveThumb win to source win
Hotkey, IfWinActive, LiveThumb ahk_class AutoHotkeyGUI
Hotkey, Lbutton, TransferMouseClick
Return

TransferMouseClick:
    SetDefaultMouseSpeed, 0
    CoordMode, Mouse, Window
    MouseGetPos, MouseX, MouseY, A
    CoordMode, Mouse, Screen
    MouseGetPos, BackupX, BackupY, A
    WinGetPos, SourceX, SourceY, , , ahk_id %hPaint%
    TargetX := SourceX + MouseX
    TargetY := MouseY + SourceY
    Click, %TargetX%, %TargetY%
    MouseMove, % vBackupX, % vBackupY
Return
User avatar
cyruz
Posts: 346
Joined: 30 Sep 2013, 13:31

Re: [CLASS] LiveThumb - DWM thumbnail implementation

01 Oct 2020, 11:34

No, sadly this API is not very flexible...

Good job for the click transfer :thumbup:
ABCza on the old forum.
My GitHub.
twiz
Posts: 11
Joined: 08 Nov 2013, 03:34

Re: [CLASS] LiveThumb - DWM thumbnail implementation

20 May 2021, 01:40

Do you know how/if it's possible to "process" (i.e. adjust hue/saturation/brightness/contrast of) the thumbnail before it's shown?

Thank you so much for this!
hasantr
Posts: 933
Joined: 05 Apr 2016, 14:18
Location: İstanbul

Re: [CLASS] LiveThumb - DWM thumbnail implementation

22 May 2021, 09:06

twiz wrote:
20 May 2021, 01:40
Do you know how/if it's possible to "process" (i.e. adjust hue/saturation/brightness/contrast of) the thumbnail before it's shown?

Thank you so much for this!
The Header has this feature of the Bahhsed Maul-Esel Library.
doubledave22
Posts: 343
Joined: 08 Jun 2019, 17:36

Re: [CLASS] LiveThumb - DWM thumbnail implementation

28 Oct 2021, 14:44

Really cool!

I guess this has to be called every time a window moves?

It seems to blank out the gui if the window position changes.

Edit: Seems to be working now? Hows the CPU usage for something like this across like 15+ windows simultanously?
iPhilip
Posts: 822
Joined: 02 Oct 2013, 12:21

Re: [CLASS] LiveThumb - DWM thumbnail implementation

28 Oct 2021, 18:19

Hi @cyruz,

Thank you for sharing this class. I wanted to let you (and others) know about an issue when displaying an entire window (SourceClientAreaOnly := False). There is an offset in the coordinates that needs to be taken into account, at least for Notepad and SciTE4AuHotkey windows. Here is some code that shows how to manage that issue:

Code: Select all

#NoEnv
#Include LiveThumb.ahk

Scale := 2

Gui, +AlwaysOnTop -Caption -DpiScale +HwndhGui +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
   
   hLT := new LiveThumb(hwnd, hGui)
   hLT.Source      := [X, Y, X+W, Y+H]
   hLT.Destination := [0, 0, sW, sH]
   hLT.SourceClientAreaOnly := False
   hLT.Visible     := True
   hLT.Opacity     := 255
   hLT.Update()
   
   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
Finally, you may want to note in your examples that the arrays for the Source and Destination properties are RECT coordinates, i.e. Left, Top, Right, Bottom - not the usual X, Y, W, H. Even though you documented that in the body of the class, people may miss it if they just look at the examples.

Cheers!

- iPhilip
Windows 10 Pro (64 bit) - AutoHotkey v2.0+ (Unicode 64-bit)
swagfag
Posts: 6222
Joined: 11 Jan 2017, 17:59

Re: [CLASS] LiveThumb - DWM thumbnail implementation

09 Nov 2022, 17:22

struct offsets are wrong. its a packed struct #pragma pack(1)

Code: Select all

class _DWM_THUMBNAIL_PROPERTIES	size(45):
	+---
 0	| dwFlags
 4	| tagRECT rcDestination
20	| tagRECT rcSource
36	| opacity
37	| fVisible
41	| fSourceClientAreaOnly
	+---
User avatar
cyruz
Posts: 346
Joined: 30 Sep 2013, 13:31

Re: [CLASS] LiveThumb - DWM thumbnail implementation

12 Nov 2022, 11:37

swagfag wrote:
09 Nov 2022, 17:22
struct offsets are wrong. its a packed struct #pragma pack(1)

Code: Select all

class _DWM_THUMBNAIL_PROPERTIES	size(45):
	+---
 0	| dwFlags
 4	| tagRECT rcDestination
20	| tagRECT rcSource
36	| opacity
37	| fVisible
41	| fSourceClientAreaOnly
	+---
Oh... I didn't see the pragma pack declaration when I checked the header at the time. Do you have any link? The library seemed to work well...
ABCza on the old forum.
My GitHub.
neogna2
Posts: 591
Joined: 15 Sep 2016, 15:44

Re: [CLASS] LiveThumb - DWM thumbnail implementation

13 Nov 2022, 06:51

cyruz wrote:
12 Nov 2022, 11:37
The library seemed to work well...
Has seemingly worked well for me for a long time too. Seems the offset issue should impact Visible and SourceClientAreaOnly yet they seem to work ok. Not sure why.
swagfag
Posts: 6222
Joined: 11 Jan 2017, 17:59

Re: [CLASS] LiveThumb - DWM thumbnail implementation

14 Nov 2022, 19:14

its been there at least as far back as win7. probably safe to assume since its inception in vista too, but i havent bothered tracking down the sdk

since ObjSetCapacity() > realloc() doesnt zero initialize the memory, if u happen to get garbage assigned to bytes 37, 38 or 39, u wont be able to set .Visibility = false
User avatar
cyruz
Posts: 346
Joined: 30 Sep 2013, 13:31

Re: [CLASS] LiveThumb - DWM thumbnail implementation

14 Nov 2022, 20:51

swagfag wrote:
14 Nov 2022, 19:14
its been there at least as far back as win7. probably safe to assume since its inception in vista too, but i havent bothered tracking down the sdk

since ObjSetCapacity() > realloc() doesnt zero initialize the memory, if u happen to get garbage assigned to bytes 37, 38 or 39, u wont be able to set .Visibility = false

I found the header, you are right, I missed this: #include <pshpack1.h>

OP updated.
ABCza on the old forum.
My GitHub.

Return to “Scripts and Functions (v1)”

Who is online

Users browsing this forum: No registered users and 92 guests