Page 1 of 2

Grab desktop wallpaper to image?

Posted: Sun May 28, 2017 4:59 am
by Dude
How can I grab the desktop wallpaper as an image, without the desktop icons on it, and without opening a window? I can do it if I toggle the desktop icons before and after, but that's ugly. I just want to copy the wallpaper image direct to my own created image. And no, I can't get the path of the wallpaper file because it may be a JPG (on Windows 7). Thanks!

Re: Grab desktop wallpaper to image?

Posted: Sun May 28, 2017 5:11 am
by kvitaliy
The source code is taken from this forum:

Code: Select all

ExamineDesktops()
SCREENX = DesktopWidth(0)
SCREENY = DesktopHeight(0)
UseJPEGImageEncoder()
OpenWindow(0,0,0,SCREENX,SCREENY,"Wallpaper Copy")
CreateImage(0,SCREENX,SCREENY,#PB_Image_DisplayFormat)
hWin = GetDC_(WindowID(0))
PaintDesktop_(hWin)
hImage = StartDrawing(ImageOutput(0))
BitBlt_(hImage,0,0,SCREENX,SCREENY,hWin,0,0,#SRCCOPY)
StopDrawing()
SaveImage(0,"c:\Wallpaper.jpg",#PB_ImagePlugin_JPEG)
ReleaseDC_(WindowID(0),hWin)
InvalidateRect_(WindowID(0),0,1)

Re: Grab desktop wallpaper to image?

Posted: Sun May 28, 2017 5:19 am
by kvitaliy
Another full path to the wallpaper:

Code: Select all

;get wallpaper

CoInitialize_(0)

wbuf=AllocateMemory(1000,0) ;wide char
mbuf=AllocateMemory(1000,0) ;multy byte

CoCreateInstance_(?CLSID_ActiveDesktop,0,1,?IID_IActiveDesktop,@pobj.IActiveDesktop)

pobj\GetWallpaper(wbuf,1000,0)

pobj\release()

WideCharToMultiByte_(#CP_ACP,0,wbuf,-1,mbuf,1000,#Null,#Null)

P$=PeekS(mbuf,1000,#PB_Ascii)
MessageRequester("Wallpapers here: ",P$)

CoUninitialize_()
FreeMemory(wbuf)
FreeMemory(mbuf)
End

;CLSID_ActiveDesktop="{75048700-EF1F-11D0-9888-006097DEACF9}"
;IID_IActiveDesktop="{F490EB00-1240-11D1-9888006097DEACF9}"

DataSection
CLSID_ActiveDesktop:
Data.l $75048700
Data.w $EF1F,$11D0
Data.b $98,$88,$00,$60,$97,$DE,$AC,$F9

IID_IActiveDesktop:
Data.l $F490EB00
Data.w $1240,$11D1
Data.b $98,$88,$00,$60,$97,$DE,$AC,$F9
EndDataSection


Re: Grab desktop wallpaper to image?

Posted: Sun May 28, 2017 5:30 am
by Dude
Thanks, but both responses do NOT do what I asked. :(

I don't want to open a window, because the wallpaper needs to be copied silently without interrupting the user with a window popping up and taking the focus from their current window.

And the path to the wallpaper is no good if the wallpaper is a JPG image, which it can be on Windows 7 (mine currently is), or if the image file gets deleted while the wallpaper is shown.

So, are there any other ways to just copy the wallpaper to an image silently?

Re: Grab desktop wallpaper to image?

Posted: Sun May 28, 2017 6:57 am
by netmaestro
May I ask why a JPG image is no good? This is working fine here with a jpg on win7:

Code: Select all

wall$ = Space(#MAX_PATH)
SystemParametersInfo_(#SPI_GETDESKWALLPAPER, #MAX_PATH, @wall$, 0)
UseJPEGImageDecoder()
UsePNGImageDecoder()
UseTIFFImageDecoder()
LoadImage(0, wall$)
ShowLibraryViewer("image", 0)
CallDebugger
You'll have to decide how you want to activate the grabber, hotkey or whatever you have in mind. Maybe a message-only window (which is invisible and has no desktop footprint at all)

Re: Grab desktop wallpaper to image?

Posted: Sun May 28, 2017 7:11 am
by Bisonte
If you want to load any picture that windows can show to an image : The function LoadImageEX() from Stefan at the german forum helps...

And to get the full filename from the wallpaper, you only need one API functions.

Here an example :

Code: Select all

;: ============================================================================
;: LoadImageEx() 
;: Author : Stefan
;: Forum  : http://www.purebasic.fr/german/viewtopic.php?t=12155
;: 
;: Load any picture without PB-ImagePlugins (jpg,png,bmp,gif, etc.)
;: ----------------------------------------------------------------------------

; #DDBLT_WAIT           = $1000000
; #DXLOCKF_READ         = 0
; #CLSCTX_INPROC_SERVER = 1
; In PB5.60 integrated

Interface nIDXSurfaceFactory
  QueryInterface(a, b)
  AddRef()
  Release()
  CreateSurface(a, b, c, d, e, f, g, h)
  CreateFromDDSurface(a, b, c, d, e, f)
  LoadImage(a.p-bstr, b, c, d, e, f)
  LoadImageFromStream(a, b, c, d, e, f)
  CopySurfaceToNewFormat(a, b, c, d, e)
  CreateD3DRMTexture(a, b, c, d, e)
  BitBlt(a, b, c, d, e)
EndInterface
DataSection
  CLSID_DXTransformFactory:
  Data.l $D1FE6762
  Data.w $FC48,$11D0
  Data.b $88,$3A,$3C,$8B,$00,$C1,$00,$00
 
  IID_IDXTransformFactory:
  Data.l $6A950B2B
  Data.w $A971,$11D1
  Data.b $81,$C8,$00,$00,$F8,$75,$57,$DB
 
  IID_IDXSurfaceFactory:
  Data.l $144946F5
  Data.w $C4D4,$11D1
  Data.b $81,$D1,$00,$00,$F8,$75,$57,$DB
 
  IID_IDXSurface:
  Data.l $B39FD73F
  Data.w $E139,$11D1
  Data.b $90,$65,$00,$C0,$4F,$D9,$18,$9D
EndDataSection
Procedure.i LoadImageEx(Image, FileName.s, Flags=32)
  
  Protected result=CoInitialize_(0)
  Protected dxtf.IDXTransformFactory, dxsf.nIDXSurfaceFactory
  Protected surf.IDXSurface, lock.IDXDCLock, re.rect
  Protected DC.i, DestDC.i, Success.i
  
  If result=#S_FALSE Or result=#S_OK
   
    CoCreateInstance_(?CLSID_DXTransformFactory,0,#CLSCTX_INPROC_SERVER,?IID_IDXTransformFactory,@dxtf.IDXTransformFactory)
   
    If dxtf
      dxtf\QueryService(?IID_IDXSurfaceFactory,?IID_IDXSurfaceFactory,@dxsf.nIDXSurfaceFactory)
      If dxsf
        dxsf\LoadImage(FileName,0,0,0,?IID_IDXSurface,@surf.IDXSurface)
        If surf
         
          surf\LockSurfaceDC(0,#INFINITE,#DXLOCKF_READ,@lock.IDXDCLock)
          If lock
            DC=lock\GetDC()
           
            If DC
              GetClipBox_(DC,re.rect)
             
              If Image=#PB_Any
                result=CreateImage(#PB_Any,re\right,re\bottom,Flags)
                Image=result
              Else
                result=CreateImage(Image,re\right,re\bottom,Flags)
              EndIf
             
              If result
               
                DestDC=StartDrawing(ImageOutput(Image)) 
                If DestDC
                  Success=BitBlt_(DestDC,0,0,re\right,re\bottom,DC,0,0,#SRCCOPY)
                  StopDrawing()         
                EndIf
               
                If Success=#False:FreeImage(Image):EndIf
              EndIf
            EndIf
           
            Lock\Release()     
          EndIf
         
          surf\Release()
        EndIf
       
        dxsf\Release()
      EndIf
     
      dxtf\Release()
    EndIf
   
    ;CoUninitialize_() ; dosn't work with this ?!?
  EndIf
 
  If Success:ProcedureReturn result:EndIf
  ProcedureReturn #False

EndProcedure

;: ============================================================================

;: Get the wallpaper filename with path

WallPaper.s = Space(#MAX_PATH)
SystemParametersInfo_(#SPI_GETDESKWALLPAPER, #MAX_PATH, WallPaper, 0)

;: Load the image
Image = LoadImageEx(#PB_Any, WallPaper)

;: Test to show the image

OpenWindow(0, 0, 0, 640, 480, "Test", #PB_Window_ScreenCentered|#PB_Window_SystemMenu|#PB_Window_SizeGadget)

ImageGadget(1, 0, 0, 640, 480, ImageID(Image))
AddKeyboardShortcut(0, #PB_Shortcut_Escape, 59999)

Repeat
  Event = WaitWindowEvent()
  
  Select Event
    Case #PB_Event_CloseWindow
      Quit = #True

    Case #PB_Event_Menu
      Select EventMenu()
        Case 59999
          Quit = #True
      EndSelect
      
  EndSelect
  
Until Quit

Re: Grab desktop wallpaper to image?

Posted: Sun May 28, 2017 7:25 am
by Dude
netmaestro wrote:May I ask why a JPG image is no good?
Mainly because UseJPEGImageDecoder() adds 127 KB to my exe size when a simple BitBlt_() call should do the same thing.

Basically, kvitaliy's solution above would be 100% perfect if I didn't have to open a window.

I can easily do what I want already, but WITH the desktop icons included. :( So there must be a way to grab WITHOUT toggling the icons off first, surely?

Re: Grab desktop wallpaper to image?

Posted: Sun May 28, 2017 8:13 am
by Bisonte
Have you read NM's or my post ?

That is a way to load the original desktop wallpaper to an image !

Re: Grab desktop wallpaper to image?

Posted: Sun May 28, 2017 9:54 am
by firace
Give this one a try.
No wallpaper path, no JPG decoder, no open windows, no desktop icons. :)
(Tested on Windows 10)

Code: Select all

ExamineDesktops()
CreateImage(1,DesktopWidth(0),DesktopHeight(0))
PaintDesktop_(StartDrawing(ImageOutput(1)))
StopDrawing()
SaveImage(1,"tada.bmp")

Re: Grab desktop wallpaper to image?

Posted: Sun May 28, 2017 10:42 am
by Bisonte
very nice ;)

Re: Grab desktop wallpaper to image?

Posted: Sun May 28, 2017 11:09 am
by Dude
Bisonte wrote:Have you read NM's or my post ?

That is a way to load the original desktop wallpaper to an image !
Yes, and both posts don't satisfy the criteria that I asked. Are you aware that your desktop can have a wallpaper image WITHOUT a file on disk for it? Maybe you've never seen that, but I have. So I can't rely on trying to get the image from a file that might not be there anymore. That's why I'm asking if anyone knows a way to get the image without a file.

@firace: Thanks, but that just gives a black BMP image here on Win 7.

Re: Grab desktop wallpaper to image?

Posted: Sun May 28, 2017 11:13 am
by RASHAD
Try

Code: Select all

ExamineDesktops()

hWnd = FindWindow_("ProgMan", 0)
hBitmap = CreateImage(0, DesktopWidth(0), DesktopHeight(0),24)
hdc = StartDrawing(ImageOutput(0))
     SelectObject_(hdc, hBitmap)
     BitBlt_(hdc, 0, 0,DesktopWidth(0), DesktopHeight(0), GetWindowDC_(hWnd), 0, 0, #SRCCOPY)
StopDrawing()

SaveImage(0,GetHomeDirectory()+"test.bmp")

Re: Grab desktop wallpaper to image?

Posted: Sun May 28, 2017 11:27 am
by Dude
Hi Rashad, that's close, but your solution still shows the desktop icons. :( I thought I fixed it but it still fails in some situations.

Re: Grab desktop wallpaper to image?

Posted: Sun May 28, 2017 1:02 pm
by RASHAD
Hi Dude
Try

Code: Select all

ExamineDesktops()

hWnd = FindWindow_("ProgMan", 0)
hBitmap = CreateImage(0, DesktopWidth(0), DesktopHeight(0),24)
If OSVersion() < #PB_OS_Windows_10 
  shWnd = GetWindow_(hWnd, #GW_CHILD)
  ShowWindow_(shWnd,#SW_HIDE)
EndIf
hdc = StartDrawing(ImageOutput(0))
     SelectObject_(hdc, hBitmap)
     BitBlt_(hdc, 0, 0,DesktopWidth(0), DesktopHeight(0), GetWindowDC_(hWnd), 0, 0, #SRCCOPY)
StopDrawing()
If OSVersion() < #PB_OS_Windows_10
  ShowWindow_(shWnd,#SW_SHOW)
EndIf
SaveImage(0,GetHomeDirectory()+"test.bmp")

Re: Grab desktop wallpaper to image?

Posted: Sun May 28, 2017 1:33 pm
by Dude
Hi Rashad. :) It's weird. Your code works on Win 7 now but ONLY when I'm logged in as a limited user. When I tried it with an admin account, it saves the current foreground window instead (the PureBasic IDE). Thanks anyway.