Tutorial 163: The Guide — message boxes, keyboard input and system pages

CNA Tutorials  ·  CNA snapshot b0e97bb1

ℹ

What you’ll learn: how to show message boxes and keyboard input and finish them correctly, which Guide::Show* pages need a server account, how the Guide owns input while visible, and how to pause the game meanwhile.

ℹ

Status: the Guide works offline, with local profiles, and with a server; only its social pages need a server account. The code follows CNA’s headers at snapshot b0e97bb1 and was not compiled or run for this page. It assumes the setup from Tutorial 162: a GamerServicesComponent and a GraphicsDeviceManager.

What the Guide is in CNA

On the Xbox 360 the Guide was the console’s own UI, drawn over the game: sign-in, message boxes, the on-screen keyboard, friends and messages. XNA games reached it through the static Guide class. CNA draws that UI itself. When the game has a GamerServicesComponent and a graphics device service, the component installs an overlay that draws the Guide after the game’s own Draw and reads its input from the keyboard, the controllers and the mouse. Every standard Guide::Show* call opens a real page after XNA’s argument checks.

The look is CNA’s own visual language, not a copy of the console’s. Quiet system sounds synthesized by CNA play while a player drives it (CNA_GAMER_SERVICES_SOUNDS=0 turns them off), and CNA_GAMER_SERVICES_REDUCED_MOTION=1 removes its short animations. After it draws, the Guide restores the game’s blend, depth-stencil, rasterizer and first sampler states, so a game’s next frame is not affected by it.

1. Ask a question with a message box

BeginShowMessageBox shows one to three buttons. The title and text must be non-empty and shorter than 256 characters; focusButton is the button selected first. The Begin call returns an IAsyncResult that the caller owns; keep it, check it in Update, and call EndShowMessageBox once it has completed:

#include "Microsoft/Xna/Framework/GamerServices/Guide.hpp"
#include "Microsoft/Xna/Framework/GamerServices/MessageBoxIcon.hpp"
#include <memory>
#include <optional>

using namespace Microsoft::Xna::Framework;
using namespace Microsoft::Xna::Framework::GamerServices;

std::unique_ptr<System::IAsyncResult> quitBox_;   // member: the game owns the result

void MyGame::AskToQuit()
{
    if (quitBox_ || Guide::getIsVisibleProperty()) return;   // one Guide screen at a time
    quitBox_.reset(Guide::BeginShowMessageBox(PlayerIndex::One, "Quit",
        "Leave the game? Unsaved progress is lost.", {"Quit", "Keep playing"},
        1, MessageBoxIcon::Warning, {}, {}));   // no callback, no state
}

void MyGame::PollQuitBox()   // call from Update, after Game::Update(gameTime)
{
    if (!quitBox_ || !quitBox_->getIsCompletedProperty()) return;
    const std::optional<int> choice = Guide::EndShowMessageBox(quitBox_.get());
    quitBox_.reset();
    if (choice && *choice == 0) Exit();   // empty: cancelled with Escape, B or Back
}

Players answer with the mouse, with the arrows, Tab, the D-pad or the left stick to move and Enter, Space or A to choose, or cancel with Escape, B or Back. A cancelled box returns an empty std::optional. CNA shows one message box at a time, and any controller may answer it; the overload without a PlayerIndex shows it for player one.

2. Ask for text, including passwords

BeginShowKeyboardInput shows a title, a description and a text field that starts with defaultText; Enter confirms and Escape cancels. The same ownership rule applies. CNA’s own Guide code uses the callback form and takes ownership inside the callback, which is equally valid:

void MyGame::AskForName()
{
    (void)Guide::BeginShowKeyboardInput(PlayerIndex::One, "Pilot name", "Up to 15 letters", pilotName_,
        [this](System::IAsyncResult& result) {
            std::unique_ptr<System::IAsyncResult> owned(&result);   // the callback owns it now
            if (Guide::WasKeyboardInputCanceledEXT(&result)) return;  // CNAEXT, see below
            pilotName_ = Guide::EndShowKeyboardInput(&result);
        },
        {});
}

XNA returned null from EndShowKeyboardInput on cancel; a C++ std::string cannot, so cancelling returns an empty string and the CNA extension WasKeyboardInputCanceledEXT tells a cancel from an empty confirmation. The overload with a trailing bool usePasswordMode shows one * per typed character; the returned text is always the real text, so password mode protects the screen, not the string in memory. Text the player types arrives through CNA’s text-input events, so every UTF-16 code unit is accepted. Title, description and default text must each be shorter than 256 characters.

How End calls wait

XNA’s End methods wait for the answer. CNA keeps that contract without freezing the screen: an End call made before the player has answered runs modal frames: the Guide keeps drawing and reading input while the game’s own Update and Draw are suspended until the answer arrives. If no running game can present the Guide — a call from a tool without a Game, for example — End throws InvalidOperationException instead of hanging. Each result can be ended once.

⚠

Do not wait on the result’s wait handle. The handle of a message-box or keyboard result is already signalled while the answer is still pending, and a loop that pumps GamerServicesDispatcher::UpdateAsync() until IsCompleted never ends, because the answer comes only from the Guide drawn in the game’s frames (CNA-BUG-050). Poll getIsCompletedProperty() from Update, use the callback, or call End and let it run the modal frames.

