Sign in to follow this  
Followers 0
monoceres

Simple vista thumbnail example

38 posts in this topic

Hi everyone!

Here's a simple example on how to get the dwm thumbnail that dwm generates for all windows into your own GUI.

Enjoy :P

Global Const $DWM_TNP_RECTDESTINATION = 0x00000001
Global Const $DWM_TNP_RECTSOURCE = 0x00000002
Global Const $DWM_TNP_OPACITY = 0x00000004
Global Const $DWM_TNP_VISIBLE = 0x00000008
Global Const $DWM_TNP_SOURCECLIENTAREAONLY = 0x00000010

Run("calc.exe")
WinWait("[CLASS:SciCalc]")
$calchwnd=WinGetHandle("[CLASS:SciCalc]")
$size=WinGetClientSize("[CLASS:SciCalc]")




$hwnd = GUICreate("Thumbnail", $size[0]*2, $size[1]*2)
GUISetState()


$DWM_THUMBNAIL_PROPERTIES = DllStructCreate("dword dwFlags;int rcDestination[4];int rcSource[4];byte opacity;int fVisible;int fSourceClientAreaOnly")

DllStructSetData($DWM_THUMBNAIL_PROPERTIES, "dwFlags",BitOr($DWM_TNP_RECTDESTINATION,$DWM_TNP_OPACITY,$DWM_TNP_VISIBLE ,$DWM_TNP_SOURCECLIENTAREAONLY))
DllStructSetData($DWM_THUMBNAIL_PROPERTIES,"rcDestination",0,1)
DllStructSetData($DWM_THUMBNAIL_PROPERTIES,"rcDestination",0,2)
DllStructSetData($DWM_THUMBNAIL_PROPERTIES,"rcDestination",$size[0]*2,3)
DllStructSetData($DWM_THUMBNAIL_PROPERTIES,"rcDestination", $size[1]*2,4)
DllStructSetData($DWM_THUMBNAIL_PROPERTIES,"opacity",128)
DllStructSetData($DWM_THUMBNAIL_PROPERTIES,"fVisible",1)
DllStructSetData($DWM_THUMBNAIL_PROPERTIES,"fSourceClientAreaOnly",1)


$call = DllCall("dwmapi.dll", "int", "DwmRegisterThumbnail", "hwnd", $hwnd, "hwnd", $calchwnd, "ptr*", 0)
$thumbid=$call[3]


$call=DllCall("dwmapi.dll","int","DwmUpdateThumbnailProperties","ptr",$thumbid,"ptr",DllStructGetPtr($DWM_THUMBNAIL_PROPERTIES))



Do
    $msg = GUIGetMsg()
Until $msg = -3

Screenshot:

Posted Image

And for those interested in the functions:

http://msdn.microsoft.com/en-us/library/aa969526(VS.85).aspx

http://msdn.microsoft.com/en-us/library/aa969521(VS.85).aspx


Broken link? PM me and I'll send you the file!

Share this post


Link to post
Share on other sites



This is pretty cool, makes me wish my vista-comp was working :P

Do you think it would be possible to build a Win+Tab replacer? (ofcourse without the 3d-part) That would be cool! :P

Share this post


Link to post
Share on other sites

This is pretty cool, makes me wish my vista-comp was working :P

Do you think it would be possible to build a Win+Tab replacer? (ofcourse without the 3d-part) That would be cool! :P

That would be rather simple, except that I can't HotKeySet the win+tab combination (same goes with alt.tab).


Broken link? PM me and I'll send you the file!

Share this post


Link to post
Share on other sites

This is really cool :P My vista doesnt have autoit tho :P


code

Share this post


Link to post
Share on other sites

#7 ·  Posted (edited)

I'm having some strangle problems with this. I've made a function that does the drawing of the thumb, but somehow the sizes for the dest-rect are totally wrong. I'm tring to draw it in a rectangle of 190x190, but it works right when I use a value of 355x355.

func CreateThumb($hSource, $hDest, $x, $y, $w, $h)
    $DWM_THUMBNAIL_PROPERTIES = DllStructCreate("dword dwFlags;int rcDestination[4];int rcSource[4];byte opacity;int fVisible;int fSourceClientAreaOnly")
    DllStructSetData($DWM_THUMBNAIL_PROPERTIES, "dwFlags", BitOr($DWM_TNP_RECTDESTINATION, $DWM_TNP_OPACITY, $DWM_TNP_VISIBLE, $DWM_TNP_SOURCECLIENTAREAONLY))
    DllStructSetData($DWM_THUMBNAIL_PROPERTIES, "rcDestination", $x, 1)
    DllStructSetData($DWM_THUMBNAIL_PROPERTIES, "rcDestination", $y, 2)
    DllStructSetData($DWM_THUMBNAIL_PROPERTIES, "rcDestination", $w, 3)
    DllStructSetData($DWM_THUMBNAIL_PROPERTIES, "rcDestination", $h, 4)
    DllStructSetData($DWM_THUMBNAIL_PROPERTIES, "opacity", 255)
    DllStructSetData($DWM_THUMBNAIL_PROPERTIES, "fVisible", 1)
    DllStructSetData($DWM_THUMBNAIL_PROPERTIES, "fSourceClientAreaOnly", 1)
    $call = DllCall("dwmapi.dll", "int", "DwmRegisterThumbnail", "hwnd", $hDest, "hwnd", $hSource, "ptr*", 0)
    $hThumb = $call[3]
    $call = DllCall("dwmapi.dll", "int", "DwmUpdateThumbnailProperties", "ptr", $hThumb, "ptr", DllStructGetPtr($DWM_THUMBNAIL_PROPERTIES))
    return $hThumb
endfunc
Edited by SaphuA

Share this post


Link to post
Share on other sites

#9 ·  Posted (edited)

Strangely, Windows 7's Calculator has a different class; CalcFrame.

Anyway, I also made this a function for easier use. Only thing I couldn't decide on how it should work was the flags, these are still pre-defined.

Global Const $DWM_TNP_RECTDESTINATION = 0x00000001
Global Const $DWM_TNP_RECTSOURCE = 0x00000002
Global Const $DWM_TNP_OPACITY = 0x00000004
Global Const $DWM_TNP_VISIBLE = 0x00000008
Global Const $DWM_TNP_SOURCECLIENTAREAONLY = 0x00000010

Run("calc.exe")
WinWait("[CLASS:CalcFrame]")
$calchwnd = WinGetHandle("[CLASS:CalcFrame]")
$size = WinGetClientSize("[CLASS:CalcFrame]")

$hwnd = GUICreate("Thumbnail", $size[0], $size[1])

_DWM_Thumbnail($hwnd, $calchwnd, 1, 2, $size[0], $size[1])

GUISetState()

Do
    $msg = GUIGetMsg()
Until $msg = -3

Func _DWM_Thumbnail($hWnd, $hWndOw, $rcDest_X, $rcDest_Y, $rcDest_Width, $rcDest_Height, $rcOpacity = 250, $rcReadOnly = True)
    $DWM_THUMBNAIL_PROPERTIES = DllStructCreate("dword dwFlags;int rcDestination[4];int rcSource[4];byte opacity;int fVisible;int fSourceClientAreaOnly")

    DllStructSetData($DWM_THUMBNAIL_PROPERTIES, "dwFlags", BitOR($DWM_TNP_RECTDESTINATION, $DWM_TNP_OPACITY, $DWM_TNP_VISIBLE, $DWM_TNP_SOURCECLIENTAREAONLY))
    DllStructSetData($DWM_THUMBNAIL_PROPERTIES, "rcDestination", 0, $rcDest_X)
    DllStructSetData($DWM_THUMBNAIL_PROPERTIES, "rcDestination", 0, $rcDest_Y)
    DllStructSetData($DWM_THUMBNAIL_PROPERTIES, "rcDestination", $rcDest_Width, 3)
    DllStructSetData($DWM_THUMBNAIL_PROPERTIES, "rcDestination", $rcDest_Height, 4)
    DllStructSetData($DWM_THUMBNAIL_PROPERTIES, "opacity", $rcOpacity)
    DllStructSetData($DWM_THUMBNAIL_PROPERTIES, "fVisible", $rcReadOnly)
    DllStructSetData($DWM_THUMBNAIL_PROPERTIES, "fSourceClientAreaOnly", 1)

    $call = DllCall("dwmapi.dll", "int", "DwmRegisterThumbnail", "hwnd", $hWnd, "hwnd", $hWndOw, "ptr*", 0)
    If Not IsArray($call) Then
        SetError(1) ; Register thumbnail failed
        Return 0
    Else
        $thumbid = $call[3]
    EndIf

    $call = DllCall("dwmapi.dll", "int", "DwmUpdateThumbnailProperties", "ptr", $thumbid, "ptr", DllStructGetPtr($DWM_THUMBNAIL_PROPERTIES))
EndFunc   ;==>_DWM_Thumbnail
Completely missed SaphuA's post. Ah well. Edited by JamesBrooks

Share this post


Link to post
Share on other sites

#10 ·  Posted (edited)

Now I feel like I'm picking on you... :/ sorry.

But shouldn't these two lines be like so, specifying the proper indexes:

DllStructSetData($DWM_THUMBNAIL_PROPERTIES, "rcDestination", $rcDest_X, 1)
DllStructSetData($DWM_THUMBNAIL_PROPERTIES, "rcDestination", $rcDest_Y, 2)

