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 |
