Jump to content

Vista Thumbs


 Share

Recommended Posts

So I'm trying to use this awesome example in one of my applications. I want to mimic Vista's ALT+TAB screen.

However, with the code below I have two problems:

- It display only one thumb, the other one gets 'overwritten'.

- It crashes my pc

What am I doing wrong?

Thanks

Code removed, see below for new version.

Edited by SaphuA
Link to comment
Share on other sites

I tried to fix this but this stuff really is harmfull!

However I don't think that you can register more than one thumbnail to a single hwnd, I think you have to create childs and include them into the main GUI.. however I didn't get this to work either (no crashing though).

I also think that one should unregister the thumbnail (something I didn't do in my example :P )

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

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

Link to comment
Share on other sites

Ah that's a smart idea :P

I've tried it aswell, without succes though (although no more crashes!)

Edit: Using $WS_EX_MDICHILD works a lot better, although I can still display only 1 thumbnail:

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

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]")
WinSetState("[CLASS:SciCalc]", "", @SW_MINIMIZE)
Run("notepad.exe")
WinWait("[CLASS:Notepad]")
WinSetState("[CLASS:Notepad]", "", @SW_MINIMIZE)

$winA = WinGetHandle("[CLASS:SciCalc]")
$winB = WinGetHandle("[CLASS:Notepad]")

$main = GUICreate("Thumbs", 600, 160, 245, 195, BitOR($WS_THICKFRAME,$WS_POPUP))
GUISetState()

$cont1 = GUICreate("Cont1", 150, 150, 10, -10, $WS_POPUP, $WS_EX_MDICHILD, $main)
GUISetBkColor(0xFF0000)
GUISetState()

$cont2 = GUICreate("Cont2", 150, 150, 165, -10, $WS_POPUP, $WS_EX_MDICHILD, $main)
GUISetBkColor(0x00FF00)
GUISetState()

CreateThumb($winA, $cont1)
;CreateThumb($winB, $cont2)

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

WinClose($winA)
WinClose($winB)

func CreateThumb($sourceWh, $destWh)
    $size = WinGetClientSize($destWh)
    $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], 3)
    DllStructSetData($DWM_THUMBNAIL_PROPERTIES, "rcDestination", $size[1], 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", $destWh, "hwnd", $sourceWh, "ptr*", 0)
    $thumbid = $call[3]
    $call = DllCall("dwmapi.dll", "int", "DwmUpdateThumbnailProperties", "ptr", $thumbid, "ptr", DllStructGetPtr($DWM_THUMBNAIL_PROPERTIES))
endfunc
Edited by SaphuA
Link to comment
Share on other sites

Sorry for all the spamming :P

I've been thinking. Could it be that only one thread is allowed one thumb at a time? If this is so, does AutoIt support multi threading?

In case the above will never work I will have to go something along these lines. Switch with left mouse button and close with right mouse button.

Ps. Is the DeleteThumb function right?

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

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]")
WinSetState("[CLASS:SciCalc]", "", @SW_MINIMIZE)
Run("notepad.exe")
WinWait("[CLASS:Notepad]")
WinSetState("[CLASS:Notepad]", "", @SW_MINIMIZE)
Run("mspaint.exe")
WinWait("[CLASS:MSPaintApp]")
WinSetState("[CLASS:MSPaintApp]", "", @SW_MINIMIZE)

$winA = WinGetHandle("[CLASS:SciCalc]")
$winB = WinGetHandle("[CLASS:Notepad]")
$winC = WinGetHandle("[CLASS:MSPaintApp]")

dim $thumb
dim $current = 0
dim $main = GUICreate("", 160, 160, 500, 195, 0, $WS_EX_TOOLWINDOW)
GUISetState()

SetTarget($winA)

