Jump to content

Redraw your desktop with GDI+


 Share

Recommended Posts

Take a screenshot of your desktop (works even if the desktop is hidden), then redraws it row by row. Makes a neat little effect. An effect I remember seeing at the photo booth at Chuck E' Cheese.

I mostly just wanted to mess with LockBits and PrintWindow and thought this was a decent way to figure it out, but I liked the outcome and thought I'd share lol

#include <GDIPlus.au3>
#include <WinApi.au3>
#include <WindowsConstants.au3>

_GDIPlus_Startup()
Global $tDesktopMetrics = GetDesktopMetrics()
Global $hHBitmapDesktop = CaptureWindow("", -1, -1, -1, -1, "Program Manager")
Global $hBitmapDesktop = _GDIPlus_BitmapCreateFromHBITMAP($hHBitmapDesktop)
_WinAPI_DeleteObject($hHBitmapDesktop)
Global $iW = _GDIPlus_ImageGetWidth($hBitmapDesktop)
Global $iH = _GDIPlus_ImageGetHeight($hBitmapDesktop)
Global $tBitmapData = _GDIPlus_BitmapLockBits($hBitmapDesktop, 0, 0, $iW, $iH, $GDIP_ILMREAD, $GDIP_PXF32PARGB)
Global $tPixelMap = DllStructCreate("int[" & $iW * $iH & "];", DllStructGetData($tBitmapData, "Scan0"))
Global $hGui = GUICreate("Redraw", $iW, $iH, $tDesktopMetrics.x, $tDesktopMetrics.y, $WS_POPUP)
Global $hGraphics = _GDIPlus_GraphicsCreateFromHWND($hGui)
Global $hBitmap = _GDIPlus_BitmapCreateFromGraphics($iW, $iH, $hGraphics)
Global $tBitmapData2 = _GDIPlus_BitmapLockBits($hBitmap, 0, 0, $iW, $iH, $GDIP_ILMWRITE, $GDIP_PXF32PARGB)
Global $tPixelMap2 = DllStructCreate("int[" & $iW * $iH & "];", DllStructGetData($tBitmapData2, "Scan0"))

GUISetState(@SW_SHOW, $hGui)

_GDIPlus_GraphicsClear($hGraphics)

For $iY = 0 To $iH - 1
    Local $iRowOffset = $iY * $iW + 1
    For $iX = 0 To $iW - 1 ;get each pixel in each line and row
        DllStructSetData($tPixelMap2, 1, DllStructGetData($tPixelMap, 1, $iRowOffset + $iX), $iRowOffset + $iX)
    Next
    If (Not Mod($iY, 5)) Then   ; Every 5 rows draw the bitmap
        _GDIPlus_BitmapUnlockBits($hBitmap, $tBitmapData2)
        _GDIPlus_GraphicsDrawImage($hGraphics, $hBitmap, 0, 0)
        $tBitmapData2 = _GDIPlus_BitmapLockBits($hBitmap, 0, 0, $iW, $iH, $GDIP_ILMWRITE, $GDIP_PXF32PARGB)
        $tPixelMap2 = DllStructCreate("int[" & $iW * $iH & "];", DllStructGetData($tBitmapData2, "Scan0"))
    EndIf
Next

If (Mod($iY, 5)) Then   ; Didn't end on an even row, clean up
    _GDIPlus_BitmapUnlockBits($hBitmap, $tBitmapData2)
    _GDIPlus_GraphicsDrawImage($hGraphics, $hBitmap, 0, 0)
    $tPixelMap2 = 0
    $tBitmapData2 = 0
EndIf

_GDIPlus_BitmapUnlockBits($hBitmapDesktop, $tBitmapData)
_GDIPlus_BitmapDispose($hBitmapDesktop)
_GDIPlus_BitmapDispose($hBitmap)
_GDIPlus_GraphicsDispose($hGraphics)
_GDIPlus_Shutdown()
GUIDelete($hGui)
Exit 0

