XBOX360 Achievement is used to display smart messages directly after the start one at a time. The program chooses a random message if no command line argument is specified. If a command line argument is specified, it is used as the index value for the XBOX360 achievement message to display.
Introduction
The code does display a smart message in the form of a XBOX360 achievement notification on the Windows Desktop. It shows how we can animate a layered window on top of the desktop above all other windows.
Background
XBOX360 Achievement is used to display smart messages directly after the start one at a time. The program chooses a random message if no command line argument is specified. If a command line argument is specified, it is used as the index value for the XBOX360 achievement message to display.
There are three possible animation types:
OneTime
StayUntilLeftMouseClick
EndlessLoop
OneTime
is the closest to the original XBOX360 achievement notification. It displays the message one time and exits. StayUntilLeftMouseClick
displays the same message over and over again and for a longer duration, until the user clicks the left mouse button inside the window. EndlessLoop
does the same as OneTime
, but it runs in a never ending loop.
Our binary executable included in this sample is compiled with the animation type StayUntilLeftMouseClick
. You have to click the achievement window with the left mouse to close it. To save some space, we could pack the executable with UPX which will reduce the executable size dramatically. We did not compress it for this sample though.
Using the Code
The code is plain C style stuff. We implemented the complete notification control in the files, MyNotifyControl.h and MyNotifyControl.cpp. Simply include the header file in your main CPP file, initialize the structure MY_NOTIFY_CONTROL_PARAMS
and create a thread with the start routine MyNotifyControlInitThreadProc
in this way:
#include "MyNotifyControl.h"
MY_NOTIFY_CONTROL_PARAMS ncp;
memset(&ncp,0,sizeof(MY_NOTIFY_CONTROL_PARAMS));
ncp.wszTitle = L"Achievement Title";
ncp.wszText = L"Achievement Text";
ncp.animationType = StayUntilLeftMouseClick;
ncp.wLogoId = IDB_PNG_LOGO1;
HANDLE hThread = CreateThread(NULL,0,MyNotifyControlInitThreadProc,&ncp,0,NULL);
Pay attention to the resource IDs. An achievement logo should be 49x49 pixels in size and have a circularity shape with a transparent background. We included three logo examples for reference. The animation logos are also included. You have to set the first animation frame to resource ID 101 and the last frame to 284. All IDs between 101 and 284 are the animation images used for the base achievement message.
Changes Version 1.1
Windows 10 shows a problem with our message loop which does not appear on Windows XP and Server 2003. The call to WaitForSingleObject
blocks all messages until the painting thread is finished. This can lead to a deadlock of the application which result in a Windows 10 message "The program is not responding." If this message appears, we can see our window in the taskbar and the invisible background gets painted black.
We solved this problem by applying the following code changes:
- In
MyNotifyControlFrameThreadProc
, the ShowWindow
parameter SW_SHOW
is replaced by SW_SHOWNOACTIVATE
. - We added a new
MyNotifyControlOnDestroy
handler and placed WaitForSingleObject
in it prior to the PostQuitMessage
call. - We removed the calls to
WaitForSingleObject
and DestroyWindow
from the handler MyNotifyControlOnLButtonDown
, because the WM_CLOSE
message is posted directly from the painting thread to the message loop. - We placed a call to the new handler
MyNotifyControlOnDestroy
in the Windows message loop procedure.
History
- 26th November, 2020 - Initial release
- 31st December, 2020 - Version 1.1
This project is also available at Sourceforge at https://sourceforge.net/projects/xbox360-achievement/.
Have fun with this sample!