Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / desktop / Win32

XBOX360 Achievement

4.94/5 (3 votes)
31 Dec 2020GPL33 min read 7K   58  
Display smart messages on the Windows Desktop as XBOX360 achievements
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:

  1. OneTime
  2. StayUntilLeftMouseClick
  3. 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:

C++
#include "MyNotifyControl.h"

//...

// notify control parameters
MY_NOTIFY_CONTROL_PARAMS ncp;
memset(&ncp,0,sizeof(MY_NOTIFY_CONTROL_PARAMS));

// fill achievement parameters
ncp.wszTitle = L"Achievement Title";
ncp.wszText = L"Achievement Text";
ncp.animationType = StayUntilLeftMouseClick;
ncp.wLogoId = IDB_PNG_LOGO1;

// notify control initialization
// send the structure MY_NOTIFY_CONTROL_PARAMS as thread parameters
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!

License

This article, along with any associated source code and files, is licensed under The GNU General Public License (GPLv3)