Table of Contents: Table of Contents: ______________________________________________________ 2 Introduction ___________________________________________________________ 6 About this Document _________________________________________________ 6 About the SDK API __________________________________________________ 6 Portable Embedded GUI – PEG ___________________________________________ 7 Static PEG Objects ___________________________________________________ 7 The PegPresentationManager __________________________________________ 7 The PegMessageQueue_______________________________________________ 7 The PegScreen _____________________________________________________ 7 The PegThing _______________________________________________________ 8 Traversing the Presentation Tree of PegThings ____________________________ 8...
Page 3
Window and Screen Drawing ____________________________________________ 31 The WindowsExample Add-in_________________________________________ 31 An Overview of Windows in the WindowsExample _______________________ 31 CPMainFrame _____________________________________________________ 31 CPModuleWindow _________________________________________________ 31 CPWindow _______________________________________________________ 31 Windows in WindowsExample________________________________________ 31 Coordinates on the ClassPad __________________________________________ 33 Drawing on the ClassPad _____________________________________________ 34 Overriding the Draw() Function _______________________________________ 34 Invalidating and Drawing outside of the Draw() Method____________________ 35 Drawing and Invalidating in WindowsExample___________________________ 36...
Page 5
ClassPad Character Set ______________________________________________ 94 CP_CHAR and PEGCHAR ___________________________________________ 97 CP_CHAR Functions _______________________________________________ 98 CPString___________________________________________________________ 99 Constructors and Assignment _________________________________________ 99 CPString Comparison ______________________________________________ 100 Useful String Functions ____________________________________________ 100 Buffer Ownership _________________________________________________ 102 String Conversions _________________________________________________ 102 Converting Between CPStrings and Supported C native data types___________ 102 Converting Between CPStrings and BCDs______________________________ 103 Multiple Language Support in the ClassPad ____________________________ 105 Message Number Enumeration_______________________________________ 106...
The purpose of this document is to provide you with a reference guide while programming on the ClassPad 300. This document is not meant to be a tutorial, or a complete list of functions contained in the SDK. Please Refer to SDK Programming Tutorial for a tutorial on working from a “Hello World”...
Portable Embedded GUI – PEG The ClassPad’s user interface classes are all based on the Portable Embedded GUI system, or PEG. In this section we will give a broad overview of PEG. This will include a detailed look at the PegThing, the class on which all viewable objects are based. We will also look at how PEG uses the PegPresentationManager to store these viewable components in memory.
between the video hardware and the rest of the PEG library, which is required to insure that PEG is easily portable to any target environment. The PegThing The most important and fundamental class in the PEG library is the PegThing. PegThing is the base class from which all viewable PEG objects are derived.
Page 9
PegPresentationManager PegWindow1 PegPrompt1 PegPrompt2 PegButton PegWindow2 PegCheckBox PEG provides the following functions to access and traverse this tree structure: PegThing* PegThing::Parent(void); PegThing* PegThing::First(void); PegThing* PegThing::Next(void); PegThing* PegThing::Previous(void); Their use can best be explained using a close up view of a portion of the previous tree diagram: Next() PegWindow2...
PegPresentationManager. Next() would return PegWindow2. Since all lists are terminated with a NULL, Previous() would return NULL. So, if we wanted traverse all of the children of an object, we could use the following code: PegThing *pTest = Parent()->First(); // first child of my parent int iSiblings = 0;...
PegThing* PegThing::Remove(PegThing *Who, BOOL bDraw = TRUE); void Destroy(PegThing *Who); The PegThing member function Remove() is used to detach an object from the object’s parent. This removes the object from the tree, but does not remove the object from memory. The PegThing member function Destroy() is similar to Remove(), although Destroy() both removes the object from the tree and deletes the object from memory.
PegThing Type and Attributes PegThing Type All PEG objects have a member variable called muType, which is a logical type indicator. You can retrieve or set an object’s muType value by calling the Type() functions: UCHAR Type(void) { return muType; } void Type(UCHAR uSet) {muType = uSet;} Type() called with no arguments will return that PegThing’s type, whereas Type() called...
A few object ID values are reserved by PEG for proper operation of dialog boxes and message windows. Therefore you should always begin your private control enumeration with a value of 1, so as not to overlap the reserved ID values. Valid user object IDs are in the range between 1 and 999.
PSF_CLICKED Default button select notification PSF_FOCUS_RECEIVED Sent when the object receives input focus PSF_FOCUS_LOST Sent when the object loses input focus PSF_TEXT_SELECT Sent when the user selects all or a portion of a text object PSF_TEXT_EDIT Sent each time text object string is modified PSF_TEXT_EDITDONE Sent when a text object modification is complete PSF_CHECK_ON...
PSF_SIZEABLE This flag determines whether or not an object can be resized. The application level software can modify this flag. PSF_MOVEABLE This flag determines whether or not an object can be moved. The application level software can modify this flag. PSF_NONCLIENT This flag, when set, allows a child object to draw outside the client area of its parent.
Page 16
PS_SHOW_VAL PS_RECESSED PS_LED PS_VERTICAL PS_PERCENT Spin Button Style SB_VERTICAL Refer to the ClassPad 300 SDK Reference Guide for more details on these styles. In all cases, the desired style flags can be logically ORed together to form one style parameter.
Current Focus All PegThing based classes support the idea of gaining and losing focus. If a PegThing has current focus, it means all key input is sent to that object. The user typically changes the input focus by pressing the pen on an object. When an object gets the input focus it gets a PM_CURRENT message and its PSF_CURRENT status is set.
Capture and Release of the Pointer When an object gains focus, it also gains focus of the pointer. Once you gain focus of the pointer you may wish to continue to receive events based on the pointer even if your object no longer has focus.
negative screen coordinates. This simply means that the object has been moved partially or entirely off the visible screen. Of course PEG clipping methods prevent the object from trying to access the non-existent area of video memory. PegRect A large part of your programming tasks when working with the graphical interface on the ClassPad will revolve around defining and calculating rectangular areas on the screen.
There is more information about using these functions in the Window and Screen Drawing section of this document. PegMessage PegMessage defines the format of messages passed within the PEG environment. PegMessage is defined as: struct PegMessage PegMessage() {Next = NULL; pTarget = NULL;} PegMessage(WORD wVal) {Next = NULL;...
// Get the value at the given index void * GetAt (int nIndex) // Set the value at the given index void SetAt (int nIndex, void *pElement) // Resize the array. Note that any objects that fall of the end of the // array are the programmer’s responsibility void SetSize (int iNewSize, int iGrowBy=-1)
Page 22
/// Returns the object pointer at the end (tail) of the list ent Tail(); /// Inserts ent at the head of the list virtual ent Insert(ent a); /// Inserts ent b before ent a in the list void InsertBefore(ent a, ent b); /// Inserts ent b after slink g void InsertAfter(slink* g, ent b);...
Messages and Message Handling The driving force behind the graphical interface on the ClassPad comes from events from the input devices and other PEG objects. All of these events all sent as messages in the PegMessageQueue. The PegMessageQueue is an encapsulated FIFO message queue with member functions for queue management.
use by PEG may change slightly in future releases, and the library therefore provides a #define indicating the first message value which is available for user definition. This #define is called FIRST_USER_MESSAGE. Peg System Messages PEG messages can be divided into two types: PEG system messages and USER messages. As we just mentioned, whether a message is a system message or a user message is determined by the value of the message wType field.
Page 25
drawing itself on the screen. PM_POINTER_MOVE This message is sent to an object whenever the pen moves over the object. PM_LBUTTONDOWN This message is sent to an object when the user generates a pen down event. PegPresentationManager routes pen input directly to the lowest child object containing the click position.
ID of the button used to close the dialog window. HM_SYS_ZOOM Zoom the active CPModuleWindow to full screen. HM_SYS_SWAP Swap the two CPModuleWindows in the CPMainFrame. HM_SYS_CLOSE The application is closing. You must save your state when you get this message. HM_SYS_RESUME The ClassPad is powering off.
If you load message pTarget values with pointers to application objects, you must insure that the object is not deleted before the message arrives. When a user defined message contains a non-NULL pTarget value, there is no verification that the pTarget field of the message is a valid object pointer.
// Create Save Contact button // The button gets created with ID SAVE_ID b = new PegBitmapButton(rr, &gbsaveBitmap, SAVE_ID,AF_ENABLED|TT_COPY); When this button is clicked, a unique message will be sent to the window’s message processing function that is formed by combining the Message Id PSF_CLICKED and the object ID SAVE_ID.
case USER_DEFINED_MSG2: // code for another user defined message: break; case SIGNAL(IDB_OK, PSF_CLICKED): // code for OK button clicked: break; default: // pass all other messages down to the base class: return CPWindow::Message(Mesg); return 0; In the previous section, we created a button with Object ID SAVE_ID. To catch the signal that this button sends, our Message function would look like this: SIGNED AddressWindow:Message(const PegMessage &Mesg) switch (Mesg.wType)
Peg Timers PEG timers provide a simple means for you to receive periodic timer messages in your windows or controls. Any object derived from a PEG object can start any number of individual timers. When the timer expires, that object will receive a PM_TIMER message from PEG.
300. To help show how these ideas are applied to an add-in application, we have provided an example add-in that uses most of the concepts that will be discussed. The add-in is located in Documents\ClassPad 300 SDK \Examples\WindowsExample\WindowsExample.dev. It is recommended that you run this application and see what type of drawing functions it performs.
Page 32
First we will look at the creation of the CPMainFrame in PegAppInitialize. The mainframe is created by passing in a peg rectangle that is the size of the mainframe. void PegAppInitialize(PegPresentationManager *pPresentation) PegRect Rect; Rect.Set(MAINFRAME_LEFT,MAINFRAME_TOP, MAINFRAME_RIGHT,MAINFRAME_BOTTOM); CPMainFrame *mw = new CPMainFrame(Rect); Next, we want to add an ExampleWindow to the mainframe.
So to sum that all up: A CPWindow got added to a CPModuleWindow that got added to a CPMainFrame that was added to the PegPresentationManager. All applications created for the ClassPad will follow part of this hierarchy. That is, all CPModuleWindows must be added to a CPMainFrame, and all CPMainFrames must be added to a PegPresentationManager.
– somewhere underneath the menu bar, and therefore it would not get drawn (Fig2). To fix this problem the ClassPad 300 SDK includes the CPWindow. CPWindow and all objects that are derived from CPWindow, support a function called AddR(). AddR() does the same thing as Add() –...
to appear ‘on-top’ (which is usually the case), you should call the base-class draw function before you do your own drawing. In some cases you may not want to invoke the base-class Draw() function at all. This is perfectly OK, as long as you remember a few rules: 1) Start your draw function with a call to BeginDraw().
screen invalidation, since your Draw() function is called specifically because an area of the screen has been invalidated. If you need to draw on the screen outside of the draw function you need to remember to invalidate the area you are going to draw to before you start drawing. If you want to be allowed to draw anywhere within the client area of your object, you can simply call the Invalidate() function with no parameters, which invalidates the area of the screen corresponding to an objects client area.
portion of ExampleWindow will become visible. ExampleWindow must be redrawn to display this portion. This is done by calling the parent’s draw function in OnPointerMove() in PanWindow.cpp: Parent()->Draw(); If we did not call DrawLines() in the Draw() function then ExampleWindow would be redrawn without the lines.
Notice that the mClient, the area you can draw to, does not extend over the scrollbars. This means that you cannot draw over the scroll bars and the drawable area in your window shrinks when scroll bars are added. mClient can shrink in other ways as well. If you look back at the Draw() function in ExampleWindow, you will see that there is a call to DrawFrame().
Page 39
Notice that we add the PegPrompt 25 pixels lower than the height of promptRect. This spaces the PegPrompts out so they are not drawn on top of each other. The following figure will give you an idea of how promptRect grows as a PegPrompt is added: A rough idea of what promptRect’s boundary, drawn in blue, looks like on startup and after adding a couple of new PegPrompts In a couple more clicks, the height of promptRect will grow larger than PanWindow’s...
rectangle is passed to Resize() to set PanWindow’s mReal to the new rectangle. Make sure you do not set mReal and mClient explicitly. You can end up in an invalid state where mClient is larger than mReal. By using the function Resize() it will make sure that if mClient grows that mReal will also grow if necessary.
The scroll bars added to the window make use of two virtual PegWindow functions: GetHScrollInfo and GetVScrollInfo. When a scroll bar needs to update itself, it calls these parent window member functions to learn the scroll bar limit, current setting, and percentage visible data.
Page 42
ExampleWindow::ExampleWindow(PegRect rect, CPMainFrame *frame) :CPModuleWindow(rect,0,0,frame) HasLines = false; SetScrollMode(WSM_AUTOSCROLL); PegRect r = mClient; r -= 20; // make the pan window a bit smaller m_panWin = new PanWindow(r); Add(m_panWin); Scrolling is now set up to work in ExampleWindow. When you run WindowsExample, you’ll notice that PanWindow is smaller than ExampleWindow and there are no scrollbars on startup.
Page 43
We suggest that you continue to add and comment lines out of the WindowsExample add-in. Once you understand everything in the example, you will have a good understanding of how drawing works on the ClassPad. If you have more questions, refer to the ClassPad 300 SDK Reference Guide.
User Interfaces We’ve discussed how to draw on the ClassPad and briefly touched on its windowing architecture. In this section we will discuss in detail what user interfaces are available on the ClassPad as well as visit each type of window that is supported in the SDK. Windows on the ClassPad In the Window and Screen Drawing section, we gave an overview of the windows that were used in the WindowsExample add-in application.
PegPresentationManager Class Name Derived From Styles Signals PegPresentationManager PegWindow None PSF_SIZED PSF_FOCUS_RECEIVED PSF_FOCUS_LOST PSF_KEY_RECEIVED The PegPresentationManager is a transparent background window that can be thought of as the desktop window for all PEG applications. PegPresentationManager keeps track of all of the windows and sub-objects present on the display device. In addition, PegPresentationManager keeps track of which object has the input focus (i.e.
CPMainFrame Class Name Derived From Styles Signals CPMainFrame PegDecoratedWindow FF_NONE PSF_SIZED FF_THIN PSF_FOCUS_RECEIVED FF_THICK PSF_FOCUS_LOST PSF_KEY_RECEIVED CPMainFrame is derived from PegDecoratedWindow. It also supports a menu bar, toolbar and status bar. A CPMainFrame has the ability to handle more than one CPModuleWindow.
mw->SetTopWindow(win); CPTabbedWindow Class Name Derived From Styles Signals CPTabbedWindow CPWindow FF_NONE PSF_SIZED PSF_FOCUS_RECEIVED PSF_FOCUS_LOST PSF_KEY_RECEIVED A CPTabbedWindow allows a virtual toolbar that is longer than the physical toolbar. This is helpful when your user interface controls will not all fit on the standard toolbar. The CPTabbedWindow has two panes each of which can contain PEG controls, such as buttons, text entry fields, etc.
PegNotebook Class Name Derived From Styles Signals PegNotebook PegWindow FF_RAISED PSF_SIZED FF_RECESSED PSF_FOCUS_RECEIVED NS_TEXTTABS PSF_FOCUS_LOST PSF_KEY_RECEIVED PSF_PAGE_SELECT PegNotebook is a PegWindow derived class for displaying and using a tabbed-notebook style control. The notebook can have any number of tabs, and each notebook tab is associated with a different notebook page.
The following code adds a PegNotebook with text tabs to a CPModuleWindow: CPMainFrame *mw = new CPMainFrame(Rect); PegRect ChildRect = mw->FullAppRectangle(); CPModuleWindow* swin = new CPModuleWindow(ChildRect,0,0,mw); mw->SetTopWindow(swin); PegNotebook *p = new PegNotebook(ChildRect, NS_TOPTABS|NS_TEXTTABS,3); p->SetTabString(0, (PEGCHAR*)"Tab1"); p->SetTabString(1, (PEGCHAR*)"Tab2"); p->SetTabString(2, (PEGCHAR*)"Tab3"); swin->AddR(p); mw->SetMainWindow(swin);...
Page 50
The PegMessageWindow class provides a quick way to display information messages. PegMessageWindow may contain a title bar, message line, and miscellaneous buttons. PegMessageWindow supports both modal and non-modal execution. In addition, the signal generated when the MessageWindow is closed by the user may be directed to any top-level window.
const PEGCHAR *Comment, WORD wStyle, WORD wStyle2, PegBitmap *pIcon, WORD dummy1, MessageWindowTypeEnum type=ERROR_WINDOW); The following example will create a PegMessageWindow with wrapping: const PEGCHAR* pTitle = (PEGCHAR*) "Title"; const PEGCHAR* pMessage = "Message that is word wrapped to the window"; PegMessageWindow *win = new PegMessageWindow(pTitle,NULL,pMessage, MW_OK|FF_THIN, 0, NULL, 0, ERROR_WINDOW);...
The progress bar added to a PegProgressWindow always has a scale of 0 to 100. It is up to the application software to pre-scale the input value accordingly. The style of the progress bar displayed in the window client area is passed to the PegProgressWindow constructor.
SCWindow Class Name Derived From Styles Signals SCWindow CPFrameWindow FF_NONE PSF_SIZED FF_THIN PSF_FOCUS_RECEIVED FF_THICK PSF_FOCUS_LOST PSF_KEY_RECEIVED SCWindow is an extension of the CPFrameWindow that adds support for events. Instead of handling user input like pen and keyboard events in the Message() method, SCWindow extends handling of events with the following event handlers: •...
For example, say that you have two drawing modes: point drawing and line drawing. The pen down in point drawing mode would create a point at that location. A pen down in line drawing mode would either mark the end of a line or the beginning of a line. You can isolate these two pen down events by creating two SCMode classes and using them with an SCWindowWithMode.
AbstractMathWindow Class Name Derived From Styles Signals AbstractMathWindow CPFrameWindow FF_NONE PSF_SIZED FF_THIN PSF_FOCUS_RECEIVED FF_THICK PSF_FOCUS_LOST PSF_KEY_RECEIVED AbstractMathWindow is an abstract class that provides scrolling or a frame for a MathWindow. MathWindows are usually placed inside one of the following AbstractMathWindows: •...
TabArrowMathWindow Class Name Derived From Styles Signals TabArrowMathWindow SlidingMathWindow FF_NONE PSF_SIZED PSF_FOCUS_RECEIVED PSF_FOCUS_LOST PSF_KEY_RECEIVED A TabArrowMathWindow uses small arrows on the left and right sides of the 2D math to scroll. The creation of a TabArrowWindow is similar to a ScrollableMathWindow: PegRect rr = {0,1,70,50};...
ScrollableMathWindow Class Name Derived From Styles Signals ScrollableMathWindow PegWindow FF_NONE PSF_SIZED FF_THIN PSF_FOCUS_RECEIVED PSF_FOCUS_LOST PSF_KEY_RECEIVED A ScrollableMathWindow contains a MathWindow and allows scrolling using the Peg horizontal and vertical scrollbars. An example of a MathWindow in a ScrollableMathWindow follows: PegRect rr = {0,1,70,50}; CPString math = "lim(1/x,x,0) + lim(1/x,x,0)";...
TextMathWindow Class Name Derived From Styles Signals TextMathWindow MathWindow FF_NONE PSF_SIZED FF_THIN PSF_FOCUS_RECEIVED FF_THICK PSF_FOCUS_LOST PSF_KEY_RECEIVED TextMathWindow is a MathWindow derived class that is used to display 2D math. The window does not allow user input or editing. PegRect rr = {0,1,70,50}; CPString math = "lim(1/x,x,0) + lim(1/x,x,0)";...
Creating UI in a CPModuleWindow Most, if not all, of the applications that you build will extend the CPModuleWindow to create your application’s main window. This is because the CPModuleWindow makes it easy to create menus, toolbars and a status bar. In this section we will discuss what needs to be done to create these user interface controls in a CPModuleWindow.
Page 60
Now let’s take a closer look at the parameters in each PegMenuDescriptionML. The first two parameters decide the text that will appear as the title of the menu. If the first value is defined, then the second value should be CMN_NO_ID. However, if the first value is NULL, then the second value must be a valid ID into a language database (see the section Multiple Language Support in the ClassPad).
Once you have done that, you will have menus! Here is what the menus created above look like on the ClassPad: Toolbars To add buttons to the toolbar you must override CPModuleWindow’s virtual function AddUI(). Here is a simple toolbar example with two text buttons: void YourWindow::AddUI() PegTextButton* b = new PegTextButton(1,1, "Button1", BUTTON1_ID, AF_ENABLED|TT_COPY);...
As shown in the previous section dealing with windows, there is a CPTabbedWindow that you can use to give your application a toolbar that is 2 times as long. This is also done inside of the AddUI() function. Toolbars don’t have to be text buttons. They can hold any PegThing derived object, including PegBitmapButton, CPDropDownButton or PegEditBox.
ClassPad. Note: In most of these cases there is more than one constructor for each class. Refer to the ClassPad 300 SDK Reference Guide to see details on all available constructors. PegButton...
PegButton serves as the base class for nearly all PEG button style objects. PegButton provides the BF_REPEAT timer operation, default frame drawing, and default selection SIGNALS. You would not normally create an instance of PegButton in your application, however PegButton is very useful as a base class for your own custom button styles. PegTextButton Class Name Derived From...
Page 65
BF_REPEAT PSF_FOCUS_RECEIVED BF_DOWNACTION PSF_FOCUS_LOST PSF_KEY_RECEIVED PSF_CLICKED PEG also allows for a button to display an image instead of text. These buttons support the standard border frames, but the text style flags do no apply. A PegBitmapButton also sends the signal PSF_CLICKED. To create a PegBitmapButton you must first create an image and define a PegBitmap that represents this image.
PegCheckBox Class Name Derived From Styles Signals PegCheckBox PegButton BF_REPEAT PSF_SIZED BF_DOWNACTION PSF_FOCUS_RECEIVED BF_SELECTED PSF_FOCUS_LOST AF_ENABLED PSF_KEY_RECEIVED PSF_CHECK_ON PSF_CHECK_OFF PEG also supports the creation of text-labeled checkboxes. Creating a checkbox is very similar to creating a button: PegCheckBox *box = new PegCheckBox(2, 2, "Check this out!"); AddR(box);...
PegRadioButton Class Name Derived From Styles Signals PegRadioButton PegButton/ BF_REPEAT PSF_SIZED PegTextThing BF_DOWNACTION PSF_FOCUS_RECEIVED BF_SELECTED PSF_FOCUS_LOST AF_ENABLED PSF_KEY_RECEIVED PSF_DOT_ON PSF_DOT_OFF PegRadioButton provides a mutually exclusive selection indicator. When a PegRadioButton is selected by the user, it finds all sibling radio buttons and de-selects them.
PegRadioButtons support the style flags AF_ENABLED and BF_SELECTED. They send the PSF_DOT_ON and PSF_DOT_OFF signals. CPDropDownButton Class Name Derived From Styles Signals CPDropDownButton PegBitmapButton BF_REPEAT PSF_SIZED BF_DOWNACTION PSF_FOCUS_RECEIVED BF_SELECTED PSF_FOCUS_LOST AF_ENABLED PSF_KEY_RECEIVED PSF_CLICKED CPDropDownButtons are used by many applications on the ClassPad. They allow a user to select an item from a list of bitmap buttons.
CPMultiButton Class Name Derived From Styles Signals CPMultiButton PegBitmapButton BF_REPEAT PSF_SIZED BF_DOWNACTION PSF_FOCUS_RECEIVED BF_SELECTED PSF_FOCUS_LOST AF_ENABLED PSF_KEY_RECEIVED PSF_CLICKED A CPMultiButton is very similar to a CPDropDownButton. With a CPMultiButton, the bitmaps are cycled through instead of being chosen from a drop down. The bold button in eActivity is an example of a CPMultiButton.
CPToggleButton Class Name Derived From Styles Signals CPDropDownButton PegBitmapButton BF_REPEAT PSF_SIZED BF_DOWNACTION PSF_FOCUS_RECEIVED BF_SELECTED PSF_FOCUS_LOST AF_ENABLED PSF_KEY_RECEIVED PSF_CLICKED CPToggleButton implements a two state PegBitmapButton that can be selected or unselected. When selected, the PegBitmap is inversed. Here is the code to create a simple example: void MCSWindow::AddUI() PegRect r = GetToolbarButtonRect();...
This section will show you how to create each of these text controls. Note: In most of these cases there is more than one constructor for each object. Refer to the ClassPad 300 SDK Reference Guide to see details on all available constructors. PegPrompt...
Be aware that if you do not pass in a static string to a PegPrompt, you should set the style flag TT_COPY. This causes PegPrompt to keep a copy of the string you pass in, so even if the string becomes invalid the PegPrompt will still have its own copy. PegString Class Name Derived From...
CPPegString Class Name Derived From Styles Signals CPPegString PegString/ FF_NONE PSF_SIZED CPUndoThing FF_THIN PSF_FOCUS_RECEIVED TT_COPY PSF_FOCUS_LOST AF_TRANSPARENT PSF_KEY_RECEIVED AF_ENABLED PSF_TEXT_SELECT EF_EDIT PSF_TEXT_EDIT PSF_TEXT_EDITDONE A CPPegString is a subclass of PegString. It has advanced features not available in PegString such as drag and drop, cut and paste and undo. The constructor to create a CPPegString can take the exact same parameters as our last example: PegRect r = mReal;...
PegTextBox Class Name Derived From Styles Signals PegTextBox PegWindow/ FF_NONE PSF_SIZED PegTextThing FF_THIN PSF_FOCUS_RECEIVED FF_THICK PSF_FOCUS_LOST EF_WRAP PSF_KEY_RECEIVED TT_COPY TJ_RIGHT TJ_LEFT TJ_CENTER PegTextBox is a multi-line text display control that does not support editing. By default, PegTextBox left-justifies the displayed text. Center-justification is also supported. Lines of text that are too long to fit in the client width of the textbox are also wrapped by default to use two or more lines.
If a string is long enough to require scroll bars, they can be added to the textbox by calling: p->SetScrollMode(WSM_AUTOSCROLL); If you would like the textbox to have scroll bars, make sure that you create the textbox with the style flag EF_EDIT. While this will not allow a user to edit the text inside the textbox, but it will allow the user to scroll the text.
CPEditBox Class Name Derived From Styles Signals CPEditBox PegEditBox/ FF_NONE PSF_SIZED CPUndoThing FF_THIN PSF_FOCUS_RECEIVED FF_THICK PSF_FOCUS_LOST EF_WRAP PSF_KEY_RECEIVED TT_COPY PSF_TEXT_SELECT TJ_RIGHT PSF_TEXT_EDIT TJ_LEFT PSF_TEXT_EDITDONE TJ_CENTER CPEditBox is a subclass of PegEditBox that supports drag and drop, copy and paste and undo.
Other User Interface Controls PEG has several other user interface controls that can be used to display information to the user or gather information from the user. PegList Class Name Derived From Styles Signals PegList PegWindow FF_NONE PSF_SIZED FF_THIN PSF_FOCUS_RECEIVED FF_THICK PSF_FOCUS_LOST LS_WRAP_SELECT...
// Set Scrolling just like a PegWindow list->SetScrollMode(WSM_AUTOVSCROLL); PegPrompt *pp; pp = new PegPrompt(0, 0, "Hello everybody", 0, FF_NONE|TJ_LEFT|AF_ENABLED|TT_COPY); list->AddToEnd(pp); pp = new PegPrompt(0, 0, "Hello again", 0, FF_NONE|TJ_LEFT|AF_ENABLED|TT_COPY); list->AddToEnd(pp); pp = new PegPrompt(0, 0, "How are you?", 0, FF_NONE|TJ_LEFT|AF_ENABLED|TT_COPY); list->AddToEnd(pp);...
Page 79
PSF_KEY_RECEIVED PSF_LIST_SELECT PegComboBox is similar to (and derived from) PegVList. PegComboBox adds the concept of "Opening and Closing", which can conserve space when a large number of items are added to the combo box. A drop-down arrow is provided to open the combo box.
PegSpinButton Class Name Derived From Styles Signals PegSpinButton PegThing SB_VERTICAL PSF_SIZED PSF_FOCUS_RECEIVED PSF_FOCUS_LOST PSF_KEY_RECEIVED PSF_SPIN_MORE PSF_SPIN_LESS PegSpinButton is a thumbwheel style control that is normally used to adjust a numeric value displayed in an adjacent object. PegSpinButton objects can be horizontal or vertical in orientation.
PegProgressBar Class Name Derived From Styles Signals PegProgressButton PegThing FF_NONE PSF_SIZED FF_THIN PSF_FOCUS_RECEIVED PS_SHOW_VAL PSF_FOCUS_LOST PS_RECESSED PSF_KEY_RECEIVED PS_LED PS_VERTICAL PS_PERCENT PegProgressBar is a simple progress bar control used to indicate to an end user the completion status of a slow activity. PegProgressBar can assume any scale value within the range of the SIGNED data type, however it is most common to display a value that is a percentage of the completion status.
Page 82
In this example Task() could be called from a user event, like clicking on a button. Here is a screenshot where a toolbar button starts Task(): For more information, including a complete list of constructors and member functions for each control class, see the ClassPad 300 SDK Reference Guide.
Using Floating-Point Values with the ClassPad The ClassPad does not support the use of double data types. Instead, the ClassPad has a native representation of doubles called BCD. There are two types of BCDs: OBCD and CBCD. OBCD is used to represent real numbers, whereas CBCD is used to represent complex numbers.
Page 84
Positive Infinity: Negative Infinity: True: Overflow Error: As you can see in the case of infinity or an error, you must inspect the low byte of the exponent for more information about the value. When dealing with infinity these bytes will tell you whether the infinity is positive or negative.
0x0016 Application ERROR 0x0017 System ERROR 0x0018 Already Exists 0x0019 Complex Number In List 0x001a Complex Number In Mat 0x001b Can't Solve (There is no solution) 0x001c Range ERROR 0x001d Iteration ERROR 0x001e Condition ERROR 0x001f NULL The Mantissa The remaining space in the mantissa is used to hold the value of your number. Remember that the flag is actually part of the mantissa, and there are 2 bytes of reserved data at the end.
For example, let’s say you want to store 1750. The value of the mantissa will be 1750. But remember we must calculate the exponent as if 1.750 is actually stored in the mantissa. Therefore the exponent needs to be 10^3 (because 1.75 * 10^3 = 1750). Since 1750 is positive the OBCD’s exponent starts at 1000.
Page 87
These functions place a word (unsigned short), short, and a long into an OBCD respectively. Here is an example using Cal_setn_OBC: OBCD x; Cal_setn_OBC(5, &x); //sets x to the value 5 Since this function takes an unsigned short we cannot set the value to a negative number. We would have to use the Cal_minus_OBC function as follows: OBCD x;...
Page 88
Cal_longto_OBC(523, &x); x.obcd1.exponential = 0x1120; // changes the value to 5.23e120 x.obcd1.exponential = 0x6004; // changes the value to -52300 x.obcd1.exponential = 0x5996; // changes the value to -0.000523 You can also create an OBCD by explicitly setting all 20 bytes of the mantissa as well as the 2 bytes of the exponent.
When this code finishes, x has the value of 25. If the return value from the addition function is anything other than IM_CAL_NORM, then an error occurred. You can view all the return values in the ClassPad 300 SDK API Reference Guide under Math Functions->Calculation Error Codes.
These functions differ by which form of the OBCD is placed in the string – normal mode, scientific notation, etc. We will look at four of these functions. To view all of the available functions, refer to the ClassPad 300 SDK API Reference Guide Strings- >Functions to Convert OBCD/CBCD datatypes to strings.
C++ that are more human readable. You can view all of these functions in the ClassPad 300 SDK API Reference Guide under Math Fuctions->C++ Math Functions. Here is an example of how they work: OBCD x, y;...
OBCDs. You can, however, convert a CBCD to a string. The functions are very similar to the ones used to convert CBCDs. You can view them all in the ClassPad 300 SDK API Reference Guide under Strings->Functions to convert OBCD/CBCD data types to strings.
CBCD y = {{{{0x05, 0x87, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, 0x1000}}, {{{0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, 0x1000}}}; More Information For more information about OBCD/CBCD data structures and the functions they can use, please refer to the ClassPad 300 SDK API Reference Guide.
Strings and String Handling In the ClassPad In this section we will discuss how strings are represented and used in the ClassPad. We will start with a look at the ClassPad’s character set and move on to the CPString class, string conversion and displaying multiple languages.
Each character also has a bold representation. Let’s walk through the creation of the multi-byte character . Looking at the character charts, you’ll see that has display code 0xEE and it’s second byte is 0x6E (refer to the chart immediately above). To create this character the code would look like this: CP_CHAR multi[3]={0xEE,0x6E,0};...
two types exist, you should avoid using the data type char. Using char will lead to a lot of unnecessary casting. CP_CHAR Functions The SDK provides a few string functions that can be used for characters or character arrays of type CP_CHAR. To change the case of a CP_CHAR*, the following functions are used: void CP_CharacterUpper(CP_CHAR *pS);...
CPString The CPString is a C++ class that encapsulates the memory allocation necessary for string handling and multi-byte string handling, while still providing access to a raw character buffer. The character buffer is dynamically allocated, and may be reallocated when the string is modified.
OBCD x; Cal_setpi_OBC(&x); CPString pi(x, 10); // pi=”3.14159265” CPString Comparison The comparison operators == and != are defined as: int operator==(const CPString& y); int operator!=(const CPString& y); The Standard C function strcmp is also available by using these functions: Compare(const CPString& y) const; Compare(PEGCHAR * lpsz) const;...
Page 101
unsigned int ByteLength() const {return m_byteLength;} unsigned int Length() const {return m_charLength;} unsigned int ByteLengthTo(int charOffset); int IsEmpty(); Notice that the first two functions are called ByteLength() and Length(). If you remember, CPStrings are made to hold single-byte or multiple-byte characters. This means that a string’s byte length is not always equal to its character length.
Buffer Ownership CPStrings control and manage a PEGCHAR* buffer that represents a string. The deletion of these buffers is normally handled by the CPString class. If you have a PEGCHAR* that you have already created, but would like to encapsulate in a CPString class, you can place it in a CPString with: void TakeBufferOwnership(PEGCHAR *buffer);...
Finally, if you want to convert from an int, long, short or char to a HEX string, use these functions: CP_CHAR *CP_IntToStringHex(int value, CP_CHAR *pS); CP_CHAR *CP_LongToStringHex(long value, CP_CHAR *pS); CP_CHAR *CP_ShortToStringHex(short value, CP_CHAR *pS); CP_CHAR *CP_CharToStringHex(char value, CP_CHAR *pS); Here is an example that uses some of these functions: CPString str1("44");...
Page 104
The parameter dig represents the number of significant digits. So the BCD 555555 passed with a dig of 3 would be 5.55e5. You can also use the following functions to convert a BCD to format mode of length digit: word CP_digit_OBC(OBCD *x,CP_CHAR str[],word digit, short mode,short dig);...
To go step by step through creating an add-in with multiple language support we will refer to the Hello World example add-in that came with the ClassPad 300 SDK. The add- in is located in Documents\ClassPad 300 SDK \Examples\HelloWorld\. First, let’s run the program and see how the text on the ClassPad changes depending on what language you are using.
Message Number Enumeration The first step that you will need to do when designing your application is keep a running enumeration of IDs for all of the strings that will appear in you application. These IDs are called message numbers. In the Hello World add-in this is done in HelloLangDatabase.h.
"Hallo", "Hallo Mundo", Each supported language in the ClassPad has its own array. You do not have to support every language if you do not want to. Defining ExtensionGetLang() Now comes the step of actually defining the function ExtensionGetLang(). You can view ExtensionGetLang() in its entirety by looking in HelloLangDatabase.cpp.
Page 108
return pStr; The current language decides which of our language arrays we will index into. We then return the string at our normalized index to complete the ExtensionGetLang() function. But you may be wondering, how does the menu or button know which message ID it should send? The answer is that you supply this information when you create the object.
MCS – Memory Control System MCS, Memory Control System, is used to save data on the ClassPad. This includes saving something as simple as a variable in Main to saving something as complex as an eActivity file with multiple embedded applications. This section will briefly discuss the structure of MCS and then provide information on the BIOS functions to write to MCS as well as the C++ file classes for MCS.
Page 110
Top Address MCS Top MCS Special Area (Fixed Size) Folder Management Area (Fixed Size) Folder Area (Variable Size) MCS Area Free Area (Fixed Size) Malloc Area MCS End Bottom Address The three sections of MCS each perform their own separate tasks. The MCS Special Area handles the overhead necessary to control the MCS file system.
typedef struct NAMEBUFFER CP_CHAR cpcName[8]; // Folder and Variable Name Buffer }NAMEBUFFER; The variables are stored in structures that are defined as: typedef struct _VARIABLEMANAGEMENTSTRUCT{ NAMEBUFFER naName; // Variable Name DWORD dwOffsetAdr; // Variable offest DWORD dwDataSize; // Variable data size UCHAR ucType;...
Page 112
To create this same variable in your add-in you would use the function: int BMCSCreateVariable(CP_CHAR *pcpcFolderName, CP_CHAR *pcpcValName, UCHAR ucValType, DWORD dwDataLength, UCHAR *pucDataTopAdr) If the function completed successfully, the return value will be IMU_MCS_SUCCESS, #define’d as 0. Otherwise the return value will be one of the error codes defined in MCSLib.h.
When creating a folder, you must pass in a reference to a UCHAR to get the folder number back from the function. The following example shows how to create and delete a folder: UCHAR temp; if(IMU_MCS_SUCCESS != BMCSCreateFolder((CP_CHAR *)"test", &temp)) // error handling…...
UCHAR attr; OBCD dat; Cal_setn_OBC(5,&dat); // Create x=5 BMCSCreateVariable((CP_CHAR*)"main", (CP_CHAR*)"x", IMU_MCS_TypeReal, sizeof(OBCD), (UCHAR*)&dat); // Rename x to y BMCSRenameVariable((CP_CHAR*)"main", (CP_CHAR*)"x", (CP_CHAR*)"y"); // Lock y BMCSVariableLockOn((CP_CHAR*)"main",(CP_CHAR*)"y"); // Get the attributes of y BMCSGetVariableAttribute((CP_CHAR*)"main",(CP_CHAR*)"y", &attr); // Check to see if the lock is set on y if ((attr &...
Page 115
The first function, BMCSSearchVariable(), searches for an exact match of the variable name that you pass in. The second and third both perform partial matches. Notice that BMCSSearchVal3() takes a VALMANSTRUCT reference as a parameter. In this case, it is important that you know and understand the structure of a variable in MCS before trying to use the function.
else // If the variable is found, make a copy of it BMCSCopyVariable((CP_CHAR*)"test", buffer, (CP_CHAR*)"test", (CP_CHAR*)"found x2"); // The third search function returns the structure of the found // variable. This structure contains the variable’s name VALMANSTRUCT *pValMan; if(BMCSSearchVal3((CP_CHAR*)"test",(CP_CHAR*)"copied ",&pValMan, 7)!=0) // NotFound!! else // If the variable is found, create a copy of it...
return MEM_ERR; To set the current folder, you just need the name of the folder: CP_CHAR folderName[] = "FOLDER1"; UCHAR *pucManagementTopAddress; UCHAR ucFolderNumber; if(BMCSSetCurrentFolder(folderName,pucManagementTopAddress, &ucFolderNumber) != 0) return MEM_ERR; Searching for a Folder Unlike with variables, there is only one function that is used to search for a folder. It is declared as: int BMCSSearchFolder(CP_CHAR *pcpcFolderName, UCHAR **ppManTopAdr, UCHAR *pucFolderNumber)
Since we are reading and writing from MCS we will only create instances of the classes CPReadMCSFile and CPWriteMCSFile to actually read and write. There are some member functions in CPReadFile/CPWriteFile and CPFile that we will use, but you will never instantiate these classes.
Page 119
int i = f.ReadWord(); While this would work fine if your application only saved integers, how do you read data types that do not have a function in CPReadFile? For the most part, all data types define their own Read() function to support being read from MCS. For example, let's assume a class foo with the following: class Foo void Read(CPReadMCSFile&...
If we look closely at the Contact class, we see it is just composed of CPStrings that hold all the information for a contact. Therefore, the Contact class’s Read() function will just be each one of these CPStrings calling its Read() function: // Reads a contact from a file.
Page 121
f.Realize(); f.WriteInt(8); Without the call to Realize() the amount of space needed to write the file would have been computed, but the file would not have been written to memory. Once you call Realize() the file is put in write mode, and all subsequent write functions actually write to memory.
for(int i=0; i<GetSize();i++) Contact *s = (Contact*)GetAt(i); s->Write(f); All that happens here is that we write out the total number of contacts that will be stored as an integer, then call each contact’s Write() function to write the contact. Here is the code for the Contact Class’s Write() function: // Writes a contact to a file.
Page 123
The class only has two member functions, Read() and Write(). void Read(CPReadFile &f); void Write(CPWriteFile &f); Once you have created a CPMEMFileHeader, you simply call its Read() function if you are reading in a file or its Write() function if you are writing out a file. For example, here is the Read() function from AddressDocument.cpp: // Application Type const PEGCHAR* ADDRESSBOOK_MEMTYPE_HEADER = "AddressBook";...
Page 124
4) Write the data for the file 5) Call Realize(); 6) Write the header 7) Write the data for the file For more information about these classes, please refer to the ClassPad 300 SDK Reference Guide or to the AddressBook example add-in.
Working through these examples and making changes to discover how your changes affect the program is an excellent way to get a better grasp of how to program on the ClassPad 300.