# SystemParametersInfo - C/C++

This topic is 4449 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

Okay, for starters, before we get going into my problem, here's something: in the MSDN 6 library, from cd, it says that if your call to SystemParametersInfo fails, to use GetLastError. Fine, no problem here. Then, for GetLastError, it directs you to FormatMessage to get a string describing the problem. And, in the FormatMessage info, it tell you to go back to GetLastError if it fails. Here's a question: what if you have problems making the FormatMessage function work? Can you really go back to GetLastError? I mean, you can call it, but how do you get useful information about the error without FormatMessage? </rant> Okay, now, onto my real problem. I'm attempting to use the SystemParametersInfo function to change the background. It's not going well.
if( !SystemParametersInfo(SPI_SETDESKWALLPAPER, 0,
"C:\\Documents and Settings\\Naim\\My Documents\\My Pictures\\naruto wallpapers\\Naruto022.jpg",
SPIF_UPDATEINIFILE) ){

char* str = NULL;	// function allocates the mem with LocalAlloc(), used with LocalFree()
int msg_ret = FormatMessage(	FORMAT_MESSAGE_ALLOCATE_BUFFER |	// let the function alloc string mem
FORMAT_MESSAGE_FROM_SYSTEM |	// use system message and not a passed one
FORMAT_MESSAGE_IGNORE_INSERTS,	// ignore and "inserts"
NULL,
GetLastError(),			// get the error
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),	// default language
(char*)&str,
0,
NULL);

printf(	"\n Error: Desktop wallpaper change failed."
"\n Error message: %s"
"\n", str);

LocalFree(str);	// free the local mem allocated

exit(1);
}


I got the SystemParametersInfo function from the other topic that was recently in the beginners forum, something about the program taking all the CPU time because he wasn't Sleep'ing it. Anyway, there's a random thing going on before the System.... call, but I've hardcoded everything until I get it going. For starters: yes, the file does exist in that directory, and it is a valid jpg file. Second, I get a strange string back from the FormatMessage function. Here's the total output:
 Error: Desktop wallpaper change failed.
Error message: The operation completed successfully.

For an error message, that is honestly one of the least helpful I've seen. And, MSDN actually says:
Quote:
 If the function fails, the return value is zero. To get extended error information, callGetLastError.
So, does anyone know how to use this function properly? Edit:: Also, I saved the file to a bmp and tried to use that as the filename, and, well it didn't work, the background stayed the same, but, the function was successful, it didn't enter the if.

##### Share on other sites
Ok, first of all, you probably want the fourth parameter to be SPIF_SENDCHANGE, not SPIF_UPDATEINIFILE. Currently, you're updating the stored setting, but nothing else is being notified of the change. Explorer won't look for a new background setting, you have to tell it it's changed. You'll find that the background will probably be applied when you restart currently. To have it happen instantly, change the fourth parameter to SPIF_SENDCHANGE.

Quote:
 Here's a question: what if you have problems making the FormatMessage function work? Can you really go back to GetLastError? I mean, you can call it, but how do you get useful information about the error without FormatMessage?

GetLastError gives you the numerical identifier of the error. With the error number, you can just look it up in documentation. All FormatMessage does is look it up for you basically. System Error Codes.

##### Share on other sites
Correction: You want both SPIF_UPDATEINIFILE and SPIF_SENDCHANGE to be applied. Combine them using a binary or, like so:

SystemParametersInfo(SPI_SETDESKWALLPAPER, 0, path, SPIF_UPDATEINIFILE | SPIF_SENDCHANGE);

##### Share on other sites
NOW we're cooking.

Okay, using both worked, as I can see it should, but I can only use it with bitmaps and not jpg's.

The background that I selected from the desktop properties was a jpg, so, why won't it work like this?

##### Share on other sites
Images that are not BMP (JPG, GIF...) will be converted to a temporary bitmap when you're selecting it from Display Properties, and this feature is functional when Active Desktop is activated. When you set the wallpaper using SystemParametersInfo (), the Active Desktop configurations (probably - I'm not sure about its underlying mechanism) remains unchanged, so calling SystemParameterInfos () with an image of type other than bitmap won't work (you'll see a black background instead).

Disabling Active Desktop will also disable the ability to select a JPG image in Display Properties.

Hth.

##### Share on other sites
Any idea how to maybe call a function that will be recognized by Active Desktop?

##### Share on other sites
I'm begin searching... I will reply as soon as I can.
Good luck.

##### Share on other sites
That was quick! Thanks.

Edit:: Okay, I'm having a little trouble using this. I get that I have to access it through an IActiveDesktop interface. But beyond that, not a lot of the MSDN stuff I'm looking at is making sense.

