Join Now
Quality Rating:
  • Currently 0.0 / 5
(0.0 / 5 - 0 votes cast)
Expertise Level:
  • Currently 0.0 / 5
(0.0 / 5 - 0 votes cast)

This page was last modified 17:07, 23 June 2008.

How to read key-input in console applications

From Forum Nokia Wiki

This code-snippet show how you can get user input in your console applications – this can be very handy for e.g. implementing a small menu and for simple testing purposes.

We’ll be using the following three functions from the CConsoleBase class:

  • void Read(TRequestStatus) - issues an asynchronous request, waiting for the user to press a key.
  • TKeyCode KeyCode() – return the TKeyCode corresponding to the key pressed.
  • void ReadCancel() – cancels a pending Read request.

As you can see the Read(TRequestStatus) function is an asynchronous function to utilize it probably we need to wrap it in an active object.

The following code snippet shows you how this could implemented in a CKeyInput class (note, error handling and such are not implemented).

KeyInput.h

#ifndef KEYINPUT_H
#define KEYINPUT_H
 
#include <e32base.h>
#include <e32keys.h>
 
 
class MKeyInputObserver
    {
public:
    virtual TBool ProcessKeyPress(TKeyCode aKey) = 0;
    };
 
// Forward declaration
class CConsoleBase;
 
class CKeyInput : public CActive
    {
public:
    static CKeyInput* NewL(CConsoleBase *aBase, MKeyInputObserver *aObserver);
    static CKeyInput* NewLC(CConsoleBase *aBase, MKeyInputObserver *aObserver);
 
    void GetKeyPress();
    void Stop();
    ~CKeyInput();
 
private:
    void ConstructL();
    CKeyInput(CConsoleBase *aBase, MKeyInputObserver *aObserver);
 
private: // From CActive
    void RunL();
    void DoCancel();
    TInt RunError(TInt aError);
 
 
private:
    CConsoleBase *iBase;
    MKeyInputObserver *iObserver;
 
    };
 
 
#endif

As you can see we’re using the observer pattern to propagate incoming key-presses back to an observer of the type MKeyInputObserver, the observer will have to implement the MKeyInputObserver::ProcessKeyPress() function. The observer will also be determining whether the CKeyInput active object should continue reading key input. If the observer returns ETrue from the ProcessKeyPress function the CKeyInput class will continue and issue another read request, if the observer returns EFalse this signals the CKeyInput class that no more input should be read. To see how this is implemented let’s take a look at the CKeyInput class declaration:

KeyInput.cpp

#include "KeyInput.h"
#include <e32cons.h>            // Console
 
CKeyInput* CKeyInput::NewL(CConsoleBase *aBase, MKeyInputObserver *aObserver)
    {
    CKeyInput *self = CKeyInput::NewLC(aBase, aObserver);
    CleanupStack::Pop(self);
    return self;
    }
 
CKeyInput* CKeyInput::NewLC(CConsoleBase *aBase, MKeyInputObserver *aObserver)
    {
    CKeyInput *self = new (ELeave) CKeyInput(aBase, aObserver);
    CleanupStack::PushL(self);
    self->ConstructL();
    return self;
    }
 
void CKeyInput::GetKeyPress()
    {
    iBase->Read(iStatus);
    SetActive();
    }
 
CKeyInput::~CKeyInput()
    {
    Cancel();
    }
 
void CKeyInput::ConstructL()
    {
    }
 
CKeyInput::CKeyInput(CConsoleBase *aBase, MKeyInputObserver *aObserver) : 
    CActive(EPriorityStandard), iBase(aBase), iObserver(aObserver)
    {
    CActiveScheduler::Add(this);
    }
 
void CKeyInput::RunL()
    {
    User::LeaveIfError(iStatus.Int());
 
    TKeyCode keyCode = iBase->KeyCode();
    TBool cont = iObserver->ProcessKeyPress(keyCode);
    
    if((int)ETrue == cont)
        {
        iBase->Read(iStatus);
        SetActive();
        }
 
    }
 