And the default opacity should be 255 as the max?

BTW, I love that the thumbnail is live :D

Edited by wraithdu

Share this post


Link to post
Share on other sites

Nice :D, but using WinGetClientSize() and setting fSourceClientAreaOnly to 1 does look a little blurry / resized on my computer.

#include <WindowsConstants.au3>
#include <GUIConstantsEx.au3>
#include <WinAPI.au3>

$iPID = Run("calc.exe")
If WinWait("[CLASS:CalcFrame]", "", 5) = 0 Then Exit

$hwnd_calc = WinGetHandle("[CLASS:CalcFrame]")

$a_WinGetClientSize = WinGetClientSize($hwnd_calc)
$a_WinGetPosEx = _WinGetPosEx($hwnd_calc)

ConsoleWrite($a_WinGetClientSize[0] & "x" & $a_WinGetClientSize[1] & @crlf)
ConsoleWrite($a_WinGetPosEx[2] & "x" & $a_WinGetPosEx[3] & @crlf)
ConsoleWrite(_WinAPI_GetClientWidth($hwnd_calc) & "x" & _WinAPI_GetClientHeight($hwnd_calc) & @crlf)

$hwnd1 = GUICreate("Thumbnail1 - fSourceClientAreaOnly = True", $a_WinGetClientSize[0], $a_WinGetClientSize[1], 100, 100, $WS_POPUP)
_DWM_Thumbnail($hwnd1, $hwnd_calc, 0, 0, $a_WinGetClientSize[0], $a_WinGetClientSize[1], 255, True, 1)
GUISetState()

$hwnd2 = GUICreate("Thumbnail2 - fSourceClientAreaOnly = False", $a_WinGetPosEx[2], $a_WinGetPosEx[3], 400, 100, $WS_POPUP, $GUI_WS_EX_PARENTDRAG)
_DWM_Thumbnail($hwnd2, $hwnd_calc, 0, 0, $a_WinGetPosEx[2], $a_WinGetPosEx[3], 255, True, 0)
GUISetState()



Do
    $msg = GUIGetMsg()
    Sleep(10)
    If Not ProcessExists($iPID) Then ExitLoop
Until $msg = -3



Func _DWM_Thumbnail($hwnd, $hWndOw, $rcDest_X, $rcDest_Y, $rcDest_Width, $rcDest_Height, $rcOpacity = 255, $rcReadOnly = True, $rcClientAreaOnly = 0)
    Local Const $DWM_TNP_RECTDESTINATION = 0x00000001
    Local Const $DWM_TNP_RECTSOURCE = 0x00000002
    Local Const $DWM_TNP_OPACITY = 0x00000004
    Local Const $DWM_TNP_VISIBLE = 0x00000008
    Local Const $DWM_TNP_SOURCECLIENTAREAONLY = 0x00000010

    $DWM_THUMBNAIL_PROPERTIES = DllStructCreate("dword dwFlags;int rcDestination[4];int rcSource[4];byte opacity;int fVisible;int fSourceClientAreaOnly")

    DllStructSetData($DWM_THUMBNAIL_PROPERTIES, "dwFlags", BitOR($DWM_TNP_RECTDESTINATION, $DWM_TNP_OPACITY, $DWM_TNP_VISIBLE, $DWM_TNP_SOURCECLIENTAREAONLY))
    DllStructSetData($DWM_THUMBNAIL_PROPERTIES, "rcDestination", $rcDest_X, 1)
    DllStructSetData($DWM_THUMBNAIL_PROPERTIES, "rcDestination", $rcDest_Y, 2)
    DllStructSetData($DWM_THUMBNAIL_PROPERTIES, "rcDestination", $rcDest_Width, 3)
    DllStructSetData($DWM_THUMBNAIL_PROPERTIES, "rcDestination", $rcDest_Height, 4)
    DllStructSetData($DWM_THUMBNAIL_PROPERTIES, "opacity", $rcOpacity)
    DllStructSetData($DWM_THUMBNAIL_PROPERTIES, "fVisible", $rcReadOnly)
    DllStructSetData($DWM_THUMBNAIL_PROPERTIES, "fSourceClientAreaOnly", $rcClientAreaOnly)

    $call = DllCall("dwmapi.dll", "int", "DwmRegisterThumbnail", "hwnd", $hwnd, "hwnd", $hWndOw, "ptr*", 0)
    If Not IsArray($call) Then
        SetError(1) ; Register thumbnail failed
        Return 0
    Else
        $thumbid = $call[3]
    EndIf

    $call = DllCall("dwmapi.dll", "int", "DwmUpdateThumbnailProperties", "ptr", $thumbid, "ptr", DllStructGetPtr($DWM_THUMBNAIL_PROPERTIES))
EndFunc   ;==>_DWM_Thumbnail


; #FUNCTION# =======================================================
; Name...........:  _WinGetPosEx
; Description ...:  Retrieves Window size and position similar to WinGetPos() but regards possible Aero effects on Vista and Win7
; Syntax.........:  _WinGetPosEx($hWnd)
; Parameters ....:  $hWnd - Handle to Window to measure
; Return values .:  Success:    Returns a 4-element array containing the following information:
;                               $array[0] = X position
;                               $array[1] = Y position
;                               $array[2] = Width
;                               $array[3] = Height
;                       Sets @extended  = 0 for Aero effect is OFF for $hWnd
;                                       = 1 for Aero effect is ON for $hWnd
;
;                   Failure:    Returns 0 and sets @error to 1 if windows is not found.
; Author ........: KaFu
; Link ..........; http://msdn.microsoft.com/en-us/library/aa969515%28VS.85%29.aspx
; Example .......; Yes
; ==================================================================
Func _WinGetPosEx($hwnd)
    If Not IsHWnd($hwnd) Then Return SetError(1, 0, 0)
    Local $aPos[4], $tRect = DllStructCreate("int Left;int Top;int Right;int Bottom")
    Local Const $DWMWA_EXTENDED_FRAME_BOUNDS = 9
    DllCall("dwmapi.dll", "hwnd", "DwmGetWindowAttribute", "hwnd", WinGetHandle($hwnd), "dword", $DWMWA_EXTENDED_FRAME_BOUNDS, "ptr", DllStructGetPtr($tRect), "dword", DllStructGetSize($tRect))
    If @error Then Return SetError(0, 0, WinGetPos($hwnd))
    Local $iRectLeft = DllStructGetData($tRect, "Left")
    Local $iRectTop = DllStructGetData($tRect, "Top")
    Local $iRectRight = DllStructGetData($tRect, "Right")
    Local $iRectBottom = DllStructGetData($tRect, "Bottom")
    If Abs($iRectLeft) + Abs($iRectTop) + Abs($iRectRight) + Abs($iRectBottom) > 0 Then
        $aPos[0] = $iRectLeft
        $aPos[1] = $iRectTop
        $aPos[2] = $iRectRight - $iRectLeft
        $aPos[3] = $iRectBottom - $iRectTop
        Return SetError(0, 1, $aPos)
    EndIf
    Return SetError(0, 0, WinGetPos($hwnd))
EndFunc   ;==>_WinGetPosEx

Share this post


Link to post
Share on other sites

The blurriness is due to resizing. This fixes it, but I don't know why the size if off in the thumbnail, it should match the GUI size without adjustments.

$hwnd1 = GUICreate("Thumbnail1 - fSourceClientAreaOnly = True", $a_WinGetClientSize[0], $a_WinGetClientSize[1] + 20, 100, 100, $WS_POPUP)
_DWM_Thumbnail($hwnd1, $hwnd_calc, 0, 0, $a_WinGetClientSize[0] + 10, $a_WinGetClientSize[1] + 20, 255, True, 1)

Share this post


Link to post
Share on other sites

#13 ·  Posted (edited)

Now I feel like I'm picking on you... :/ sorry.

Just a little.

But shouldn't these two lines be like so, specifying the proper indexes:

DllStructSetData($DWM_THUMBNAIL_PROPERTIES, "rcDestination", $rcDest_X, 1)
DllStructSetData($DWM_THUMBNAIL_PROPERTIES, "rcDestination", $rcDest_Y, 2)

Ah yes, I got muddled in the structure.

And the default opacity should be 255 as the max?

Stupid newbie mistake. I set it to 256 is at first, then thought "Oh wait.." I forgot it's 255.

How does this suit you?

Global Const $DWM_TNP_RECTDESTINATION = 0x00000001
Global Const $DWM_TNP_RECTSOURCE = 0x00000002
Global Const $DWM_TNP_OPACITY = 0x00000004
Global Const $DWM_TNP_VISIBLE = 0x00000008
Global Const $DWM_TNP_SOURCECLIENTAREAONLY = 0x00000010

Run("calc.exe")
WinWait("[CLASS:CalcFrame]")
$calchwnd = WinGetHandle("[CLASS:CalcFrame]")
$size = WinGetClientSize("[CLASS:CalcFrame]")

$hwnd = GUICreate("Thumbnail", $size[0], $size[1])

_DWM_Thumbnail($hwnd, $calchwnd, 1, 2, $size[0], $size[1])

GUISetState()

Do
    $msg = GUIGetMsg()
Until $msg = -3