I'm including shlobj.h, which looks like it has everything I need, but whenever I try to use IActiveDesktop as a namespace or class name, it just complains that it doesn't exist.

##### Share on other sites
You need to #include <WinInet.h>, or define _WININET_, the ShlObj.h checks for availability of this symbol to declare some other methods, but these have nothing to do with SetWallpaper ().

I hope this little program will run smoothly:
#include <Windows.h>#include <WinInet.h>#include <ShlObj.h>//Main window procedure WinMainint WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int iShowCmd){	CoInitialize (NULL) ;	HRESULT hr;	IActiveDesktop *pActiveDesktop;	//Create an instance of the Active Desktop	hr = CoCreateInstance(CLSID_ActiveDesktop, NULL, CLSCTX_INPROC_SERVER,						IID_IActiveDesktop, (void**)&pActiveDesktop);	//Insert code to call the IActiveDesktop methods		LPCWSTR wcPath = L"Insert File Path Here" ;		if (pActiveDesktop -> SetWallpaper (wcPath, 0) != S_OK)		{			//The method has failed...		}	// Call the Release method	pActiveDesktop->Release();	CoUninitialize () ;	return 0 ;}

There maybe something wrong though, I have no compiler to check right now...

##### Share on other sites
Okay, how do you convert a normal char string to a wchar string?

Edit:: or, better yet, a std::string to std::wstring?

Okay, I've gotten that working.

The program compiles fine, runs with no errors, yet again, nothing happens.

This is the code that I currenly have:
	// create a wstring object because that is what the setwallpaper func takes	std::wstring s;	// convert between string and wstring	for(i=0; i < fname.size(); i++)		s += fname;	CoInitialize(NULL);	HRESULT hr;	IActiveDesktop *pActiveDesktop;	//Create an instance of the Active Desktop	hr = CoCreateInstance(CLSID_ActiveDesktop, NULL, CLSCTX_INPROC_SERVER,						IID_IActiveDesktop, (void**)&pActiveDesktop);	if( hr != S_OK )		MessageBox(NULL, "ERROR", "ERROR", MB_OK);	// change the wallpaper	pActiveDesktop->SetWallpaper(s.c_str(), 0);	// Call the Release method	pActiveDesktop->Release();	CoUninitialize () ;

And, I've tried calling GetLastError after every single statement there. After every single one, and the only error I get, is after the 'CoUninit..' call. The error is "Class does not exist.". Which is fairly confusing, because, if it didn't wouldn't every function call there generate a fit? (fit, as in crazy fit)

[Edited by - Endar on December 20, 2005 8:40:37 AM]

##### Share on other sites
That's really wierd, my program above's just worked with me (Windows XP Pro).
I also noticed that even these function executed successfully, a call to GetLastError () still produces error codes (I checked every function call and invoked GetLastError () right after). This case I really have no idea, sorry.

##### Share on other sites
Quote:
 Original post by Skeleton_V@TThat's really wierd, my program above's just worked with me (Windows XP Pro).I also noticed that even these function executed successfully, a call to GetLastError () still produces error codes (I checked every function call and invoked GetLastError () right after). This case I really have no idea, sorry.

Did you try with jpg's or only bmp's?

##### Share on other sites
I've tried JPG, PNG, GIF, not BMP (as I'm quite sure it will work). And with BMPs I'd just use SystemParametersInfo ().

I'm surprised you received no error code from these functions but GetLastError ().

You may try GetWallpaper () method to see if pActiveDesktop really works:
WCHAR wcTemp[512] ;hr = pActiveDesktop -> GetWallpaper (wcTemp, 512, 0) ;MessageBoxW (0, wcTemp, 0, 0) ;

[Edited by - Skeleton_V@T on December 20, 2005 10:10:21 AM]

##### Share on other sites
Skeleton, your little code snippet (when called after I've called SetWallpaper) gives the name of the wallpaper I just set it to. So, it looks like a case of what happened before when I was using SystemParametersInfo. It just looks like the system doesn't know to update the wallpaper.

##### Share on other sites
I just realized I hadn't included IActiveDesktop::ApplyChanges () in my posted code.
Quote:
 There maybe something wrong though, I have no compiler to check right now...

pActiveDesktop -> ApplyChanges (AD_APPLY_ALL) ;

This should work for you now, sorry.

Btw, if we select a JPEG as wallpaper then call GetWallpaper (), we'll see that the temporary bitmap is stored at
[WinPart]:\Documents and Settings\[UserName]\Local Settings\Application Data\Microsoft\Wallpaper1.bmp

##### Share on other sites
Success!!

Thanks for all your help Skeleton.