Func CaptureWindow($sFileName = "", $iLeft = -1, $iTop = -1, $iWidth = -1, $iHeight = -1, $hWnd = WinGetHandle("[Active]"), $bClientArea = True)
    If (Not IsHWnd($hWnd)) Then $hWnd = WinGetHandle($hWnd)
    If (@error) Then Return SetError(1, 0, False)
    If (BitAND(WinGetState($hWnd), 16) = 16) Then Return SetError(2, 0, False)
    Local $iSrcWidth = 0
    Local $iSrcHeight = 0

    ConsoleWrite($iLeft & ', ' & $iTop & ", " & $iWidth & ', ' & $iHeight & @LF)

    If ($hWnd = _WinAPI_GetDesktopWindow() Or $hWnd = WinGetHandle("Program Manager")) Then
        Local $tDesktop = GetDesktopMetrics()
        If ($iWidth = -1 Or $iWidth = 0 Or $iWidth = Default Or $iWidth > DllStructGetData($tDesktop, 3)) Then $iWidth = DllStructGetData($tDesktop, 3)
        If ($iHeight = -1 Or $iHeight = 0 Or $iHeight = Default Or $iWidth > DllStructGetData($tDesktop, 4)) Then $iHeight = DllStructGetData($tDesktop, 4)
        $iSrcWidth = DllStructGetData($tDesktop, 3)
        $iSrcHeight = DllStructGetData($tDesktop, 4)
    Else
        Local $tRectWindow = _WinAPI_GetWindowRect($hWnd)
        ; Get the absolute width, using Abs on all of the memembers because the [1] index of the struct may be negative, supports multiple monitors
        Local $iAbsWidth = Abs(Abs(DllStructGetData($tRectWindow, 3)) - Abs(DllStructGetData($tRectWindow, 1)))
        ; Get the absolute height, using Abs on all of the memembers because the [1] index of the struct may be negative, supports multiple monitors
        ; Subtracts the caption bar if $bClientArea only
        Local $iAbsHeight = Abs(Abs(DllStructGetData($tRectWindow, 4)) - Abs(DllStructGetData($tRectWindow, 2))) - ($bClientArea ? _WinAPI_GetSystemMetrics($SM_CYCAPTION) : 0)
        If ($iWidth = -1 Or $iWidth = 0 Or $iWidth = Default Or $iWidth > $iAbsWidth) Then $iWidth = $iAbsWidth
        If ($iHeight = -1 Or $iHeight = 0 Or $iHeight = Default Or $iHeight > $iAbsHeight) Then $iHeight = $iAbsHeight
        $iSrcWidth = $iAbsWidth
        $iSrcHeight = $iAbsHeight
    EndIf

    If ($iLeft = -1 Or $iLeft = Default) Then $iLeft = 0
    If ($iTop = -1 Or $iTop = Default) Then $iTop = 0

    Local $hDC = _WinAPI_GetWindowDC($hWnd)
    Local $hDestDC = _WinAPI_CreateCompatibleDC($hDC)
    Local $hDestBitmap = _WinAPI_CreateCompatibleBitmap($hDC, $iWidth, $iHeight)
    Local $hDestSv = _WinAPI_SelectObject($hDestDC, $hDestBitmap)
    Local $hSrcDC = _WinAPI_CreateCompatibleDC($hDC)
    Local $hBmp = _WinAPI_CreateCompatibleBitmap($hDC, $iSrcWidth, $iSrcHeight)
    Local $hSrcSv = _WinAPI_SelectObject($hSrcDC, $hBmp)

    _WinAPI_PrintWindow($hWnd, $hSrcDC, True)

    _WinAPI_BitBlt($hDestDC, 0, 0, $iWidth, $iHeight, $hSrcDC, $iLeft, $iTop, $MERGECOPY)

    _WinAPI_SelectObject($hDestDC, $hDestSv)
    _WinAPI_SelectObject($hSrcDC, $hSrcSv)
    _WinAPI_ReleaseDC($hWnd, $hDC)
    _WinAPI_DeleteDC($hDestDC)
    _WinAPI_DeleteDC($hSrcDC)
    _WinAPI_DeleteObject($hBmp)
    $tPoint = 0
    $tRectWindow = 0
    $tDesktop = 0

    If ($sFileName) Then
        _GDIPlus_Startup()
        Local $hBitmap = _GDIPlus_BitmapCreateFromHBITMAP($hDestBitmap)
        _GDIPlus_ImageSaveToFile($hBitmap, $sFileName)
        _GDIPlus_BitmapDispose($hBitmap)
        _GDIPlus_Shutdown()
    EndIf
    Return $hDestBitmap
EndFunc   ;==>CaptureWindow

Func GetDesktopMetrics()
    Return _GDIPlus_RectFCreate(_WinAPI_GetSystemMetrics($SM_XVIRTUALSCREEN), _WinAPI_GetSystemMetrics($SM_YVIRTUALSCREEN), _
            _WinAPI_GetSystemMetrics($SM_CXVIRTUALSCREEN), _WinAPI_GetSystemMetrics($SM_CYVIRTUALSCREEN))
EndFunc   ;==>GetDesktopMetrics

 

Edited by InunoTaishou
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

×
×
  • Create New...