[help] Set Wallpaper To Non-.bmp

I'm trying to write an app to change the desktop wallpaper, but the registry entry I've found only works after a restart and the SystemParametersInfo API only works for .bmp. Has anyone found a way around this? I can't use GD to convert, because I'd have to include wrappers and TLBs and all that.. but surely there's some way to do it. >.

#171591

Well, you might want to tell us what registry entry doesn't work.

Have you tried this registry entry?HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Themes\LastTheme

Hope this helps,

nightcrawler1089

#171597

That doesn't seem to change anything.. there is a Wallpaper value under HKEY_CURRENT_USER\Control Panel\Desktop, but it has to be a BMP. -_-

#171636

Ripped from a change-wallpaper application I wrote for Pe8er / Lou:

#include <windows.h>
#include <gdiplus.h>
#include <shellapi.h>
#pragma comment(lib,"gdiplus.lib")
using namespace Gdiplus;

int GetEncoderClsid(const WCHAR* format, CLSID* pClsid)
{
  UINT  num = 0;          // number of image encoders
  UINT  size = 0;         // size of the image encoder array in bytes

  ImageCodecInfo* pImageCodecInfo = NULL;

  GetImageEncodersSize(&num, &size);
  if(size == 0)
     return -1;  // Failure

  pImageCodecInfo = (ImageCodecInfo*)(malloc(size));
  if(pImageCodecInfo == NULL)
     return -1;  // Failure

  GetImageEncoders(num, size, pImageCodecInfo);

  for(UINT j = 0; j < num; ++j)
  {
     if( wcscmp(pImageCodecInfo[j].MimeType, format) == 0 )
     {
        *pClsid = pImageCodecInfo[j].Clsid;
        free(pImageCodecInfo);
        return j;  // Success
     }    
  }

  free(pImageCodecInfo);
  return -1;  // Failure
}

int WINAPI WinMain(

   HINSTANCE hInstance, // handle to current instance
   HINSTANCE hPrevInstance, // handle to previous instance
   LPSTR lpCmdLine, // pointer to command line
   int nCmdShow  // show state of window
  )

{
GdiplusStartupInput g_gdiplusStartupInput;
ULONG_PTR g_gdiplusToken;
GdiplusStartup(&g_gdiplusToken, &g_gdiplusStartupInput, NULL);

WCHAR* wCmd = GetCommandLineW();
int argc(0);
WCHAR** argv = CommandLineToArgvW(wCmd,&argc);

if(argc > 1)
{
 Bitmap* bmp = new Bitmap(argv[1]);
 Bitmap* bmp2 = (Bitmap*)(((Image*)bmp)->Clone());
 delete bmp;
 bmp = 0;
 

 char path[MAX_PATH];
 GetWindowsDirectory(path,MAX_PATH);
 strcat(path,"\\louwall.bmp");
 OLECHAR wPath[MAX_PATH];
 MultiByteToWideChar(CP_OEMCP,0,path,-1,wPath,MAX_PATH);

 CLSID encoderClsid = {0};
 GetEncoderClsid(L"image/bmp",&encoderClsid);
 bmp2->Save(wPath, &encoderClsid, 0);
 delete bmp2;
 bmp2 = 0;

 HKEY key = {0};
 RegOpenKeyEx(HKEY_CURRENT_USER,"Control Panel\\Desktop\\",0,KEY_ALL_ACCESS,&key);
 const char wp[] = {'W','a','l','l','p','a','p','e','r','\0'};
 RegSetValueEx(key,wp,0,REG_SZ,(BYTE*)path,strlen(&path[0])+1);
 RegFlushKey(key);
 RegCloseKey(key);
 SystemParametersInfo(SPI_SETDESKWALLPAPER,0,(PVOID)path,SPIF_SENDWININICHANGE);

}
GlobalFree((HGLOBAL)wCmd);
GlobalFree((HGLOBAL)argv);

GdiplusShutdown(g_gdiplusToken);

return 0;
}

Don't ask me about the strange things, I was on drugs I think <_<

#171654

It has to be bmp if you don't have active desktop enabled.

Don't know for XP; but 98, ME, NT and 2000 asked the user if

he/she wanted to enable ActiveDesktop if you tried to switch to a non bmp.

There should be a different API to do it without reboot.

#171655

Thanks, Ave, but I'm not using C.. I'd compile that into a COM DLL that I could use, but I don't have a compiler and wouldn't know how anyways. :rolleyes:

#171704

Well, The C++ shouldn't be the problem. For except the Gdiplus calls, there are only WINAPI calls.

What languages are you using then?

BTW, the wallpaper has to be a BMP file. Windows automatically converts any other type it seems to support to a Bitmap and stores this file in the root of your user directory. It also uses a certain registrykey to store the filepath of the original one.

#172016

Yes, I know about the conversion thing and the registry entry linking to it, and the API call for setting the wallpaper.. it's just the converting-to-BMP part I have a problem with. It's a Kapsules VBScript widget, which of course can't do any of that stuff, but my idea was to use VB6 to make a small OCX that'd convert the image and apply it. Could you give me any help on the minimum specific API calls I'd have to use, and how to use them?

#172225

You can do a conversion DLL in VB6 that loads the following:

GIF

JPG/JPEG

TIFF

and saves it to a BMP file. Just use the LoadPicture / SavePicture methods.

However, PNGs and other image types later than 1994 won't do.

To come around the reboot problem,

SystemParametersInfo(SPI_SETDESKWALLPAPER,0,(PVOID)path,SPIF_SENDWININICHANGE);

from Ave's C++ post does the trick. A lot of web sites dedicated to VB programming show you how to use it - googling helps.

Unfortunately, the IActiveDesktop interface I was referring to is not accessible by VB and vbScript - its SetWallpaper method would handle all image types that Internet Explorer is capable of viewing (without the need of conversion), even plugged in image helpers like QuickTime would extend its functionality...

hth,

herd

#174053