Create your own Flip Task Bar with live thumbnails using Vista Desktop Window Manager DWM
The sample below uses Desktop Window Manager under Windows Vista with Aero to get dynamic live thumbnails of running applications. If a movie is playing in Windows Media Player, it will play in the thumbnail too!
EnumChildWindows or EnumWindows is used to enumerate all running windows created by the various processes on your machine.
I extracted code from: How does EventHandler work? IConnectionPoint! to make the CAsmLib class to generate assembly code. The sample below uses the class to generate ASM code that gets called by EnumChildWindows and calls _VFP.DoCmd method to insert the Window handles found into a cursor.
On both XP and Vista, the code will generate a cursor with Window Handles and their titles.
A SQL statement executed in a timer routine determines if any new processes were added and if so, to refresh the display.
SELECT hWnd,Title FROM NewTopLevel WHERE hWnd NOT in (SELECT hWnd FROM TopLevel) UNION ;
SELECT hWnd,Title FROM TopLevel WHERE hWnd NOT in (SELECT hWnd FROM NewTopLevel) ;
INTO CURSOR temp
If you’re running on Vista and DwmIsCompositionEnabled, the code will then create a form and an array of live thumbnails on it. The form uses an array of invisible commandbuttons for each thumbnail. Using an Image control without an image displays a cross. All we’re doing is providing an hWnd and a rect for DWM to draw the thumbnail.
(Vista Aero can have DwmIsCompositionEnabled enabled or disabled. See Control Panel->System and Maintenance->System->Advanced System Settings->Advanced->Performance->Settings->Visual Effects->Enable desktop composition)
GetWindowThreadProcessId is called to get the Process Id of the window handle.
Play a movie: make it repeat if it’s short, do things in other windows, and you’ll see the thumbnails update on the form. Hit Alt-Tab (or Alt-Ctrl-Tab to keep the flip display on, or even WindowsKey-Tab), and you’ll see the thumbnail still live. Use the slider to changes the size of the thumbnails. You can even make the thumbs larger than the source application!
Click on a thumbnail to make it the foreground application. Resize the thumbnail form. Modify source windows by editing text, etc. Hit WindowKey->M to minimize all windows.
CLEAR ALL
CLEAR
MODIFY COMMAND PROGRAM() NOWAIT
SET SAFETY OFF
PUBLIC oForm
oForm=CREATEOBJECT("CThumbForm")
#define WS_VISIBLE 0x10000000
#define WS_BORDER 0x00800000
DEFINE CLASS CThumbForm as Form
ShowWindow=2 && Top Level
width=SYSMETRIC(1) && entire width of display
height=100
MinButton=.f. && don't allow minimize for us
nThumbs=0 && number of thumbs currently on form
fDWM = .f. && are we running under Vista Desktop Window Management?
nThumbWidth=400 && size of thumb to draw
nThumbHeight=this.nThumbWidth * SYSMETRIC(2)/SYSMETRIC(1) && same aspect ratio as desktop
ADD OBJECT cmdQuit as CommandButton WITH Caption="\<Quit",cancel=.t.
ADD OBJECT cmdRefresh as CommandButton WITH Caption="\<Refresh",left=120
ADD OBJECT oSlider as cSlider WITH left=250
ADD OBJECT oTimer as Timer WITH interval=2000 && millisecs
PROCEDURE oTimer.Timer
thisform.GetHWnds("NewTopLevel")
SELECT hWnd,Title FROM NewTopLevel WHERE hWnd NOT in (SELECT hWnd FROM TopLevel) UNION ;
SELECT hWnd,Title FROM TopLevel WHERE hWnd NOT in (SELECT hWnd FROM NewTopLevel) ;
INTO CURSOR temp
IF _Tally>0 && a new window was created or destroyed
thisform.GetThumbNails() && ToDo: optimize for only the change
ENDIF
PROCEDURE cmdRefresh.Click
thisform.GetThumbNails()
PROCEDURE cmdQuit.Click
thisform.release
PROCEDURE Init
SET TALK OFF
IF VAL(OS(3))>=6 && runnning under Vista. Check for Desktop Compostion enabled
DECLARE integer DwmIsCompositionEnabled IN dwmapi integer @ dwEnabled
dwEnabled=0
IF DwmIsCompositionEnabled(@dwEnabled) = 0 AND dwEnabled>0
this.fDWM = .t.
ENDIF
ENDIF
IF this.fDWM
DECLARE integer DwmRegisterThumbnail IN dwmapi integer hwndDest, integer hwndSrc, integer @ nThumbnailId
DECLARE integer DwmUnregisterThumbnail IN dwmapi integer nThumbnailId
DECLARE integer DwmQueryThumbnailSourceSize IN dwmapi integer nThumbnailId, string @pSize
DECLARE integer DwmUpdateThumbnailProperties IN dwmapi integer hThumbnailId, string @ ptnProperties
DECLARE integer SetForegroundWindow IN WIN32API integer
DECLARE integer GetWindowPlacement IN WIN32API integer hWnd, string @ pPlacement
DECLARE integer SetWindowPlacement IN WIN32API integer hWnd, string @ pPlacement
this.Visible=1
* this.GetThumbNails() && Resize will call GetThumbNails
ELSE
NEWOBJECT("CEnumWindows") && call the class that creates the cursor of hWnds
LOCATE && go to the top of the cursor
BROWSE LAST NOWAIT
RETURN .f. && don't create form
ENDIF
PROCEDURE Resize
this.GetThumbNails()
PROCEDURE GetHWnds(DestCursor as string)
NEWOBJECT("CEnumWindows") && call the class that creates the cursor of hWnds
SELECT * FROM hwnds WHERE BITAND(style,WS_VISIBLE+WS_BORDER) = WS_VISIBLE+WS_BORDER AND ;
hWnd != thisform.HWnd ;
INTO CURSOR (DestCursor) && Only those hWnds which are visible and have a border
RETURN _tally
PROCEDURE GetThumbNails
LOCAL cStr,oLbl,cName,x,y,oi
thisform.LockScreen= .T.
FOR indx = 1 TO thisform.nThumbs
cName="im"+PADL(indx,3,"0") && im001, im002...
thisform.RemoveObject(cName)
IF TYPE("thisForm."+cName+"lbl")="O"
thisform.RemoveObject(cName+"lbl")
ENDIF
ENDFOR
thisform.nThumbs=this.GetHWnds("TopLevel")
INDEX on hwnd TAG hwnd
nRatio = thisform.oSlider.Value/thisform.oSlider.max
x = 0
y = 20
indx=1
SCAN
cName="im"+PADL(indx,3,"0") && im001, im002...
thisform.AddObject(cName,"CThumb")
cStr="Thisform."+cName
oi = EVALUATE(cStr)
oi.Height = this.nThumbHeight * nRatio
oi.Width = this.nThumbWidth * nRatio
oi.Left = x
oi.Top = y
oi.visible=1