Monday, February 23, 2009

Receiving/loosing the focus (WM_ACTIVATE) on Windows Mobile

When DirectX application is running in full screen (DDSCL_FULLSCREEN) it does not receive any focus changed events, namely WM_ACTIVATE message.

As stated in
"...The exclusive (full-screen) mode prevents other applications from allocating some surface types and from drawing to the primary display. The exclusive mode also prevents other windows on the system from coming to the foreground, so DirectDraw applications must watch for system events (such as incoming phone calls) so they can relinquish control back to the system when necessary..."

The possible solution for that is discussed here
"...My solution is not to use DDSCL_FULLSCREEN cooperative level. Use DDSCL_NORMAL..."

Another related link is Sludge said here:
"...When opening a full screen application, there is no way to receive focus change events. For example on the HTC Touch, screen elements aren't drawn correctly when a phone call comes in, or the volume buttons are used..."

t looks that couple of people has problems with not receiving the WM_ACTIVATE message. In order to receive WM_ACTIVATE message the DirectX cooperative level has to be set to DDSCL_NORMAL, not DDSCL_FULLSCREEN.

This looks fine, but it introduces another problem as written here

"…Processes in NORMAL mode can access primary surfaces but are restricted with regard to flipping, creating complex primaries, and setting display modes…"

On older devices like HTC Wizard(Qtek 9100) where the
HW flipping is not supported it is fine but on e.g. HTC Kaiser when using the NORMAL mode, the application crashes when the primary surface is initialized with the error DDERR_NOCOOPERATIVELEVELSET. This is because the HTC Kaiser supports HW flipping, which is detected, and I try to use it, but this is unfortunately not possible in the DDSCL_NORMAL mode. So I have to choose - either try to be phone friendly and handle the WM_ACTIVATE or be game friendly and use the HW flipping…

The application can loose focus from many reasons, e.g. receiving the call, message, Bluetooth transfer, alarm event, calendar notification, going to sleep mode. Even if I receive the WM_ACTIVATE message I need to follow the complex handling:
  • I call ShowWindow() with SW_HIDE
  • The game loop is interrupted and application is chilled with the GetMessage()
  • After the situation is handled (e.g. call) and the user starts the application again, new process is created.
  • I use the FindWindow() to detect such situation and when I found existing window I set it to foreground by calling SetForegroundWindow() and I exit the new instance
Is there some easier way how to handle it? I'm really pretty new, do I something badly?

Anyway if some Win CE platform developers want to see how to handle such situations in an elegant way - check the DSA (Direct Screen Access) approach used on Symbian platform

Every comment welcomed!!

No comments:

Post a Comment