Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Changing Device Wallpaper in Background

28 views
Skip to first unread message

Sunil Garg

unread,
May 7, 2007, 2:58:23 AM5/7/07
to
I am trying to change the wallpaper of the home screen by

1. resetting the value of BgImage in HKEY_CURRENT_USER\ControlPanel
\Home to the location of the new wallpaper file
2. Win32Window.SendMessage((IntPtr)HWND_BROADCAST, WM_WININICHANGE,
SPI_SETDESKWALLPAPER, 0);

It seems that this succeeds, but the desktop is not redrawn until all
applications are minimized (e.g., the desktop is displayed as the top
level application) and the device is not idle. This is not ideal
behavior, however, as Windows takes control of the device while
refreshing the wallpaper, making the phone unusable for a few seconds.

I want to change the wallpaper without interrupting the user of the
phone (e.g., while the device is idle and regardless of whether or not
the desktop is the top level application), yet it does not seem like
this is feasible. Any ideas on how to trigger the redraw so that the
user will never be forced to wait for the change to complete?

Thanks.

Paul G. Tobey [eMVP]

unread,
May 7, 2007, 12:06:16 PM5/7/07
to
The wallpaper *is* what is drawn behind the Today screen. It has no meaning
that would cause it to be redrawn when some other window is in front of the
today screen.

As far as limiting the effect of the change itself, you could just send the
INI change message to the desktop window, I guess. That's probably the only
application that cares about it.

Paul T.

"Sunil Garg" <su...@sunilgarg.com> wrote in message
news:1178521103....@p77g2000hsh.googlegroups.com...

jonfroehlich

unread,
May 7, 2007, 4:38:22 PM5/7/07
to
Paul,