while true
    $msg = GUIGetMsg()
    if $msg == $GUI_EVENT_SECONDARYUP then
        ExitLoop
    elseif $msg == $GUI_EVENT_PRIMARYDOWN then
        DeleteThumb($thumb)
        if $current == 0 then
            $current = 1
            SetTarget($winB)
        elseif $current == 1 then
            $current = 2
            SetTarget($winC)
        elseif $current == 2 then
            $current = 0
            SetTarget($winA)
        endif
    endif
wend

DeleteThumb($thumb)

WinClose($winA)
WinClose($winB)
WinClose($winC)

func SetTarget($wh)
    $thumb = CreateThumb($wh, $main)
    WinSetTitle($main, "", WinGetTitle($wh))
endfunc

func CreateThumb($sourceWh, $destWh)
    $size = WinGetClientSize($destWh)
    $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], 3)
    DllStructSetData($DWM_THUMBNAIL_PROPERTIES, "rcDestination", $size[1], 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", $destWh, "hwnd", $sourceWh, "ptr*", 0)
    $thumbid = $call[3]
    $call = DllCall("dwmapi.dll", "int", "DwmUpdateThumbnailProperties", "ptr", $thumbid, "ptr", DllStructGetPtr($DWM_THUMBNAIL_PROPERTIES))
    return $thumbid
endfunc

func DeleteThumb($thumbid)
    DllCall("dwmapi.dll", "int", "DwmUnregisterThumbnail", "ptr", $thumbid)
endfunc
Edited by SaphuA
Link to comment
Share on other sites

Sorry for all the spamming :P

I've been thinking. Could it be that only one thread is allowed one thumb at a time? If this is so, does AutoIt support multi threading?

In case the above will never work I will have to go something along these lines. Switch with left mouse button and close with right mouse button.

Ps. Is the DeleteThumb function right?

Nah, I don't think so, if it were so it would be the most unfriendly api...ever!

I think we're missing something really simple here, just can't see it!

Edit: No autoit doesn't support multi threading, and no it's not on the todo list :P

Edited by monoceres

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

Link to comment
Share on other sites

SaphuA,

Perhaps you can put this one in the freezer for a little while :P and start first with creating it with the tumbnails and some little text-box with the information on top... and if that is working correctly THAN you can try to apply this..

But no change in multi-threading indeed, there are/were some really topics about it allready :P

Greetz,

Neo

[center][font="Arial"]--- The Neo and Only --- [/font][font="Arial"]--Projects---[/font]Image to Text converterText to ASCII converter[/center]

Link to comment
Share on other sites

After playing around with the code some. I've found that the problem is with DwmRegisterThumbnail. It always returns the same address for phThumbnailId on my system (0x00000001) for any registered instance. So it works fine if you only have one instance, but when you try to register another instance it returns the same pointer. The crashing seems to happen when it unregisters the first reference (successfully) and then proceeds to try and unregister the second reference using the same address.

Link to comment
Share on other sites

I'm leaning more towards the application needing to be multi-thread capable. As the documentation states, a thumbnail isn't just a static snapshot its a dynamic stream of the current state of the window. It seems highly unlikely that the API would be written for for a single-threaded application.

I've done some more testing, and there isn't a problem if you only have one thumbnail loaded. You can change the thumbnail as you want by unregistering and registering. So everything i've seen seems to suggest multi-threading is a must.

Here's a script for enumerating the current open windows.

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

Global Const $DWM_TNP_RECTDESTINATION = 0x00000001, _
        $DWM_TNP_RECTSOURCE = 0x00000002, _
        $DWM_TNP_OPACITY = 0x00000004, _
        $DWM_TNP_VISIBLE = 0x00000008, _
        $DWM_TNP_SOURCECLIENTAREAONLY = 0x00000010
Global Const $S_OK = 0x00000000, _
        $E_INVALIDARG = 0X80070057
Global Const $tag_DTP = "dword dwFlags;int rcDestination[4];int rcSource[4];byte opacity;int fVisible;int fSourceClientAreaOnly"

$main = GUICreate("Thumbnail", 250, 250, -1, -1)
$lbWindow = GUICtrlCreateLabel("", 3, 3, 244, 30)
$btPrev = GUICtrlCreateButton("<", 40, 216, 75, 25, 0)
$btNext = GUICtrlCreateButton(">", 136, 216, 75, 25, 0)
GUISetState()
$hThumb = 0
$aWindows = _WinAPI_EnumWindowsTop()
$i = 1
$iMax = $aWindows[0][0]
If $iMax > 0 Then
    GUICtrlSetData($lbWindow, $aWindows[1][1])
    $hThumb = RegisterThumb($aWindows[1][0], $main)
    UpdateThumb($hThumb)
EndIf

While 1
    $msg = GUIGetMsg()
    Switch $msg
        Case $GUI_EVENT_CLOSE
            UnregisterThumb($hThumb)
            Exit
        Case $btNext
            $i += 1
            If $i > $iMax Then $i=0
            UnregisterThumb($hThumb)
            GUICtrlSetData($lbWindow, $aWindows[$i][1])
            $hThumb = RegisterThumb($aWindows[$i][0], $main)
            UpdateThumb($hThumb)
        Case $btPrev
            $i -= 1
            If $i < 1 Then $i = $iMax
            UnregisterThumb($hThumb)
            GUICtrlSetData($lbWindow, $aWindows[$i][1])
            $hThumb = RegisterThumb($aWindows[$i][0], $main)
            UpdateThumb($hThumb)
    EndSwitch
WEnd

Func RegisterThumb($hSrcWnd, $hDestWnd)
    Local $aResult, $pThumbId
    ConsoleWrite("+> Registering: " & $hSrcWnd & @LF)
    $aResult = DllCall("dwmapi.dll", "int", "DwmRegisterThumbnail", "hwnd", $hDestWnd, "hwnd", $hSrcWnd, "int*", $pThumbId)
    $pThumbId = $aResult[3]
    ConsoleWrite("+> ThumbnailId: " & $pThumbId & @LF)
    Return $pThumbId
EndFunc   ;==>RegisterThumb

Func UpdateThumb($hThumbnailId, $x=40, $y=40, $w=170, $h=170)
    Local $aResult, $strDTP
    $strDTP = DllStructCreate($tag_DTP)
    DllStructSetData($strDTP, "dwFlags", BitOR($DWM_TNP_RECTDESTINATION, $DWM_TNP_OPACITY, $DWM_TNP_VISIBLE, $DWM_TNP_SOURCECLIENTAREAONLY))
    DllStructSetData($strDTP, "rcDestination", $x, 1)
    DllStructSetData($strDTP, "rcDestination", $y, 2)
    DllStructSetData($strDTP, "rcDestination", $x + $w, 3)
    DllStructSetData($strDTP, "rcDestination", $y + $h, 4)
    DllStructSetData($strDTP, "opacity", 255)
    DllStructSetData($strDTP, "fVisible", True)
    DllStructSetData($strDTP, "fSourceClientAreaOnly", True)
    $aResult = DllCall("dwmapi.dll", "int", "DwmUpdateThumbnailProperties", "hwnd", $hThumbnailId, "ptr", DllStructGetPtr($strDTP))
EndFunc   ;==>UpdateThumb

Func UnregisterThumb($hThumbId)
    Local $aResult
    ConsoleWrite("-> Unregistering: " & $hThumbId & @LF)
    $aResult = DllCall("dwmapi.dll", "int", "DwmUnregisterThumbnail", "hwnd", $hThumbId)
EndFunc   ;==>UnregisterThumb
Link to comment
Share on other sites

Hehe, nice little script you have there zorphnog.

Here's something I just whippen together, but it's far from perfect. After creating a thumb it makes a screenshot and draws the image to one of the two containers on the left. There are some obvious drawbacks, but I'm sure someone can use the idea to create something awesome :P

#include <GDIPlus.au3>
#include <GUIConstantsEx.au3>
#Include <ScreenCapture.au3>
#include <WindowsConstants.au3>

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

HotKeySet("+!c", "Close")

Run("calc.exe")
WinWait("[CLASS:SciCalc]")
WinSetState("[CLASS:SciCalc]", "", @SW_MINIMIZE)
Run("notepad.exe")
WinWait("[CLASS:Notepad]")
WinSetState("[CLASS:Notepad]", "", @SW_MINIMIZE)
$winA = WinGetHandle("[CLASS:SciCalc]")
$winB = WinGetHandle("[CLASS:Notepad]")

$main = GUICreate("Thumbs", 600, 160, 245, 195, BitOR($WS_THICKFRAME,$WS_POPUP))
GUISetState()
$cont1 = GUICreate("Cont1", 150, 150, 10, -10, $WS_POPUP, $WS_EX_MDICHILD, $main)
GUISetBkColor(0xFF0000)
GUISetState()
$cont2 = GUICreate("Cont2", 150, 150, 165, -10, $WS_POPUP, $WS_EX_MDICHILD, $main)
GUISetBkColor(0x00FF00)
GUISetState()
$cont3 = GUICreate("Cont2", 150, 150, 320, -10, $WS_POPUP, $WS_EX_MDICHILD, $main)
GUISetBkColor(0x0000FF)
GUISetState()

$count = 0
$current = 1
$thumb = CreateThumb($winA, $cont1)

while true
    if $current == 1 then
        $current = 2
        DeleteThumb($thumb)
        $thumb = CreateThumb($winB, $cont1)
        
        _GDIPlus_Startup()
        $hbmp = _ScreenCapture_CaptureWnd("", $cont1, 0, 0, -1, -1, false)
        $bmp = _GDIPlus_BitmapCreateFromHBITMAP($hbmp)
        $gfx = _GDIPlus_GraphicsCreateFromHWND($cont2)
        _GDIPlus_GraphicsDrawImage ($gfx, $bmp, 0, 0)
        _GDIPlus_GraphicsDispose($gfx)
        _GDIPlus_ImageDispose($bmp)
        _WinAPI_DeleteObject($hbmp)
        _GDIPlus_ShutDown ()
    elseif $current == 2 then
        $current = 1
        DeleteThumb($thumb)
        $thumb = CreateThumb($winA, $cont1)
        
        _GDIPlus_Startup()
        $hbmp = _ScreenCapture_CaptureWnd("", $cont1, 0, 0, -1, -1, false)
        $bmp = _GDIPlus_BitmapCreateFromHBITMAP($hbmp)
        $gfx = _GDIPlus_GraphicsCreateFromHWND($cont3)
        _GDIPlus_GraphicsDrawImage ($gfx, $bmp, 0, 0)
        _GDIPlus_GraphicsDispose($gfx)
        _GDIPlus_ImageDispose($bmp)
        _WinAPI_DeleteObject($hbmp)
        _GDIPlus_ShutDown ()
    endif
    Sleep(200)
wend

func CreateThumb($sourceWh, $destWh)
    $size = WinGetClientSize($destWh)
    $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], 3)
    DllStructSetData($DWM_THUMBNAIL_PROPERTIES, "rcDestination", $size[1], 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", $destWh, "hwnd", $sourceWh, "ptr*", 0)
    $thumbid = $call[3]
    $call = DllCall("dwmapi.dll", "int", "DwmUpdateThumbnailProperties", "ptr", $thumbid, "ptr", DllStructGetPtr($DWM_THUMBNAIL_PROPERTIES))
    return $thumbid
endfunc

func DeleteThumb($thumbid)
    DllCall("dwmapi.dll", "int", "DwmUnregisterThumbnail", "ptr", $thumbid)
endfunc

func Close()
    DeleteThumb($thumb)
    WinClose($winA)
    WinClose($winB)
    exit
endfunc
Edited by SaphuA
Link to comment
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
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...