Func _DWM_Thumbnail($hWnd, $hWndOw, $rcDest_X, $rcDest_Y, $rcDest_Width, $rcDest_Height, $rcOpacity = 255, $rcReadOnly = True)
    $DWM_THUMBNAIL_PROPERTIES = DllStructCreate("dword dwFlags;int rcDestination[4];int rcSource[4];byte opacity;int fVisible;int fSourceClientAreaOnly")

    DllStructSetData($DWM_THUMBNAIL_PROPERTIES, "dwFlags", BitOR($DWM_TNP_RECTDESTINATION, $DWM_TNP_OPACITY, $DWM_TNP_VISIBLE, $DWM_TNP_SOURCECLIENTAREAONLY))
    DllStructSetData($DWM_THUMBNAIL_PROPERTIES, "rcDestination", $rcDest_X, 1)
    DllStructSetData($DWM_THUMBNAIL_PROPERTIES, "rcDestination", $rcDest_Y, 2)
    DllStructSetData($DWM_THUMBNAIL_PROPERTIES, "rcDestination", $rcDest_Width, 3)
    DllStructSetData($DWM_THUMBNAIL_PROPERTIES, "rcDestination", $rcDest_Height, 4)
    DllStructSetData($DWM_THUMBNAIL_PROPERTIES, "opacity", $rcOpacity)
    DllStructSetData($DWM_THUMBNAIL_PROPERTIES, "fVisible", $rcReadOnly)
    DllStructSetData($DWM_THUMBNAIL_PROPERTIES, "fSourceClientAreaOnly", 1)

    $call = DllCall("dwmapi.dll", "int", "DwmRegisterThumbnail", "hwnd", $hWnd, "hwnd", $hWndOw, "ptr*", 0)
    If Not IsArray($call) Then
        SetError(1) ; Register thumbnail failed
        Return 0
    Else
        $thumbid = $call[3]
    EndIf

    $call = DllCall("dwmapi.dll", "int", "DwmUpdateThumbnailProperties", "ptr", $thumbid, "ptr", DllStructGetPtr($DWM_THUMBNAIL_PROPERTIES))
EndFunc   ;==>_DWM_Thumbnail
Edited by JamesBrooks

Share this post


Link to post
Share on other sites

The blurriness is due to resizing. This fixes it, but I don't know why the size if off in the thumbnail, it should match the GUI size without adjustments.

Found this quote: "Unlike menus, tool and status bars are seperate controls that live inside the parent window's client area."

Is assume that WinGetClientSize() does not consider the toolbar...

Share this post


Link to post
Share on other sites

#15 ·  Posted (edited)

Border size and caption needed to be determined.

#include <WindowsConstants.au3>
#include <GUIConstantsEx.au3>
#include <WinAPI.au3>
#include <Misc.au3>
#include <Constants.au3>

if @OSVersion = "WIN_7" Then
    $Class_Calc = "[CLASS:CalcFrame]"
ElseIf @OSVersion = "WIN_VISTA" Then
    $Class_Calc = "[CLASS:SciCalc]"
Else
    MsgBox(16,"Error","Vista or Win7 needed to run example.")
    Exit
endif

Opt("GUIOnEventMode", 1)
Opt("WinWaitDelay", 50)

$tTimer_Doubleclick = 0
$hM_Hook = _WinAPI_SetWindowsHookEx($WH_MOUSE_LL,DllCallbackGetPtr(DllCallbackRegister("_Mouse_Proc", "int", "int;ptr;ptr")),_WinAPI_GetModuleHandle(0))

HotKeySet("{ESC}","_exit")

$iZoomFactor = 1

$iPID = Run("calc.exe")

If WinWait($Class_Calc, "", 5) = 0 Then Exit

$hwnd_calc = WinGetHandle($Class_Calc)
$a_WinGetPosEx = _WinGetPosEx($hwnd_calc)
if @extended <> 1 Then
    MsgBox(16,"Error","AERO not enabled on your system. Example will not work.")
    ProcessClose($iPID)
    Exit
endif

$a_GetWindowInfo = _WinAPI_Ex_GetWindowInfo($hwnd_calc)
if UBound($a_GetWindowInfo) <> 16 then
    MsgBox(16,"Error","_WinAPI_Ex_GetWindowInfo() did not return result.")
    ProcessClose($iPID)
    Exit
endif

$a_WinGetPosEx[2] = $a_WinGetPosEx[2] - (2*$a_GetWindowInfo[13][1])
if BitAND($a_GetWindowInfo[9][1],$WS_CAPTION) then
    $a_WinGetPosEx[3] = $a_WinGetPosEx[3] - (2*$a_GetWindowInfo[13][1]) - _WinAPI_GetSystemMetrics(4)
Else
    $a_WinGetPosEx[3] = $a_WinGetPosEx[3] - (2*$a_GetWindowInfo[13][1])
endif

$hwnd = GUICreate("Vista Thumbnail", ($a_WinGetPosEx[2]) / (1/$iZoomFactor), ($a_WinGetPosEx[3]) / (1/$iZoomFactor), 100, 100, $WS_POPUP, $WS_EX_TOPMOST)
GUISetOnEvent($GUI_EVENT_PRIMARYDOWN, "_WindowDrag")
_DWM_Thumbnail($hwnd, $hwnd_calc, 0, 0, $a_WinGetPosEx[2] / (1/$iZoomFactor), $a_WinGetPosEx[3] / (1/$iZoomFactor), 255, True, 1)

$Big = True
AdlibRegister("_check_GUI_Pos")

GUISetState()

While sleep(10)
    If Not ProcessExists($iPID) Then ExitLoop
WEnd

_exit()

Func _exit()
    ProcessClose($iPID)
    _WinAPI_UnhookWindowsHookEx($hM_Hook)
    Exit
EndFunc

Func _check_GUI_Pos()
    $Win = WinGetPos($hwnd)
    if _WindowFromPoint() <> $hwnd then
        If $Big Then
            For $i = $a_WinGetPosEx[3] To 100 Step -5
                WinMove($hwnd, "", $Win[0], $Win[1], $a_WinGetPosEx[2] * ($i / $a_WinGetPosEx[3]), $i)
                _DWM_Thumbnail($hwnd, $hwnd_calc, 0, 0, $a_WinGetPosEx[2] * ($i / $a_WinGetPosEx[3]), $i, 255, True, 1)
            Next
            WinMove($hwnd, "", $Win[0], $Win[1], $a_WinGetPosEx[2] * (100 / $a_WinGetPosEx[3]), 100)
            _DWM_Thumbnail($hwnd, $hwnd_calc, 0, 0, $a_WinGetPosEx[2] * (100 / $a_WinGetPosEx[3]), 100, 255, True, 1)

            $Big = False
        EndIf
    Else
        If Not $Big Then
            For $i = 100 To $a_WinGetPosEx[3] Step 5
                WinMove($hwnd, "", $Win[0], $Win[1], $a_WinGetPosEx[2] * ($i / $a_WinGetPosEx[3]), $i)
                _DWM_Thumbnail($hwnd, $hwnd_calc, 0, 0, $a_WinGetPosEx[2] * ($i / $a_WinGetPosEx[3]), $i, 255, True, 1)
            Next
            WinMove($hwnd, "", $Win[0], $Win[1], $a_WinGetPosEx[2], $a_WinGetPosEx[3])
            _DWM_Thumbnail($hwnd, $hwnd_calc, 0, 0, $a_WinGetPosEx[2], $a_WinGetPosEx[3], 255, True, 1)
            $Big = True
        EndIf
    EndIf
EndFunc