3. The system pages

All Show calls throw GuideAlreadyVisibleException while another Guide screen is up, so check Guide::getIsVisibleProperty() first. What each one needs:

CallOpensNeeds
ShowSignIn(panes, false)The sign-in picker, for 1, 2 or 4 playersNothing: local profiles offline, accounts with a server
ShowSignIn(panes, true)Account sign-in; later players may join as guests of the first accountA server (GamerServicesNotAvailableException otherwise)
ShowFriends, ShowFriendRequest, ShowGamerCardFriends and requests; a gamer card with join, invite, message, review, mute, friend and block actionsA server account for that player
ShowMessages, ShowComposeMessageRead, reply, delete; compose a messageA server account
ShowGameInvite(player, recipients)Invite gamers to the current online session (an empty list asks for a gamertag)A server account and an online session (InvalidOperationException without one)
ShowParty, ShowPartySessions, ShowPlayers, ShowPlayerReviewParty, party members’ games, recent players, player reviewA server account
ShowAchievementsEXT (CNAEXT)The player’s achievements in this titleA server account
ShowMarketplaceThe Game content page: the title’s licence and the installed avatar catalogs; there is no storeAn account allowed to purchase (GamerPrivilegeException otherwise)
ShowGameInvite(sessionId)—Always NotSupportedException, as in XNA outside Windows Phone

The social pages and what they do with a server are covered in Tutorial 165.

4. The Guide button, input ownership and pausing

In a game that draws, the Home key (as in Games for Windows LIVE) or a controller’s Guide button opens the system Guide for that player without any call from the game, and the same button closes it. With nobody signed in on that controller it shows the sign-in picker; otherwise it shows the player’s portrait, gamertag, score and status and a rail of pages — Home, Friends, Party, Messages, Achievements, Leaderboards, Recent players, Game content and Settings — with Edit avatar opening CNA’s avatar editor. A game that needs the Home key for itself sets CNA_GAMER_SERVICES_GUIDE_BUTTON=0.

While any Guide screen is visible, the Guide owns the input: the game reads a neutral keyboard, controllers with no buttons pressed and sticks and triggers centred, and no mouse buttons (the pointer and wheel still move). Input held when the Guide closes stays hidden from the game until it is released, so the Enter that closed a dialog does not also fire the game’s menu. The game keeps running, though, so pause the simulation yourself:

void MyGame::Update(GameTime& gameTime)
{
    Game::Update(gameTime);   // the Guide's work and pending completions happen here
    PollQuitBox();

    if (Guide::getIsVisibleProperty())   // a message box, keyboard, sign-in or system page is up
    {
        paused_ = true;                  // stop timers, AI and physics; input reads neutral anyway
        return;
    }
    // ... gameplay ...
}

getIsVisibleProperty() throws InvalidOperationException before gamer services are initialized, so call it from Update, not from the constructor.

5. Notifications and trial mode

  • Toasts appear at Guide::setNotificationPositionProperty(...) (default NotificationPosition::BottomCenter): “Achievement unlocked” when an achievement is awarded, offline too, and, with a server, new messages, friend requests, friends coming online and invitations. Guide::DelayNotifications(delay) holds back the Guide’s game-invitation prompts for up to 120 seconds, for example during a cutscene.
  • Trial mode. CNA titles are fully licensed. getIsTrialModeProperty() is true until gamer services first update and then follows setSimulateTrialModeProperty(...) as it was at each update, as in XNA. While a title simulates trial mode, the Game content page offers XNA’s Test Purchase, which ends the simulation; reaching that page through ShowMarketplace needs a server account.

Games without the component

A program that initializes GamerServicesDispatcher itself, without a GamerServicesComponent, has no overlay. It can still show a message box or keyboard prompt by calling the CNA extensions Guide::RenderPendingMessageBoxEXT and Guide::RenderPendingKeyboardInputEXT once per frame after drawing its scene, inside a SpriteBatch it has begun; they draw the pending dialog and read its input. The full system Guide, sign-in and toasts need the component.

Evidence and qualification

  • CNA’s final audit run of this work (2 October 2026, Linux): the GamerServices suite 649 passed and the Net suite 524 passed, with no failures; the server’s 40 registered tests: 33 passed, 7 network-isolation tests skipped for lack of a test tool, none failed. The GamerServices suite contains the Guide’s UI, input-ownership, render-state and system-Guide tests. These are CNA-recorded runs; this site did not re-run them.
  • The Guide’s sounds reached a real output device in CNA’s check, but nobody listened to them: how they sound is unverified.
  • Not qualified: Windows and macOS (Guide input there was not exercised), a real wide-area network with NAT, voice on physical audio devices, and avatar pixels on Direct3D and Metal.
  • Browser builds include the Guide and local profiles; they have no service, relay or voice, so the server-account pages are unavailable there.

Next

Tutorial 164 connects the game to a CNA Gamer Services server so players can sign in with accounts. Back to Tutorial 162 for local profiles, or to the Gamer Services overview.