void CKeyInput::DoCancel()
    {
    iBase->ReadCancel();
    }
 
TInt CKeyInput::RunError(TInt aError)
    {
    // Implement error handling
    return KErrNone;
    }

Now we’ve done all the groundwork all that’s left is to take advantage of our band new key-input reader class. For a simple example we first need at class working as an observer of our CKeyInput class e.g.


class CConsoleAS : public CBase, public MKeyInputObserver
    {
public:
    static CConsoleAS* NewLC();
    static CConsoleAS* NewL();
    ~CConsoleAS();
    void PrintMenu();
 
 
private:   
    CConsoleAS();
    void ConstructL();
 
private: // From MKeyInputObserver
    TBool ProcessKeyPress(TKeyCode aKey);
 
    };
 
CConsoleAS* CConsoleAS::NewLC()
    {
    CConsoleAS *self = new (ELeave) CConsoleAS;
    CleanupStack::PushL(self);
    self->ConstructL();
    return self;
    }
 
 
CConsoleAS* CConsoleAS::NewL()
    {
    CConsoleAS *self = CConsoleAS::NewLC();
    CleanupStack::Pop(self);
    return self;
    }
 
 
CConsoleAS::~CConsoleAS()
    {
 
    }
 
 
CConsoleAS::CConsoleAS()
    {
    }
 
 
void CConsoleAS::ConstructL()
    {
 
    }
 
 
TBool CConsoleAS::ProcessKeyPress(TKeyCode aKey)
    {
    _LIT(KPrint, "%d");
    console->Printf(KPrint, aKey);
    if(aKey < 92)
        {
        // consume
        return ETrue;
        }
     
    switch(aKey) 
        {
        case 92: // 1
            {   
            CActiveScheduler::Stop();
            return EFalse;
            }
        case 97: // 2
            {
            console->Printf(_L("Hello world!"));
            return ETrue;
            }
        case 100: // 3
            {
            console->Printf(_L("Why oh why, world?"));
            return ETrue;
            }
        default:
            {
            _LIT(KUnknown, "Err unkown command\n");
            console->Printf(KUnknown);
            PrintMenu();
            return ETrue;
            }
        }  
    }
 
 
void CConsoleAS::PrintMenu()
    {
    _LIT(KExit, "(1) Exit\n");
    console->Printf(KExit);
    _LIT(KStartServer, "(2) Start server\n");
    console->Printf(KStartServer);
    _LIT(KStartClient, "(3) Start client\n");
    console->Printf(KStartClient);
    }


This class could be used in a simple console application, such as the ones created by the Application Wizards in the following way:

LOCAL_C void MainL()
    {
 
    CConsoleAS *driver = CConsoleAS::NewLC();
    driver->PrintMenu();
    CKeyInput *keyInput = CKeyInput::NewLC(console, driver);
    keyInput->GetKeyPress();
    CActiveScheduler::Start();
 
    CleanupStack::PopAndDestroy(2); // CConsoleAS, CKeyInput
 
    }
Related Discussions
Thread Thread Starter Forum Replies Last Post
how to automate makekeys process? chenloong Symbian Tools & SDKs 5 2007-07-30 02:26
encypting data to be sent using HTTP (MIDP 1.0) dihex Mobile Java Networking & Messaging & Security 7 2005-10-27 20:16
Why can't get reference to Printf() wuxiang00 General Symbian C++ 2 2004-09-08 10:42
exe sends event to app ebinder General Symbian C++ 4 2003-10-17 10:26
key pad issue sandy_zeng General Symbian C++ 1 2007-12-26 04:42
 
Powered by MediaWiki
     
     RDF Facets:
     
     
     qfnZtypeQUqfnTypeZCommunityContentQ
     qfnZtypeQUqfnTypeZWebpageQ
     qfnZtypeQUqfnTypeZWikiContentQ
     qmarsZlanguageQUxhttpE3aE2fE2fswE2enokiaE2ecomE2flanguageE2d1E2fenX