Func _WindowFromPoint()
    ; from _GUICtrl_SetOnHover
    ; http://www.autoitscript.com/forum/index.ph...showtopic=55120
    ; by G.Sandler a.k.a MrCreatoR (CreatoR's Lab, http://creator-lab.ucoz.ru)
    Local $Old_Opt_MCM = Opt("MouseCoordMode", 1)
    Local $aRet = DllCall("User32.dll", "int", "WindowFromPoint", _
            "long", MouseGetPos(0), _
            "long", MouseGetPos(1))
    ;$aRet = DllCall("user32.dll", "int", "GetDlgCtrlID", "hwnd", $aRet[0])
    Opt("MouseCoordMode", $Old_Opt_MCM)
    Return $aRet[0]
EndFunc   ;==>_WindowFromPoint


Func _WindowDrag()
    While _IsPressed("01")
        DllCall("user32.dll", "int", "SendMessage", "hWnd", $hwnd, "int", $WM_NCLBUTTONDOWN, "int", $HTCAPTION, "int", 0)
    WEnd
EndFunc   ;==>_WindowDrag

Func _DWM_Thumbnail($hwnd, $hWndOw, $rcDest_X, $rcDest_Y, $rcDest_Width, $rcDest_Height, $rcOpacity = 255, $rcReadOnly = True, $rcClientAreaOnly = 0)
    Local Const $DWM_TNP_RECTDESTINATION = 0x00000001
    Local Const $DWM_TNP_RECTSOURCE = 0x00000002
    Local Const $DWM_TNP_OPACITY = 0x00000004
    Local Const $DWM_TNP_VISIBLE = 0x00000008
    Local Const $DWM_TNP_SOURCECLIENTAREAONLY = 0x00000010

    $DWM_THUMBNAIL_PROPERTIES = DllStructCreate("dword dwFlags;int rcDestination[4];int rcSource[4];byte opacity;int fVisible;int fSourceClientAreaOnly")

    DllStructSetData($DWM_THUMBNAIL_PROPERTIES, "dwFlags", BitOR($DWM_TNP_RECTDESTINATION, $DWM_TNP_OPACITY, $DWM_TNP_VISIBLE, $DWM_TNP_SOURCECLIENTAREAONLY))
    DllStructSetData($DWM_THUMBNAIL_PROPERTIES, "rcDestination", $rcDest_X, 1)
    DllStructSetData($DWM_THUMBNAIL_PROPERTIES, "rcDestination", $rcDest_Y, 2)
    DllStructSetData($DWM_THUMBNAIL_PROPERTIES, "rcDestination", $rcDest_Width, 3)
    DllStructSetData($DWM_THUMBNAIL_PROPERTIES, "rcDestination", $rcDest_Height, 4)
    DllStructSetData($DWM_THUMBNAIL_PROPERTIES, "opacity", $rcOpacity)
    DllStructSetData($DWM_THUMBNAIL_PROPERTIES, "fVisible", $rcReadOnly)
    DllStructSetData($DWM_THUMBNAIL_PROPERTIES, "fSourceClientAreaOnly", $rcClientAreaOnly)

    $call = DllCall("dwmapi.dll", "int", "DwmRegisterThumbnail", "hwnd", $hwnd, "hwnd", $hWndOw, "ptr*", 0)
    If Not IsArray($call) Then
        SetError(1) ; Register thumbnail failed
        Return 0
    Else
        $thumbid = $call[3]
    EndIf

    $call = DllCall("dwmapi.dll", "int", "DwmUpdateThumbnailProperties", "ptr", $thumbid, "ptr", DllStructGetPtr($DWM_THUMBNAIL_PROPERTIES))
EndFunc   ;==>_DWM_Thumbnail


Func _WinAPI_Ex_GetWindowInfo($hwnd)
    If Not IsHWnd($hwnd) Then Return SetError(1, 0, 0)

    ; http://msdn.microsoft.com/en-us/library/ms632610(VS.85).aspx
    $tWINDOWINFO = DllStructCreate("dword cbSize;int rcWindow_Left;int rcWindow_Top;int rcWindow_Right;int rcWindow_Bottom;int rcClient_Left;int rcClient_Top;int rcClient_Right;int rcClient_Bottom;dword dwStyle;dword dwExStyle;dword dwWindowStatus;uint cxWindowBorders;uint cyWindowBorders;byte atomWindowType;byte wCreatorVersion;")
    DllStructSetData($tWINDOWINFO, 1, DllStructGetSize($tWINDOWINFO))

    ; http://msdn.microsoft.com/en-us/library/ms633516(VS.85).aspx
    $aRet = DllCall("user32.dll", "hwnd", "GetWindowInfo", "hwnd", $hwnd_calc, "ptr", DllStructGetPtr($tWINDOWINFO))
    if $aRet[0] <> 1 then  Return SetError(2, 0, 0)

    Local $aRes[16][2]
    $aRes[0][0] = "cbSize"
    $aRes[1][0] = "rcWindow_Left"
    $aRes[2][0] = "rcWindow_Top"
    $aRes[3][0] = "rcWindow_Right"
    $aRes[4][0] = "rcWindow_Bottom"
    $aRes[5][0] = "rcClient_Left"
    $aRes[6][0] = "rcClient_Top"
    $aRes[7][0] = "rcClient_Right"
    $aRes[8][0] = "rcClient_Bottom"
    $aRes[9][0] = "dwStyle"
    $aRes[10][0] = "dwExStyle"
    $aRes[11][0] = "dwWindowStatus"
    $aRes[12][0] = "cxWindowBorders"
    $aRes[13][0] = "cyWindowBorders"
    $aRes[14][0] = "atomWindowType"
    $aRes[15][0] = "wCreatorVersion"

    For $i = 1 To 16
        $aRes[$i-1][1] = DllStructGetData($tWINDOWINFO, $i)
    Next

    Return $aRes


    ; ConsoleWrite(DllStructGetData($tWINDOWINFO, 4) - DllStructGetData($tWINDOWINFO, 2) & "x" & DllStructGetData($tWINDOWINFO, 5) - DllStructGetData($tWINDOWINFO, 3) & @CRLF)
    ; ConsoleWrite(DllStructGetData($tWINDOWINFO, 8) - DllStructGetData($tWINDOWINFO, 6) & "x" & DllStructGetData($tWINDOWINFO, 9) - DllStructGetData($tWINDOWINFO, 7) & @CRLF & @CRLF)

EndFunc   ;==>_WinAPI_Ex_GetWindowInfo


; #FUNCTION# =======================================================
; Name...........:  _WinGetPosEx
; Description ...:  Retrieves Window size and position similar to WinGetPos() but regards possible Aero effects on Vista and Win7
; Syntax.........:  _WinGetPosEx($hWnd)
; Parameters ....:  $hWnd - Handle to Window to measure
; Return values .:  Success:    Returns a 4-element array containing the following information:
;                               $array[0] = X position
;                               $array[1] = Y position
;                               $array[2] = Width
;                               $array[3] = Height
;                       Sets @extended  = 0 for Aero effect is OFF for $hWnd
;                                       = 1 for Aero effect is ON for $hWnd
;
;                   Failure:    Returns 0 and sets @error to 1 if windows is not found.
; Author ........: KaFu
; Link ..........; http://msdn.microsoft.com/en-us/library/aa969515%28VS.85%29.aspx
; Example .......; Yes
; ==================================================================
Func _WinGetPosEx($hwnd)
    If Not IsHWnd($hwnd) Then Return SetError(1, 0, 0)
    Local $aPos[4], $tRect = DllStructCreate("int Left;int Top;int Right;int Bottom")
    Local Const $DWMWA_EXTENDED_FRAME_BOUNDS = 9
    DllCall("dwmapi.dll", "hwnd", "DwmGetWindowAttribute", "hwnd", WinGetHandle($hwnd), "dword", $DWMWA_EXTENDED_FRAME_BOUNDS, "ptr", DllStructGetPtr($tRect), "dword", DllStructGetSize($tRect))
    If @error Then Return SetError(0, 0, WinGetPos($hwnd))
    Local $iRectLeft = DllStructGetData($tRect, "Left")
    Local $iRectTop = DllStructGetData($tRect, "Top")
    Local $iRectRight = DllStructGetData($tRect, "Right")
    Local $iRectBottom = DllStructGetData($tRect, "Bottom")
    If Abs($iRectLeft) + Abs($iRectTop) + Abs($iRectRight) + Abs($iRectBottom) > 0 Then
        $aPos[0] = $iRectLeft
        $aPos[1] = $iRectTop
        $aPos[2] = $iRectRight - $iRectLeft
        $aPos[3] = $iRectBottom - $iRectTop
        Return SetError(0, 1, $aPos)
    EndIf
    Return SetError(0, 0, WinGetPos($hwnd))
EndFunc   ;==>_WinGetPosEx


Func _Mouse_Proc($nCode, $wParam, $lParam)
    ;$mouseData = DllStructGetData(DllStructCreate("int X;int Y" & ";dword mouseData", $lParam), 3)
    ;If $wParam = 0x020A Then $mouseEvent = BitShift($mouseData, 16)
    ; ConsoleWrite($nCode & @tab & $wParam & @tab & $lParam & @CRLF)
    if $wParam = 0x00000201 Then
        if TimerDiff($tTimer_Doubleclick) < 500 Then
            ;WinSetState($hwnd_calc,"",@SW_SHOW)
            WinSetState($hwnd_calc,"",@SW_SHOWNORMAL)
            WinSetOnTop($hwnd_calc,"",1)
            WinSetOnTop($hwnd_calc,"",0)
            ; ConsoleWrite("DoubleClick" & @crlf)
        endif
        $tTimer_Doubleclick = TimerInit()
    endif
EndFunc   ;==>_Mouse_Proc

Edit: Added @OSVersion check to change calc.exe window class respectively.

Seem like a good start for my next project :D, build a custom window thumbnail previewer :huggles:.

Edit2: Started :, updated above example to more what I've got in mind... next: add hwnd selector and behavior settings.

Edit3: Added $WH_MOUSE_LL to detect double-click on thumbnail to (re-)set Winstate to @SW_SHOWNORMAL

Edited by KaFu

Share this post


Link to post
Share on other sites

This version seems to work better for me. The window size calculation is now correct (it was still off a little in yours). However running this is just crushing dwm.exe and the target EXE, ie calc.exe. Playing with calc and moving it around it spiking my CPU to 100%.

#include <WindowsConstants.au3>
#include <GUIConstantsEx.au3>
#include <WinAPI.au3>
#include <Misc.au3>
#include <Constants.au3>

if @OSVersion = "WIN_7" Then
    $Class_Calc = "[CLASS:CalcFrame]"
ElseIf @OSVersion = "WIN_VISTA" Then
    $Class_Calc = "[CLASS:SciCalc]"
Else
    MsgBox(16,"Error","Vista or Win7 needed to run example.")
    Exit
endif

Opt("GUIOnEventMode", 1)
Opt("WinWaitDelay", 50)

$tTimer_Doubleclick = 0
$hM_Hook = _WinAPI_SetWindowsHookEx($WH_MOUSE_LL,DllCallbackGetPtr(DllCallbackRegister("_Mouse_Proc", "int", "int;ptr;ptr")),_WinAPI_GetModuleHandle(0))

HotKeySet("{ESC}","_exit")

$iZoomFactor = 1

$iPID = Run("calc.exe")

If WinWait($Class_Calc, "", 5) = 0 Then Exit

$hwnd_calc = WinGetHandle($Class_Calc)
$a_WinGetPosEx = _WinGetPosEx($hwnd_calc)
if @extended <> 1 Then
    MsgBox(16,"Error","AERO not enabled on your system. Example will not work.")
    ProcessClose($iPID)
    Exit
endif

; subtract the frame sizes
$a_WinGetPosEx[2] -= (2*_WinAPI_GetSystemMetrics(33)) ; width of vertical frames
If BitAND(_WinAPI_GetWindowLong($hwnd_calc, $GWL_STYLE), $WS_CAPTION) Then
    ; height of horizontal frames + height of caption
    $a_WinGetPosEx[3] -= ((2*_WinAPI_GetSystemMetrics(32)) + _WinAPI_GetSystemMetrics(4))
Else
    $a_WinGetPosEx[3] -= (2*_WinAPI_GetSystemMetrics(32))
Endif

$hwnd = GUICreate("Vista Thumbnail", ($a_WinGetPosEx[2]) / (1/$iZoomFactor), ($a_WinGetPosEx[3]) / (1/$iZoomFactor), 100, 100, _
                    $WS_POPUP, BitOR($WS_EX_TOPMOST, $WS_EX_CONTROLPARENT))
GUISetBkColor(0xFF0000)
_DWM_Thumbnail($hwnd, $hwnd_calc, 0, 0, $a_WinGetPosEx[2] / (1/$iZoomFactor), $a_WinGetPosEx[3] / (1/$iZoomFactor), 255, True, 1)

$Big = True
AdlibRegister("_check_GUI_Pos")

GUISetState()

While Sleep(250)
    If Not ProcessExists($iPID) Then ExitLoop
WEnd

_exit()

Func _exit()
    ProcessClose($iPID)
    _WinAPI_UnhookWindowsHookEx($hM_Hook)
    Exit
EndFunc

Func _check_GUI_Pos()
    $Win = WinGetPos($hwnd)
    if _WindowFromPoint() <> $hwnd then
        If $Big Then
            For $i = $a_WinGetPosEx[3] To 100 Step -5
                WinMove($hwnd, "", $Win[0], $Win[1], $a_WinGetPosEx[2] * ($i / $a_WinGetPosEx[3]), $i)
                _DWM_Thumbnail($hwnd, $hwnd_calc, 0, 0, $a_WinGetPosEx[2] * ($i / $a_WinGetPosEx[3]), $i, 255, True, 1)
            Next
            WinMove($hwnd, "", $Win[0], $Win[1], $a_WinGetPosEx[2] * (100 / $a_WinGetPosEx[3]), 100)
            _DWM_Thumbnail($hwnd, $hwnd_calc, 0, 0, $a_WinGetPosEx[2] * (100 / $a_WinGetPosEx[3]), 100, 255, True, 1)

            $Big = False
        EndIf
    Else
        If Not $Big Then
            For $i = 100 To $a_WinGetPosEx[3] Step 5
                WinMove($hwnd, "", $Win[0], $Win[1], $a_WinGetPosEx[2] * ($i / $a_WinGetPosEx[3]), $i)
                _DWM_Thumbnail($hwnd, $hwnd_calc, 0, 0, $a_WinGetPosEx[2] * ($i / $a_WinGetPosEx[3]), $i, 255, True, 1)
            Next
            WinMove($hwnd, "", $Win[0], $Win[1], $a_WinGetPosEx[2], $a_WinGetPosEx[3])
            _DWM_Thumbnail($hwnd, $hwnd_calc, 0, 0, $a_WinGetPosEx[2], $a_WinGetPosEx[3], 255, True, 1)
            $Big = True
        EndIf
    EndIf
EndFunc

Func _WindowFromPoint()
    ; from _GUICtrl_SetOnHover
    ; http://www.autoitscript.com/forum/index.ph...showtopic=55120
    ; by G.Sandler a.k.a MrCreatoR (CreatoR's Lab, http://creator-lab.ucoz.ru)
    Local $Old_Opt_MCM = Opt("MouseCoordMode", 1)
    Local $aRet = DllCall("User32.dll", "int", "WindowFromPoint", _
            "long", MouseGetPos(0), _
            "long", MouseGetPos(1))
    ;$aRet = DllCall("user32.dll", "int", "GetDlgCtrlID", "hwnd", $aRet[0])
    Opt("MouseCoordMode", $Old_Opt_MCM)
    Return $aRet[0]
EndFunc   ;==>_WindowFromPoint

Func _DWM_Thumbnail($hwnd, $hWndOw, $rcDest_X, $rcDest_Y, $rcDest_Width, $rcDest_Height, $rcOpacity = 255, $rcReadOnly = True, $rcClientAreaOnly = 0)
    Local Const $DWM_TNP_RECTDESTINATION = 0x00000001
    Local Const $DWM_TNP_RECTSOURCE = 0x00000002
    Local Const $DWM_TNP_OPACITY = 0x00000004
    Local Const $DWM_TNP_VISIBLE = 0x00000008
    Local Const $DWM_TNP_SOURCECLIENTAREAONLY = 0x00000010

    $DWM_THUMBNAIL_PROPERTIES = DllStructCreate("dword dwFlags;int rcDestination[4];int rcSource[4];byte opacity;int fVisible;int fSourceClientAreaOnly")

    DllStructSetData($DWM_THUMBNAIL_PROPERTIES, "dwFlags", BitOR($DWM_TNP_RECTDESTINATION, $DWM_TNP_OPACITY, $DWM_TNP_VISIBLE, $DWM_TNP_SOURCECLIENTAREAONLY))
    DllStructSetData($DWM_THUMBNAIL_PROPERTIES, "rcDestination", $rcDest_X, 1)
    DllStructSetData($DWM_THUMBNAIL_PROPERTIES, "rcDestination", $rcDest_Y, 2)
    DllStructSetData($DWM_THUMBNAIL_PROPERTIES, "rcDestination", $rcDest_Width, 3)
    DllStructSetData($DWM_THUMBNAIL_PROPERTIES, "rcDestination", $rcDest_Height, 4)
    DllStructSetData($DWM_THUMBNAIL_PROPERTIES, "opacity", $rcOpacity)
    DllStructSetData($DWM_THUMBNAIL_PROPERTIES, "fVisible", $rcReadOnly)
    DllStructSetData($DWM_THUMBNAIL_PROPERTIES, "fSourceClientAreaOnly", $rcClientAreaOnly)

    $call = DllCall("dwmapi.dll", "int", "DwmRegisterThumbnail", "hwnd", $hwnd, "hwnd", $hWndOw, "ptr*", 0)
    If Not IsArray($call) Then
        SetError(1) ; Register thumbnail failed
        Return 0
    Else
        $thumbid = $call[3]
    EndIf

    $call = DllCall("dwmapi.dll", "int", "DwmUpdateThumbnailProperties", "ptr", $thumbid, "ptr", DllStructGetPtr($DWM_THUMBNAIL_PROPERTIES))
EndFunc   ;==>_DWM_Thumbnail

; #FUNCTION# =======================================================
; Name...........:  _WinGetPosEx
; Description ...:  Retrieves Window size and position similar to WinGetPos() but regards possible Aero effects on Vista and Win7
; Syntax.........:  _WinGetPosEx($hWnd)
; Parameters ....:  $hWnd - Handle to Window to measure
; Return values .:  Success:    Returns a 4-element array containing the following information:
;                               $array[0] = X position
;                               $array[1] = Y position
;                               $array[2] = Width
;                               $array[3] = Height
;                       Sets @extended  = 0 for Aero effect is OFF for $hWnd
;                                       = 1 for Aero effect is ON for $hWnd
;
;                   Failure:    Returns 0 and sets @error to 1 if windows is not found.
; Author ........: KaFu
; Link ..........; http://msdn.microsoft.com/en-us/library/aa969515%28VS.85%29.aspx
; Example .......; Yes
; ==================================================================
Func _WinGetPosEx($hwnd)
    If Not IsHWnd($hwnd) Then Return SetError(1, 0, 0)
    Local $aPos[4], $tRect = DllStructCreate("int Left;int Top;int Right;int Bottom")
    Local Const $DWMWA_EXTENDED_FRAME_BOUNDS = 9
    DllCall("dwmapi.dll", "hwnd", "DwmGetWindowAttribute", "hwnd", WinGetHandle($hwnd), "dword", $DWMWA_EXTENDED_FRAME_BOUNDS, "ptr", DllStructGetPtr($tRect), "dword", DllStructGetSize($tRect))
    If @error Then Return SetError(0, 0, WinGetPos($hwnd))
    Local $iRectLeft = DllStructGetData($tRect, "Left")
    Local $iRectTop = DllStructGetData($tRect, "Top")
    Local $iRectRight = DllStructGetData($tRect, "Right")
    Local $iRectBottom = DllStructGetData($tRect, "Bottom")
    If Abs($iRectLeft) + Abs($iRectTop) + Abs($iRectRight) + Abs($iRectBottom) > 0 Then
        $aPos[0] = $iRectLeft
        $aPos[1] = $iRectTop
        $aPos[2] = $iRectRight - $iRectLeft
        $aPos[3] = $iRectBottom - $iRectTop
        Return SetError(0, 1, $aPos)
    EndIf
    Return SetError(0, 0, WinGetPos($hwnd))
EndFunc   ;==>_WinGetPosEx


Func _Mouse_Proc($nCode, $wParam, $lParam)
    ;$mouseData = DllStructGetData(DllStructCreate("int X;int Y" & ";dword mouseData", $lParam), 3)
    ;If $wParam = 0x020A Then $mouseEvent = BitShift($mouseData, 16)
    ; ConsoleWrite($nCode & @tab & $wParam & @tab & $lParam & @CRLF)
    If $wParam = 0x00000201 Then
        If TimerDiff($tTimer_Doubleclick) < 500 Then
            ;WinSetState($hwnd_calc,"",@SW_SHOW)
            WinSetState($hwnd_calc,"",@SW_SHOWNORMAL)
            WinSetOnTop($hwnd_calc,"",1)
            WinSetOnTop($hwnd_calc,"",0)
            ; ConsoleWrite("DoubleClick" & @crlf)
        endif
        $tTimer_Doubleclick = TimerInit()
    endif
EndFunc   ;==>_Mouse_Proc

Share this post


Link to post
Share on other sites

#17 ·  Posted (edited)

The window size calculation is now correct (it was still off a little in yours).

Are you sure? On my system my figures look much better then yours, yours are off on my computer : .

Playing with calc and moving it around it spiking my CPU to 100%.

Guess the update in the client window has to be disabled if you move the source window... for sure there's a call for that :D, will take a look.

http://msdn.microsoft.com/en-us/library/aa969521%28VS.85%29.aspx

"The thumbnail registration handle obtained by this function is not globally unique but is unique to the process. DwmUnregisterThumbnail is used to unregister the thumbnail and must be done within the process the relationship was registered in."

That parts missing, I guess after some updates there are lots of orphaned "thumbnail registration handles" floating around :huggles:...

And instead of calling DwmRegisterThumbnail again we better make use of DwmUpdateThumbnailProperties:D...

Edited by KaFu

Share this post


Link to post
Share on other sites

Yeah that's weird with the window calculations. My version looks perfect on my laptop, and the popup thumbnail fits perfectly over the calc window (you wouldn't even notice the difference). What OS are you trying it on? I'm on Win7 Pro 32-bit. What version of AutoIt? I'm using 3.3.5.1 beta at the moment.

Share this post


Link to post
Share on other sites

#19 ·  Posted (edited)

I'm running Win7 64bit. Tested it with 3.3.2.0 (ups=>update), 3.3.4.0 and 3.3.5.1b, everything looks fine with my calc :D. Updated the script to use _DWM_Thumbnail_Register(), _DWM_Thumbnail_Update_Properties() and _DWM_Thumbnail_Unregister().

#include <WindowsConstants.au3>
#include <GUIConstantsEx.au3>
#include <WinAPI.au3>
#include <Misc.au3>
#include <Constants.au3>
#include <array.au3>

Global $hwnd_Thumbnail, $hThumbID, $iPID

Global $i_hwnd_Thumbnail_Width, $i_hwnd_Thumbnail_Width_Save
Global $i_hwnd_Thumbnail_Height, $i_hwnd_Thumbnail_Height_Save

Global $GetSystemMetrics_4 = _WinAPI_GetSystemMetrics(4)

Global Const $DWM_TNP_RECTDESTINATION = 0x00000001
Global Const $DWM_TNP_RECTSOURCE = 0x00000002
Global Const $DWM_TNP_OPACITY = 0x00000004
Global Const $DWM_TNP_VISIBLE = 0x00000008
Global Const $DWM_TNP_SOURCECLIENTAREAONLY = 0x00000010

If @OSVersion = "WIN_7" Then
    $Class_Calc = "[CLASS:CalcFrame]"
ElseIf @OSVersion = "WIN_VISTA" Then
    $Class_Calc = "[CLASS:SciCalc]"
Else
    MsgBox(16, "Error", "Vista or Win7 needed to run example.")
    Exit
EndIf

Opt("GUIOnEventMode", 1)
Opt("WinWaitDelay", 0)

$tTimer_Doubleclick = 0
$hM_Hook = _WinAPI_SetWindowsHookEx($WH_MOUSE_LL, DllCallbackGetPtr(DllCallbackRegister("_Mouse_Proc", "int", "int;ptr;ptr")), _WinAPI_GetModuleHandle(0))

HotKeySet("{ESC}", "_exit")

;$Class_Calc = "[CLASS:MozillaUIWindowClass]"
;$Class_Calc = "[CLASS:SciTEWindow]"

$iPID = Run("calc.exe")
If WinWait($Class_Calc, "", 3) = 0 Then
    MsgBox(16, "Error", "Window not found.")
    _exit()
EndIf

$hwnd_Source = WinGetHandle($Class_Calc)
If $iPID = 0 Then $iPID = WinGetProcess($hwnd_Source)

Global $iZoomFactor_Large = 1 ; to set "large" thumbnail size to width = source width
;$iZoomFactor_Large = 300 / $i_hwnd_Thumbnail_Width ; to set "large" thumbnail size to width = 300
Global $iZoomFactor_Small = 100 ; to set "small" thumbnail size to width = 100

$a_WinGetPosEx_Source = _WinGetPosEx($hwnd_Source)
$i_hwnd_Thumbnail_Width = $a_WinGetPosEx_Source[2]
$i_hwnd_Thumbnail_Height = $a_WinGetPosEx_Source[3]
If @extended <> 1 Then
    MsgBox(16, "Error", "AERO not enabled on your system. Example will not work.")
    ProcessClose($iPID)
    Exit
EndIf

$a_GetWindowInfo = _WinAPI_Ex_GetWindowInfo($hwnd_Source)
If UBound($a_GetWindowInfo) <> 16 Then
    MsgBox(16, "Error", "_WinAPI_Ex_GetWindowInfo() did not return result.")
    ProcessClose($iPID)
    Exit
EndIf

$i_hwnd_Thumbnail_Width = $i_hwnd_Thumbnail_Width - (2 * $a_GetWindowInfo[13][1])
If BitAND($a_GetWindowInfo[9][1], $WS_CAPTION) Then
    $i_hwnd_Thumbnail_Height = $i_hwnd_Thumbnail_Height - (2 * $a_GetWindowInfo[13][1]) - $GetSystemMetrics_4
Else
    $i_hwnd_Thumbnail_Height = $i_hwnd_Thumbnail_Height - (2 * $a_GetWindowInfo[13][1])
EndIf

$hwnd_Thumbnail = GUICreate("Vista Thumbnail", 100, 100, 100, 100, $WS_POPUP, BitOR($WS_EX_TOOLWINDOW, $WS_EX_TOPMOST))
GUISetOnEvent($GUI_EVENT_PRIMARYDOWN, "_WindowDrag")
$hThumbID = _DWM_Thumbnail_Register($hwnd_Thumbnail, $hwnd_Source)
If @error Then
    MsgBox(16, "Error", "Registration of Thumbnail failed.")
    _exit()
EndIf
_DWM_Thumbnail_Update_Properties($hThumbID, 0, 0, $i_hwnd_Thumbnail_Width * ($iZoomFactor_Small / $i_hwnd_Thumbnail_Height), $iZoomFactor_Small, 255, True, 1)

$Big = True

AdlibRegister("_check_GUI_Pos")

GUISetState()

While Sleep(250)
    If Not ProcessExists($iPID) Then ExitLoop
WEnd

_exit()

Func _exit()
    If IsHWnd($hwnd_Thumbnail) Then WinSetState($hwnd_Thumbnail, "", @SW_HIDE)
    _DWM_Thumbnail_Unregister($hThumbID)
    ProcessClose($iPID)
    _WinAPI_UnhookWindowsHookEx($hM_Hook)
    Exit
EndFunc   ;==>_exit

Func _check_GUI_Pos()

    If Not IsHWnd($hwnd_Thumbnail) Or Not IsHWnd($hwnd_Source) Then Return

    $aWinGetPos = WinGetPos($hwnd_Thumbnail)
    $i_hwnd_Source_State = WinGetState($hwnd_Source, "")
    If BitAND($i_hwnd_Source_State, 2) And Not BitAND($i_hwnd_Source_State, 16) Then ; Update only if source is visible and not minimized
        $a_GetWindowInfo = _WinAPI_Ex_GetWindowInfo($hwnd_Source)
        $a_WinGetPosEx_Source = _WinGetPosEx($hwnd_Source)
        $i_hwnd_Thumbnail_Width = $a_WinGetPosEx_Source[2]
        $i_hwnd_Thumbnail_Height = $a_WinGetPosEx_Source[3]
        $i_hwnd_Thumbnail_Width = $i_hwnd_Thumbnail_Width - (2 * $a_GetWindowInfo[13][1])
        If BitAND($a_GetWindowInfo[9][1], $WS_CAPTION) Then
            $i_hwnd_Thumbnail_Height = $i_hwnd_Thumbnail_Height - (2 * $a_GetWindowInfo[13][1]) - $GetSystemMetrics_4
        Else
            $i_hwnd_Thumbnail_Height = $i_hwnd_Thumbnail_Height - (2 * $a_GetWindowInfo[13][1])
        EndIf
        $i_hwnd_Thumbnail_Width = $i_hwnd_Thumbnail_Width * $iZoomFactor_Large
        $i_hwnd_Thumbnail_Height = $i_hwnd_Thumbnail_Height * $iZoomFactor_Large
    EndIf

    If _WindowFromPoint() <> $hwnd_Thumbnail Then
        If $Big Then
            $iStep = $i_hwnd_Thumbnail_Height / 10
            For $i = $i_hwnd_Thumbnail_Height To $iZoomFactor_Small Step -$iStep
                _DWM_Thumbnail_Update_Properties($hThumbID, 0, 0, $i_hwnd_Thumbnail_Width * ($i / $i_hwnd_Thumbnail_Height), $i, 255, True, 1)
                WinMove($hwnd_Thumbnail, "", $aWinGetPos[0], $aWinGetPos[1], $i_hwnd_Thumbnail_Width * ($i / $i_hwnd_Thumbnail_Height), $i)
            Next
            _DWM_Thumbnail_Update_Properties($hThumbID, 0, 0, $i_hwnd_Thumbnail_Width * ($iZoomFactor_Small / $i_hwnd_Thumbnail_Height), $iZoomFactor_Small, 255, True, 1)
            WinMove($hwnd_Thumbnail, "", $aWinGetPos[0], $aWinGetPos[1], $i_hwnd_Thumbnail_Width * ($iZoomFactor_Small / $i_hwnd_Thumbnail_Height), $iZoomFactor_Small)
            $i_hwnd_Thumbnail_Height_Save = $i_hwnd_Thumbnail_Height
            $i_hwnd_Thumbnail_Width_Save = $i_hwnd_Thumbnail_Width
            $Big = False
        ElseIf $i_hwnd_Thumbnail_Height <> $i_hwnd_Thumbnail_Height_Save Or $i_hwnd_Thumbnail_Width <> $i_hwnd_Thumbnail_Width_Save Then ;source size changed
            _DWM_Thumbnail_Update_Properties($hThumbID, 0, 0, $i_hwnd_Thumbnail_Width * ($iZoomFactor_Small / $i_hwnd_Thumbnail_Height), $iZoomFactor_Small, 255, True, 1)
            WinMove($hwnd_Thumbnail, "", $aWinGetPos[0], $aWinGetPos[1], $i_hwnd_Thumbnail_Width * ($iZoomFactor_Small / $i_hwnd_Thumbnail_Height), $iZoomFactor_Small)
            $i_hwnd_Thumbnail_Height_Save = $i_hwnd_Thumbnail_Height
            $i_hwnd_Thumbnail_Width_Save = $i_hwnd_Thumbnail_Width
        EndIf
    Else
        If Not $Big Then
            $iStep = $i_hwnd_Thumbnail_Height / 10
            For $i = $iZoomFactor_Small To $i_hwnd_Thumbnail_Height Step $iStep
                _DWM_Thumbnail_Update_Properties($hThumbID, 0, 0, $i_hwnd_Thumbnail_Width * ($i / $i_hwnd_Thumbnail_Height), $i, 255, True, 1)
                WinMove($hwnd_Thumbnail, "", $aWinGetPos[0], $aWinGetPos[1], $i_hwnd_Thumbnail_Width * ($i / $i_hwnd_Thumbnail_Height), $i)
            Next
            _DWM_Thumbnail_Update_Properties($hThumbID, 0, 0, $i_hwnd_Thumbnail_Width, $i_hwnd_Thumbnail_Height, 255, True, 1)
            WinMove($hwnd_Thumbnail, "", $aWinGetPos[0], $aWinGetPos[1], $i_hwnd_Thumbnail_Width, $i_hwnd_Thumbnail_Height)
            $i_hwnd_Thumbnail_Height_Save = $i_hwnd_Thumbnail_Height
            $i_hwnd_Thumbnail_Width_Save = $i_hwnd_Thumbnail_Width
            $Big = True
        ElseIf $i_hwnd_Thumbnail_Height <> $i_hwnd_Thumbnail_Height_Save Or $i_hwnd_Thumbnail_Width <> $i_hwnd_Thumbnail_Width_Save Then ;source size changed
            _DWM_Thumbnail_Update_Properties($hThumbID, 0, 0, $i_hwnd_Thumbnail_Width, $i_hwnd_Thumbnail_Height, 255, True, 1)
            WinMove($hwnd_Thumbnail, "", $aWinGetPos[0], $aWinGetPos[1], $i_hwnd_Thumbnail_Width, $i_hwnd_Thumbnail_Height)
            $i_hwnd_Thumbnail_Height_Save = $i_hwnd_Thumbnail_Height
            $i_hwnd_Thumbnail_Width_Save = $i_hwnd_Thumbnail_Width
        EndIf
    EndIf
EndFunc   ;==>_check_GUI_Pos

Func _WindowFromPoint()
    ; from _GUICtrl_SetOnHover
    ; http://www.autoitscript.com/forum/index.ph...showtopic=55120
    ; by G.Sandler a.k.a MrCreatoR (CreatoR's Lab, http://creator-lab.ucoz.ru)
    Local $Old_Opt_MCM = Opt("MouseCoordMode", 1)
    Local $aRet = DllCall("User32.dll", "int", "WindowFromPoint", _
            "long", MouseGetPos(0), _
            "long", MouseGetPos(1))
    ;$aRet = DllCall("user32.dll", "int", "GetDlgCtrlID", "hwnd", $aRet[0])
    Opt("MouseCoordMode", $Old_Opt_MCM)
    Return $aRet[0]
EndFunc   ;==>_WindowFromPoint


Func _WindowDrag()
    DllCall("user32.dll", "int", "SendMessage", "hWnd", $hwnd_Thumbnail, "int", $WM_NCLBUTTONDOWN, "int", $HTCAPTION, "int", 0)
EndFunc   ;==>_WindowDrag

Func _DWM_Thumbnail_Register($hwnd, $hWndOw)
    $aRet = DllCall("dwmapi.dll", "int", "DwmRegisterThumbnail", "hwnd", $hwnd, "hwnd", $hWndOw, "ptr*", 0)
    If Not IsArray($aRet) Then Return SetError(1, 0, 0); Register thumbnail failed
    Return $aRet[3]
EndFunc   ;==>_DWM_Thumbnail_Register

Func _DWM_Thumbnail_Unregister($hThumbID)
    $aRet = DllCall("dwmapi.dll", "int", "DwmUnregisterThumbnail", "hwnd", $hThumbID)
    If Not IsArray($aRet) Then Return SetError(1, 0, 0); Unregister thumbnail failed
    Return $aRet[0]
EndFunc   ;==>_DWM_Thumbnail_Unregister

Func _DWM_Thumbnail_Update_Properties($hThumbID, $rcDest_X, $rcDest_Y, $rcDest_Width, $rcDest_Height, $rcOpacity = 255, $rcReadOnly = True, $rcClientAreaOnly = 0)
    $DWM_THUMBNAIL_PROPERTIES = DllStructCreate("dword dwFlags;int rcDestination[4];int rcSource[4];byte opacity;int fVisible;int fSourceClientAreaOnly")
    DllStructSetData($DWM_THUMBNAIL_PROPERTIES, "dwFlags", BitOR($DWM_TNP_RECTDESTINATION, $DWM_TNP_OPACITY, $DWM_TNP_VISIBLE, $DWM_TNP_SOURCECLIENTAREAONLY))
    DllStructSetData($DWM_THUMBNAIL_PROPERTIES, "rcDestination", $rcDest_X, 1)
    DllStructSetData($DWM_THUMBNAIL_PROPERTIES, "rcDestination", $rcDest_Y, 2)
    DllStructSetData($DWM_THUMBNAIL_PROPERTIES, "rcDestination", $rcDest_Width, 3)
    DllStructSetData($DWM_THUMBNAIL_PROPERTIES, "rcDestination", $rcDest_Height, 4)
    DllStructSetData($DWM_THUMBNAIL_PROPERTIES, "opacity", $rcOpacity)
    DllStructSetData($DWM_THUMBNAIL_PROPERTIES, "fVisible", $rcReadOnly)
    DllStructSetData($DWM_THUMBNAIL_PROPERTIES, "fSourceClientAreaOnly", $rcClientAreaOnly)
    $aRet = DllCall("dwmapi.dll", "int", "DwmUpdateThumbnailProperties", "ptr", $hThumbID, "ptr", DllStructGetPtr($DWM_THUMBNAIL_PROPERTIES))
    If Not IsArray($aRet) Then Return SetError(1, 0, 0); Update thumbnail failed
EndFunc   ;==>_DWM_Thumbnail_Update_Properties

Func _WinAPI_Ex_GetWindowInfo($hwnd)
    If Not IsHWnd($hwnd) Then Return SetError(1, 0, 0)

    ; http://msdn.microsoft.com/en-us/library/ms632610(VS.85).aspx
    $tWINDOWINFO = DllStructCreate("dword cbSize;int rcWindow_Left;int rcWindow_Top;int rcWindow_Right;int rcWindow_Bottom;int rcClient_Left;int rcClient_Top;int rcClient_Right;int rcClient_Bottom;dword dwStyle;dword dwExStyle;dword dwWindowStatus;uint cxWindowBorders;uint cyWindowBorders;byte atomWindowType;byte wCreatorVersion;")
    DllStructSetData($tWINDOWINFO, 1, DllStructGetSize($tWINDOWINFO))

    ; http://msdn.microsoft.com/en-us/library/ms633516(VS.85).aspx
    $aRet = DllCall("user32.dll", "hwnd", "GetWindowInfo", "hwnd", HWnd($hwnd), "ptr", DllStructGetPtr($tWINDOWINFO))
    If $aRet[0] <> 1 Then Return SetError(2, 0, 0)

    Local $aRes[16][2]
    $aRes[0][0] = "cbSize"
    $aRes[1][0] = "rcWindow_Left"
    $aRes[2][0] = "rcWindow_Top"
    $aRes[3][0] = "rcWindow_Right"
    $aRes[4][0] = "rcWindow_Bottom"
    $aRes[5][0] = "rcClient_Left"
    $aRes[6][0] = "rcClient_Top"
    $aRes[7][0] = "rcClient_Right"
    $aRes[8][0] = "rcClient_Bottom"
    $aRes[9][0] = "dwStyle"
    $aRes[10][0] = "dwExStyle"
    $aRes[11][0] = "dwWindowStatus"
    $aRes[12][0] = "cxWindowBorders"
    $aRes[13][0] = "cyWindowBorders"
    $aRes[14][0] = "atomWindowType"
    $aRes[15][0] = "wCreatorVersion"

    For $i = 1 To 16
        $aRes[$i - 1][1] = DllStructGetData($tWINDOWINFO, $i)
    Next

    Return $aRes

EndFunc   ;==>_WinAPI_Ex_GetWindowInfo


Func _Mouse_Proc($nCode, $wParam, $lParam)
    ;$mouseData = DllStructGetData(DllStructCreate("int X;int Y" & ";dword mouseData", $lParam), 3)
    ;If $wParam = 0x020A Then $mouseEvent = BitShift($mouseData, 16)
    ; ConsoleWrite($nCode & @tab & $wParam & @tab & $lParam & @CRLF)
    If $wParam = 0x00000201 Then
        If TimerDiff($tTimer_Doubleclick) < 500 Then
            WinSetState($hwnd_Source, "", @SW_RESTORE)
            WinSetOnTop($hwnd_Source, "", 1)
            WinSetOnTop($hwnd_Source, "", 0)
        EndIf
        If _WindowFromPoint() = $hwnd_Thumbnail Then $tTimer_Doubleclick = TimerInit()
    EndIf
EndFunc   ;==>_Mouse_Proc


; #FUNCTION# =======================================================
; Name...........:  _WinGetPosEx
; Description ...:  Retrieves Window size and position similar to WinGetPos() but regards possible Aero effects on Vista and Win7
; Syntax.........:  _WinGetPosEx($hWnd)
; Parameters ....:  $hWnd - Handle to Window to measure
; Return values .:  Success:    Returns a 4-element array containing the following information:
;                               $array[0] = X position
;                               $array[1] = Y position
;                               $array[2] = Width
;                               $array[3] = Height
;                       Sets @extended  = 0 for Aero effect is OFF for $hWnd
;                                       = 1 for Aero effect is ON for $hWnd
;
;                   Failure:    Returns 0 and sets @error to 1 if windows is not found.
; Author ........: KaFu
; Link ..........; http://msdn.microsoft.com/en-us/library/aa969515%28VS.85%29.aspx
; Example .......; Yes
; ==================================================================
Func _WinGetPosEx($hwnd)
    If Not IsHWnd($hwnd) Then Return SetError(1, 0, 0)
    Local $aPos[4], $tRect = DllStructCreate("int Left;int Top;int Right;int Bottom")
    Local Const $DWMWA_EXTENDED_FRAME_BOUNDS = 9
    DllCall("dwmapi.dll", "hwnd", "DwmGetWindowAttribute", "hwnd", WinGetHandle($hwnd), "dword", $DWMWA_EXTENDED_FRAME_BOUNDS, "ptr", DllStructGetPtr($tRect), "dword", DllStructGetSize($tRect))
    If @error Then Return SetError(0, 0, WinGetPos($hwnd))
    Local $iRectLeft = DllStructGetData($tRect, "Left")
    Local $iRectTop = DllStructGetData($tRect, "Top")
    Local $iRectRight = DllStructGetData($tRect, "Right")
    Local $iRectBottom = DllStructGetData($tRect, "Bottom")
    If Abs($iRectLeft) + Abs($iRectTop) + Abs($iRectRight) + Abs($iRectBottom) > 0 Then
        $aPos[0] = $iRectLeft
        $aPos[1] = $iRectTop
        $aPos[2] = $iRectRight - $iRectLeft
        $aPos[3] = $iRectBottom - $iRectTop
        Return SetError(0, 1, $aPos)
    EndIf
    Return SetError(0, 0, WinGetPos($hwnd))
EndFunc   ;==>_WinGetPosEx

Edit: Hmmm, it looks good with calc.exe, but if I hook into FireFox or SciTE the size is still wrong, needs more tweaking :huggles:. Updated above example to resize thumbnail if source window is resized.

Edit2: Tweak positioning a little more :, now only updates source size if window visible and not minimized... somehow there's a little hook during first creation...

Edited by KaFu

Share this post


Link to post
Share on other sites

#20 ·  Posted (edited)

@KaFu

Can you run this real quick and post your output?

#NoTrayIcon
#include <WinAPI.au3>

ConsoleWrite("caption: " & _WinAPI_GetSystemMetrics(4) & @CRLF)
ConsoleWrite("xframe: " & _WinAPI_GetSystemMetrics(32) & @CRLF)
ConsoleWrite("yframe: " & _WinAPI_GetSystemMetrics(33) & @CRLF)
ConsoleWrite("xborder: " & _WinAPI_GetSystemMetrics(5) & @CRLF)
ConsoleWrite("yborder: " & _WinAPI_GetSystemMetrics(6) & @CRLF)
ConsoleWrite("xfixedframe: " & _WinAPI_GetSystemMetrics(7) & @CRLF)
ConsoleWrite("yfixedframe: " & _WinAPI_GetSystemMetrics(8) & @CRLF)
ConsoleWrite("-----" & @CRLF)

Run("calc.exe")
WinWait("[CLASS:CalcFrame]")
$a = _WinAPI_Ex_GetWindowInfo(WinGetHandle("[CLASS:CalcFrame]"))
ConsoleWrite("xwindowborders: " & $a[12][1] & @CRLF)
ConsoleWrite("ywindowborders: " & $a[13][1] & @CRLF)

Func _WinAPI_Ex_GetWindowInfo($hwnd)
    If Not IsHWnd($hwnd) Then Return SetError(1, 0, 0)

    ; http://msdn.microsoft.com/en-us/library/ms632610(VS.85).aspx
    $tWINDOWINFO = DllStructCreate("dword cbSize;int rcWindow_Left;int rcWindow_Top;int rcWindow_Right;int rcWindow_Bottom;int rcClient_Left;int rcClient_Top;int rcClient_Right;int rcClient_Bottom;dword dwStyle;dword dwExStyle;dword dwWindowStatus;uint cxWindowBorders;uint cyWindowBorders;byte atomWindowType;byte wCreatorVersion;")
    DllStructSetData($tWINDOWINFO, 1, DllStructGetSize($tWINDOWINFO))

    ; http://msdn.microsoft.com/en-us/library/ms633516(VS.85).aspx
    $aRet = DllCall("user32.dll", "hwnd", "GetWindowInfo", "hwnd", HWnd($hwnd), "ptr", DllStructGetPtr($tWINDOWINFO))
    If $aRet[0] <> 1 Then Return SetError(2, 0, 0)

    Local $aRes[16][2]
    $aRes[0][0] = "cbSize"
    $aRes[1][0] = "rcWindow_Left"
    $aRes[2][0] = "rcWindow_Top"
    $aRes[3][0] = "rcWindow_Right"
    $aRes[4][0] = "rcWindow_Bottom"
    $aRes[5][0] = "rcClient_Left"
    $aRes[6][0] = "rcClient_Top"
    $aRes[7][0] = "rcClient_Right"
    $aRes[8][0] = "rcClient_Bottom"
    $aRes[9][0] = "dwStyle"
    $aRes[10][0] = "dwExStyle"
    $aRes[11][0] = "dwWindowStatus"
    $aRes[12][0] = "cxWindowBorders"
    $aRes[13][0] = "cyWindowBorders"
    $aRes[14][0] = "atomWindowType"
    $aRes[15][0] = "wCreatorVersion"

    For $i = 1 To 16
        $aRes[$i - 1][1] = DllStructGetData($tWINDOWINFO, $i)
    Next

    Return $aRes

EndFunc   ;==>_WinAPI_Ex_GetWindowInfo

Mine:

caption: 22

xframe: 8

yframe: 8

xborder: 1

yborder: 1

xfixedframe: 3

yfixedframe: 3

-----

xwindowborders: 3

ywindowborders: 3

Edited by wraithdu

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0