SystemParametersInfo - C/C++

Started by
15 comments, last by Endar 18 years, 4 months ago
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.
[size="2"][size=2]Mort, Duke of Sto Helit: NON TIMETIS MESSOR -- Don't Fear The Reaper
Advertisement
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.
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);
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?
[size="2"][size=2]Mort, Duke of Sto Helit: NON TIMETIS MESSOR -- Don't Fear The Reaper
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.
--> The great thing about Object Oriented code is that it can make small, simple problems look like large, complex ones <--
Any idea how to maybe call a function that will be recognized by Active Desktop?
[size="2"][size=2]Mort, Duke of Sto Helit: NON TIMETIS MESSOR -- Don't Fear The Reaper
I'm begin searching... I will reply as soon as I can.
Good luck.
--> The great thing about Object Oriented code is that it can make small, simple problems look like large, complex ones <--
Here you go: IActiveDesktop::SetWallpaper () ^_^
--> The great thing about Object Oriented code is that it can make small, simple problems look like large, complex ones <--
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.
[size="2"][size=2]Mort, Duke of Sto Helit: NON TIMETIS MESSOR -- Don't Fear The Reaper
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...
--> The great thing about Object Oriented code is that it can make small, simple problems look like large, complex ones <--

This topic is closed to new replies.

Advertisement