I have run into this issue as well. I believe what Sunil meant is
*not* that the redraw is problematic (i.e., of course drawing an image
behind the today screen is painless and fast) but rather when the INI
change message is received, the new image is *not* applied until the
desktop is visible. In other words, broadcasting the INI message is
fast (and not the cause of overhead I don't believe)--it's that the
actual change in desktop wallpaper does not happen until the desktop
becomes visible (which could be N minutes after the INI message was
sent). This can cause some interesting UI issues. For example, I end a
phone call, the phone app minimizes, the desktop becomes top level and
suddenly I lose control of my phone for 15-30 seconds while the
background changes. Very disconcerting indeed! Alternatively, forcing
a background change while the device is idle and the desktop is or is
not visible would be preferred.

You can check the "changing wallpaper" overhead for yourself. Open
Settings->Homescreen->Background Image. Note that the background image
is *not* set until the desktop becomes visible for the first time.

Jon

On May 7, 9:06 am, "Paul G. Tobey [eMVP]" <p space tobey no spam AT no


instrument no spam DOT com> wrote:
> The wallpaper *is* what is drawn behind the Today screen. It has no meaning
> that would cause it to be redrawn when some other window is in front of the
> today screen.
>
> As far as limiting the effect of the change itself, you could just send the
> INI change message to the desktop window, I guess. That's probably the only
> application that cares about it.
>
> Paul T.
>

> "Sunil Garg" <s...@sunilgarg.com> wrote in message

Paul G. Tobey [eMVP]

unread,
May 8, 2007, 1:04:25 PM5/8/07
to
I suppose that you could get the top-level window of the today screen
application, mark its entire content area as invalid (InvalidateRect()), and
then force it to update, UpdateWindow(). You'd have to P/Invoke those, of
course.

Paul T.

"jonfroehlich" <jonfro...@gmail.com> wrote in message
news:1178570302.9...@h2g2000hsg.googlegroups.com...

jonfroehlich

unread,
May 8, 2007, 6:16:28 PM5/8/07
to
Yep. My current approach is to:

1. Wait until device goes idle for N minutes
2. Wake up device
3. Set a new background
4. Invalidate the desktop (the entire today screen) and force it to
update. I was doing this by trying to minimize any open applications
but this was a hack.
5. Put the device back into idle state

An awful lot of work just to change the desktop wallpaper. Does anyone
have any sense as to why it takes so long?

j

On May 8, 10:04 am, "Paul G. Tobey [eMVP]" <p space tobey no spam AT


no instrument no spam DOT com> wrote:
> I suppose that you could get the top-level window of the today screen
> application, mark its entire content area as invalid (InvalidateRect()), and
> then force it to update, UpdateWindow(). You'd have to P/Invoke those, of
> course.
>
> Paul T.
>

> "jonfroehlich" <jonfroehl...@gmail.com> wrote in message

Deasun

unread,
Jul 13, 2007, 10:02:05 AM7/13/07
to
Hello there,
Would you mind showing the code to do the wallpaper changing?
I have been try to do this for some time now but I am not finding much docs
on it.
Its driving me nuts.
{VB/C# .NET code would be best, but I will take anything at this point :)}

Thanks
--
Deasun
Home Site: www.tirnaog.com
Check out: The Code Vault in my forums section.

jonfroehlich

unread,
Jul 15, 2007, 7:04:08 PM7/15/07
to
Hi Deasun,

A majority of the generalizable C# code I write for Windows Mobile has
been open sourced at SourceForge in a project called Roam (http://
www.sourceforge.net/projects/roam). The code to programatically switch
wallpaper is found in the DesktopUtils.cs file. Here is a direct link:
http://roam.svn.sourceforge.net/viewvc/roam/Trunk/Source/Roam.UI/Utils/DesktopUtils.cs?revision=73&view=markup
You can download the entire Roam project via SVN. The license is BSD
so feel free to incorporate any of the code in your project :)

Jon

---
http://csharponphone.blogspot.com

Deasun

unread,
Jul 16, 2007, 10:22:03 AM7/16/07
to
Thanks very much for the code view.
I was very close to what you have there.
Using your registry code line I can now update that value.
The Sendmessage line is still not co-opperating with me.
Here is a clean version of the current code I am now using.

Running in debug mode in VS.net 2005.
Emulating PocketPc WM 5.0

At time of error on the "Sendmessage" line, varible values are;
strKeyName = "HKEY_CURRENT_USER\ControlPanel\Home"
strValueName = BgImage
strWallpaperImageIs = "\\windows\\Guava bubbles.tsk"

HWND_BROADCAST = 65535
SPIF_SENDWININICHANGE = 2
SPI_SETDESKTOPWALLPAPER = 20

Registry Key values:
[Microsoft.Win32.Registry.CurrentUser.OpenSubKey("ControlPanel").OpenSubKey("Home").GetValue("BgImage")]
Using
[objRegistryKey.OpenSubKey("ControlPanel").OpenSubKey("Home").GetValue("BgImage")] to view it value.
Before: "\\windows\\Guava bubbles_Before.tsk"
After: "\\windows\\Guava bubbles.tsk"

Error Msg on executing the Sendmessage line: NotSupportedException

#Region " Area: Imports"
Imports System.IO 'To read the windows folder for .tsk files
Imports System.Runtime.InteropServices 'For the wallpaper changing API
interface
#End Region

Public Class WPMaster_PPC

#Region " Area: Application wide variables "
'Wallpaper changing API
Public Shared SPI_SETDESKTOPWALLPAPER As Integer = 20
Public Shared SPIF_SENDWININICHANGE As Integer = 2
Public Shared HWND_BROADCAST As IntPtr = IntPtr.op_Explicit(&HFFFF)

#End Region

'<DllImport("coredll.dll")>
Private Declare Function SendMessage Lib "coredll.dll" Alias
"SendMessage" (ByVal hWnd As IntPtr, ByVal Msg As System.Int32, ByVal wParam
As System.Int32, ByVal lParam As System.Int32)

Private Sub WPMaster_PPC_Load(ByVal sender As Object, ByVal e As
System.EventArgs) Handles MyBase.Load
Dim strWhoAmI As String = msApplication & "." & msVersion & "." &
msFormOn & ".WPMaster_PPC_Load"
Try
initThemeListBox(strWhoAmI)
SetTheWallpaper(strWhoAmI)
Catch ex As Exception

End Try
End Sub

#Region " Area: Sub Procedures "

Private Sub initThemeListBox(ByVal strWhoCalledMe As String)
Dim strWhoAmI As String = msApplication & "." & msVersion & "." &
msFormOn & ".initThemeListBox"
Try
Dim intFilesInFolder As Integer =
Directory.GetFiles("\Windows\", "*.tsk").Length
Dim intIndex As Integer = 0

While (intIndex < intFilesInFolder)
Dim strFileName As String = Directory.GetFiles("\Windows\",
"*.tsk").GetValue(intIndex)
strFileName = StrReverse(strFileName)
strFileName = strFileName.Substring(0,
(strFileName.IndexOf("\")))
strFileName = StrReverse(strFileName)

Dim objTheme As New ListViewItem
With objTheme
.Text = strFileName
End With
With lstBoxThemes
.Items.Add(objTheme.Text)
End With
intIndex += 1
End While

Catch ex As Exception

End Try
End Sub

Private Sub SetTheWallpaper(ByVal strWhoCalledMe As String)
Dim strWhoAmI As String = msApplication & "." & msVersion & "." &
msFormOn & ".SetTheWallpaper"

Dim strKeyName As String = "HKEY_CURRENT_USER\ControlPanel\Home"
Dim strValueName As String = "BgImage" ' "Wallpaper" 'Skin
Dim objRegistryKey As Microsoft.Win32.RegistryKey
Dim strWallpaperImageIs As String = "\\windows\\Guava bubbles.tsk"

Try

objRegistryKey.SetValue(strKeyName, strValueName,
strWallpaperImageIs)
SendMessage(HWND_BROADCAST, SPIF_SENDWININICHANGE,
SPI_SETDESKTOPWALLPAPER, 0)

Catch ex As Exception

End Try
End Sub

#End Region

End Class

Paul G. Tobey [eMVP]

unread,
Jul 16, 2007, 12:19:02 PM7/16/07
to
I think that you've got a problem with your P/Invoke declaration. I'm not
much on VB, but you might try removing the DllImport attribute, as you've
already indicated the DLL. The actual problem, though, is that
SendMessage(), in Windows CE, ends up being SendMessageW, not SendMessage,
because CE is Unicode-based and the naming appends a W to Unicode calls.
So, instead of Aliasing to "SendMessage", Alias to "SendMessageW", and I
think it will work.

Paul T.

"Deasun" <Dea...@discussions.microsoft.com> wrote in message
news:52F56625-BF0F-4A8F...@microsoft.com...

Deasun

unread,
Jul 16, 2007, 1:38:02 PM7/16/07
to
Thanks for all the help ye have both given me.

No luck yet. I tried changing the alias to SendMessageW but I got the same
error message back.
NotSupportedException on trying to execute the SendMessage line.


--
Deasun
Home Site: www.tirnaog.com
Check out: The Code Vault in my forums section.

Paul G. Tobey [eMVP]

unread,
Jul 16, 2007, 1:55:24 PM7/16/07
to
And it's definitely *that* call that's triggering the exception? Shouldn't
you specify the return type of the function? Or the fact that it's a static
(doesn't) operate on an object instance? I don't know enough about VB.NET
to know for sure; just thinking about how it would be declared in C#.

Paul T.

"Deasun" <Dea...@discussions.microsoft.com> wrote in message

news:76DD0086-A116-41C4...@microsoft.com...

Deasun

unread,
Jul 16, 2007, 2:26:06 PM7/16/07
to
Yep, in the debugger once that line is highlighted and I press F10 I get the
message.
I have tried the Snedmessage functions as a Integer and a system.int32 type,
as well as blank.
Getting despparate, trying all sorts of daft stuff.

On the As integer/system.int32 the line executes with out error but the PPC
itself locks up completely.

Paul G. Tobey [eMVP]

unread,
Jul 16, 2007, 2:42:32 PM7/16/07
to
SendMessage won't return until *all* windows that you send the message to
have handled the message, so I think that's the right declaration and that
you have some window holding things up, perhaps you. You might use
PostMessage, instead, as that just drops the message in the message queue
for each window and has lower probability of causing your sending thread
problems.

Paul T.

"Deasun" <Dea...@discussions.microsoft.com> wrote in message

news:7D1421A5-9ECF-4B4B...@microsoft.com...

Deasun

unread,
Jul 16, 2007, 2:58:01 PM7/16/07
to
I tried the postmessage too and it locks up the PPC as well.
Is there a resource I can readup on the SendMessage and PostMessage syntax?
Just not 100% sure i have the right VB declarations for it.
Values for those parameters and such. Writing this little tool for the PC
desktop was easy compare to this.

Paul G. Tobey [eMVP]

unread,
Jul 16, 2007, 3:24:58 PM7/16/07
to
The native code help from the PPC SDK would have the real documentation.
The calls are pretty much identical to their counterparts on the desktop PC,
though. I've done a wallpaper changer in native code with no problems; the
likely cause is something to do with your declarations.

Paul T.

"Deasun" <Dea...@discussions.microsoft.com> wrote in message

news:96BBF06B-9E5D-46A3...@microsoft.com...

Deasun

unread,
Jul 16, 2007, 4:26:01 PM7/16/07
to
Ya i think the Send message is not set up correctly with the values in the
parameter section.
I now have the following with passes the code lines without error and does
not lock the PPC.
But of course it does nothing. :(

Where can I find a list of the valid parameter values SendMessage takes,
with possibly a description of what they do?
MSDN does not seem to have the list, or I am putting in the wrong search
criteria.

Thanks again for the help.

Deasun

unread,
Jul 16, 2007, 4:28:05 PM7/16/07
to
ahh the code would be nice to give.

Public Shared SPI_SETDESKTOPWALLPAPER As Integer = 20

Public Shared WM_WININICHANGE As Integer = 2

Declare Function SendMessage Lib "coredll.dll" (ByVal hWnd As IntPtr, ByVal
Msg As Integer, ByVal wParam As Integer, ByVal lParam As Integer) As IntPtr
Private Declare Function GetDesktopWindow Lib "coredll.dll" Alias
"GetDesktopWindow" () As Integer

Dim hWnd As Integer
hWnd = GetDesktopWindow()
SendMessage(hWnd, WM_WININICHANGE, SPI_SETDESKTOPWALLPAPER, 0)

I am pretty sure the hWnd is now the correct value.
But the WININICHANGE and SPI_SETDESKTOPWALLPAPER values are questionable.

Paul G. Tobey [eMVP]

unread,
Jul 16, 2007, 4:42:07 PM7/16/07
to
The list would be too long to list and is dependent on what windows that
might receive a given message are willing to accept. It's like saying,
"What are the valid parameter values for the 'plus' operator?" You could
pass an integer of any value and a floating point number of any value, for
example. As long as 'plus' is willing to deal with those items, it's valid.

Anyway, I don't, of course, have the source for the Windows Mobile shell,
but what you're sending there doesn't match what the generic Windows CE
shell would expect when a wallpaper change occurred. It's looking for
something more like:

SendMessage( HWND_BROADCAST, WM_SETTINGCHANGE, SPI_SETDESKWALLPAPER, 0 )

I can't say that what you're doing is wrong, but you might try adding
something like the code above to the changed case and see if that works
better...

Paul T.

"Deasun" <Dea...@discussions.microsoft.com> wrote in message

news:635BD8F2-557C-4462...@microsoft.com...

Paul G. Tobey [eMVP]

unread,
Jul 16, 2007, 4:43:24 PM7/16/07
to
WM_WININICHANGE is *not* 2. It's 0x1a. Where are you getting these values
from if not from the C header files? Any other source is likely to be
unreliable...

Paul T.

"Deasun" <Dea...@discussions.microsoft.com> wrote in message

news:3B49BD4D-B259-4070...@microsoft.com...

lisa...@gmail.com

unread,
Jul 30, 2007, 6:10:42 PM7/30/07
to
The code below sets the today screen wallpaper in c# on windows mobile
5. It updates the background image on the today screen and the start
menu. If the image is larger than 240 * 240 it gets cropped.

(tested on .NET Compact Framework 2.0, windows mobile 5, phone
edition, pocket pc device: hp ipaq hw6940 / hw6945)

using System.Runtime.InteropServices;
using Microsoft.Win32;
...
[DllImport("coredll.dll")]
private static extern int SendMessage(IntPtr hWnd, uint msg, int
wParam, int lParam);
...
public const int HWND_BROADCAST = 0xffff;
public const int WM_WININICHANGE = 0x001A;

// Copy wallpaper file to windows directory
File.Copy(@"\My Documents\My Pictures\ImageFileName.jpg", @"\Windows
\stwater_240_240.jpg", true);

// Update registry
Registry.SetValue(@"HKEY_CURRENT_USER\Software\Microsoft\Today",
"Wall", "ImageFileName");

// Send message to refresh today screen
SendMessage((IntPtr)HWND_BROADCAST, WM_WININICHANGE, 0xF2, 0);

0 new messages