SaphuA Posted August 14, 2008 Share Posted August 14, 2008 (edited) 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 pcWhat am I doing wrong?ThanksCode removed, see below for new version. Edited August 14, 2008 by SaphuA http://www.saphua.com/ Link to comment Share on other sites More sharing options...
monoceres Posted August 14, 2008 Share Posted August 14, 2008 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 )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 More sharing options...
SaphuA Posted August 14, 2008 Author Share Posted August 14, 2008 (edited) Ah that's a smart idea 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: expandcollapse popup#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 August 14, 2008 by SaphuA http://www.saphua.com/ Link to comment Share on other sites More sharing options...
SaphuA Posted August 14, 2008 Author Share Posted August 14, 2008 (edited) Sorry for all the spamming 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? expandcollapse popup#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 August 14, 2008 by SaphuA http://www.saphua.com/ Link to comment Share on other sites More sharing options...
monoceres Posted August 14, 2008 Share Posted August 14, 2008 (edited) Sorry for all the spamming 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 Edited August 14, 2008 by monoceres Broken link? PM me and I'll send you the file! Link to comment Share on other sites More sharing options...
NeoFoX Posted August 14, 2008 Share Posted August 14, 2008 SaphuA, Perhaps you can put this one in the freezer for a little while 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 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 More sharing options...
zorphnog Posted August 14, 2008 Share Posted August 14, 2008 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 More sharing options...
zorphnog Posted August 14, 2008 Share Posted August 14, 2008 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. expandcollapse popup#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 More sharing options...
SaphuA Posted August 14, 2008 Author Share Posted August 14, 2008 (edited) 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 expandcollapse popup#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 August 14, 2008 by SaphuA http://www.saphua.com/ Link to comment Share on other sites More sharing options...
Recommended Posts
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 accountSign in
Already have an account? Sign in here.
Sign In Now