After doing an operation in palm like - control select or application launch, may be you will get one unwanted PenUpEvent. for removing that unwanted pen or key events we can flush the event queues using
EvtFlushPenQueue();
If you Want to remove Key events from queue you can use
EvtFlushKeyQueue();
Monday, December 1, 2008
Removing PenEvents
Thursday, July 31, 2008
MP3 embedding in blogs
You have an MP3 file (a podcast, a song of your band, a lecture) and you want to share it with the visitors of your site. You can just put a link to the MP3 and let people download it or you can include it as an object and let the browser play it with a plug-in like QuickTime (and most of the times also crash the browser). Most people want to preview the audio and not wait until it downloads completely. You can play a partial MP3 file in audio player, but many people aren't aware of that.
But there's another away: a Flash player that allows you to pause and rewind the MP3. It's like an audio version of Google Video or YouTube, with the difference that the file is hosted on your server (or on another server). While there are many solutions based on Flash, this is the one I like the most. It's a modified version of Odeo player, that's used to play podcasts on odeo.com:
You just have to replace [MP3 file address] with the actual address.
Here you can see how it looks (in this audio, Marissa Mayer talks about innovation at Google):
Tuesday, July 15, 2008
Adding battery meter in the program form
For adding a signal, blue tooth or battery gadget in our palm project
just add a gadget (width=16, height=12) to your form, and use the
HsStatusSetGadgetType API from the Palm/Treo SDK.
If you develop with HB++, here is a link to a project that demonstrate hwo to
add Network, battery and Bluetooth gadgets:
http://www.handheld-basic.com/forum/viewtopic.php?t=1950
Posted by
sumesh
at
3:20 PM
|
Labels: Palm, Palm Hacks, Tutorial
Friday, July 11, 2008
Add Scroll bar in the field
--------- 1: create these three functions ------------
// you need to replace 700 by the ID of your field, and 710 by the ID of your scrollbar !!!!
void updateScrollbar(void)
{
FormPtr frm = FrmGetActiveForm();
ScrollBarPtr scroll;
FieldPtr field;
Int16 currentPosition;
Int16 textHeight;
Int16 fieldHeight;
Int16 maxValue;
field = FrmGetObjectPtr(frm, FrmGetObjectIndex(frm, 700));
FldGetScrollValues(field, ¤tPosition, &textHeight, &fieldHeight);
// if the field is 3 lines, and the text height is 4 lines
// then we can scroll so that the first line is at the top
// (scroll position 0) or so the second line is at the top
// (scroll postion 1). These two values are enough to see
// the entire text.
if (textHeight > fieldHeight)
maxValue = textHeight - fieldHeight;
else if (currentPosition)
maxValue = currentPosition;
else
maxValue = 0;
scroll = FrmGetObjectPtr(frm, FrmGetObjectIndex(frm, 710));
// on a page scroll, want to overlap by one line (to provide context)
SclSetScrollBar(scroll, currentPosition, 0, maxValue, fieldHeight - 1);
}
void scrollLines(Int16 numLinesToScroll, Boolean redraw)
{
FormPtr frm = FrmGetActiveForm();
FieldPtr field;
field = FrmGetObjectPtr(frm, FrmGetObjectIndex(frm, 700));
if (numLinesToScroll < class="qBody" id="EchoTopic">
}
}
--------- 2: modify your main form handler like this ------------
where the event frmOpenEvent is caught, add this line *before* calling FrmDrawForm:
updateScrollbar();
add this code to catch the events fldChangedEvent and sclRepeatEvent:
case fldChangedEvent:
updateScrollbar();
handled = true;
break;
case sclRepeatEvent:
scrollLines(eventP->data.s
break;
Friday, June 20, 2008
Getting RGBcolor value from picel value in palm
RGBColorType* col;
UInt32 r, g, b;
UInt16 rgb565;
UInt32 * outRGB;
UInt8 *srcBitsP;
rgb565 = ((srcBitsP[0]) << 8) | (srcBitsP[1]);
r = ((rgb565 & 0xF800) >> 8) // 5 bits of red
|((rgb565 & 0x3800) >> 11);
g = ((rgb565 & 0x07E0) >> 3) // 6 bits of green
| ((rgb565 & 0x0060) >> 5);
b = ((rgb565 & 0x001F) << 3) // 5 bits of blue
| ((rgb565 & 0x0007));
*outRGB = (r << 16) | (g << 8) | (b);
col=(RGBColorType*)*outRGB;
WinSetForeColorRGB(NULL, col);
Tuesday, June 17, 2008
Opening a web bwowser from the weblink in palm devices
Check on the Knowledgebase of palm for related article
And one more way is there that one is HsBrowseUrl(char *url) give the url with full string like"http://www.blogger.com/"
Friday, April 11, 2008
Retrieving own phone no
Char* number = NULL;
PhnAddressList list;
PhnAddressHandle address;
PhnLibOpen(phnLibRef);
if (IsCDMA())
{
Err err = PhnLibGetOwnNumbers(phnLibRef, &list);
if (!err)
{
err = PhnLibAPGetNth(phnLibRef, list, 1, &address);
if (!err && address)
{
number = PhnLibAPGetField(phnLibRef,
address,
phnAddrFldPhone);
MemHandleFree(address);
}
}
}
else
{
Err err = PhnLibGetOwnNumbers(phnLibRef, &list);
if (!err)
{
err = PhnLibGetNth(phnLibRef, list, 1, &address);
if (!err && address)
{
number = PhnLibGetField(phnLibRef,
address,
phnAddrFldPhone);
MemHandleFree(address);
}
}
}
if (number)
{
StrCopy(destNumber,number);
MemPtrFree (number);
}
Thursday, April 10, 2008
Determining PalmOS Make and Model at Run Time
| Sometimes it's necessary to determine the actual manufacturer or model of the device your app is running on, at runtime. These cases are rare, since usually you want to determine the presence of a particular PalmOS feature, and there are APIs to do that. It's not straightforward to determine device type, because the technique has evolved over the life of the OS. I derived this information experimentally, or by perusing header files, or by contributed observations from other developers. If it's wrong, blame me and not PalmSource or the licensees. The contradictions shown in this table are clear support for PalmSource's oft-repeated advice to use supported API's to query for particular capabilities (like color, VFS, wireless network) at runtime and not to depend on looking up the device model. | ||
| ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| If you have information to add, please send it to me. You can extract information from your device like this: UInt32 deviceID, companyID, miscFlags; Err devErr, compErr, miscErr;
devErr = FtrGet(sysFtrCreator, sysFtrNumOEMDeviceID, &deviceID); compErr = FtrGet(sysFtrCreator, sysFtrNumOEMCompanyID, &companyID); miscErr = FtrGet(sysFtrCreator, sysFtrNumHwrMiscFlags, &miscFlags);
if (!compErr) WinDrawChars((Char *) &companyID, 4, 20, 30); if (!devErr)
You'll have to look at the value of miscFlags as an integer, masking it with hwrMiscFlagIDMask. For Handspring devices you probably have to look at deviceID as an integer instead of 4 characters. Or if you prefer, you can run the program pixelcheckD.prc and send me the results. If your device isn't in the table above, lend a hand and send me your info. Send me the Maker, Device, and the string printed below the pitch value. If you're really ambitious, measure the length of the line next to "2 cm" and tell me how long it really is. The solid square should be just large enough to contain a US quarter. For the capabilities of particular devices, see http://www.palmos.com/dev/tech/hardware/compare.html or the individual manufacturers' web sites. | ||
Wednesday, April 9, 2008
Tuesday, April 8, 2008
Wednesday, March 26, 2008
Vibrate palm device using HsIndicatorState
For Vibration alerts in palm devices we can use this function.
void Vibrate()
{
Err err;
UInt32 extVersion;
UInt16 vibrate = kIndicatorAlertAlert;
UInt16 vibrateCount = 2;//indicates how many times it needs to vibrate.
err = FtrGet(hsFtrCreator, hsFtrIDVersion, &extVersion);
if(err == errNone && extVersion >= 0x05000000) // actually could be 0x05210000
{
err = HsIndicatorState(vibrateCount, kIndicatorTypeVibrator,&vibrate);
}
SndPlaySystemSound (sndInfo);//For making one sound indication. Other than sndInfo We can use sndWarning, sndError, sndStartUp, sndAlarm, sndConfirmation, sndClick
SndPlaySystemSound (sndInfo);
}
The documentation for the HsIndicatorState
| ||||||||||||||||
| Set or get the state of the LED or Vibrator.
|
Wednesday, March 19, 2008
How to persist data on a Palm hand held
Introduction
Welcomed this, my third article on palm development. Now that we have covered the basics and can create an application with some GUI components, the next important thing is to be able to persist data. The palm application philosophy is simple. When an application is started, it should be in the State that it was last left, giving the illusion of a multithreaded system, were in fact only one thread can run at a time. In order for this to be possible, as well as in order for just about any useful application to be written, we need to store data. Because the palm has no external storage mediums, data is stored in memory, in area is known as databases. I am sorry to report that this is somewhat of a misnomer, and does not in any way imply facilities such as SQL or relational tables. Instead what you get is a block of memory which is associated with your creator ID and the name, from which you can select data by either its array style index, or an ID which is guaranteed to be unique in the context of that device, and which would have no relation to the ID returned if the same application were run on a different device.Creating a database
The first step of course is to create a database. The variable which equates to a handle to a database is a DmOpenRef. You should declare one of these as a global in your main header file for each database that you need to keep open. The call to create a database looks like this.Err err = 0;err = DmCreateDatabase(0, "BugSquBugsDYTC", 'DYTC', 'DATA', false);
Opening a database
At this point, we still do not have an open database and we have not used our DmOpenRef. We're now going to correct both of these anomalies. There are two ways to open a database. The first is as follows:DmOpenRef myRef;
DmOpenDatabaseByTypeCreator('DATA' , 'DYTC', dmModeReadWrite);
Err err = 0;LocalID dbID = DmFindDatabase(0,"BugSquBugsDYTC");
gDB = NULL;
if (dbID > 0) gDB = DmOpenDatabase(0, dbID, dmModeReadWrite);
if (!gDB) {err = DmCreateDatabase(0, "BugSquBugsDYTC", 'DYTC', 'DATA', false);
if (err == 0)
{gDB = DmOpenDatabase(0, DmFindDatabase(0,"BugSquBugsDYTC"), dmModeReadWrite);
Creating records
So at this point we have a database on a palm, and a handle to it. Quite obviously the next step is to create some data records with the database, in particular it is likely that our newly created database should have some default values within it. The sample application is called Bug Squasher. It was written as a learning exercise, and in theory is designed to be part of a bug tracking system, where the desktop system updates a list of applications which can have bug reports, and the Palm creates bug reports which can then be uploaded to the main system. The simpler of the two databases simply stores a list of names, which equate to projects for which we can report bugs. The two default values are 'misc' ( for bugs on systems not in the Palm ) and 'BugSqu' ( so we can report bugs on the bug tracking system itself ). The functions we will need to create a record and fill it with data are DmNewRecord, which takes three parameters ( the database to operate on, the index of the record to create, and a length for the record ), and DmStrCopy, which takes a Char * ( derived from our record handle, as we will see ), a start position, and another Char *, which we will copy. Note that I capitalise the word Char, this is a common way for PalmOS to create it's own types, a Char is the type used by Palm, as opposed to char. That they are the same thing is immaterial, Palm create their own types to ensure all types are the same size across platforms. The other functions we will use are MemHandleLock, which returns a void *, and which we call on our new database record, casting the result to a Char *. Finally, MemPtrNew is the Palm equivelant of malloc, and is used to create our string, StrCopy is the equivelant of strcpy and is used to place a value in our string, and MemPtrFree is used to free the string we created. Here is the code:UInt16 index = dmMaxRecordIndex;MemHandle h = DmNewRecord(gDBProj, &index, 5);if (!h)err = DmGetLastErr();
else {Char * s = (Char *) MemHandleLock(h);
Char * pChar = (Char*)MemPtrNew(5 * sizeof(Char*));
StrCopy(pChar, "Misc\0");
DmStrCopy(s, 0, pChar);MemPtrFree( pChar);
MemHandleUnlock(h);
}
index = dmMaxRecordIndex;
h = DmNewRecord(gDBProj, &index, 6);if (!h)err = DmGetLastErr();
else {Char * s = (Char *) MemHandleLock(h);
Char * pChar = (Char*)MemPtrNew(6 * sizeof(Char*));
StrCopy(pChar, "BugSq\0");
DmStrCopy(s, 0, pChar);MemPtrFree( pChar);
MemHandleUnlock(h);
}
Well, that was easy, wasn't it ? But because the databases are just an area of memory and offer no real facilities beyond locking a record in terms of accessing items within a record, what do we do when we want to store more complex data ? The answer is to create a struct that defines our datatype. For example, if we had a strict that looks like this:
typedef struct {
DateType DateEntered;
UInt8 nBugSeverity;
UInt8 nBugType;
} BugRecord;
Char *s;
UInt16 offset = 0;
s = (Char *) MemHandleLock(DBEntry);
DmWrite(s, 0, br, sizeof(BugRecord));
MemHandleUnlock(DBEntry);
typedef struct {
DateType DateEntered;
UInt8 nBugSeverity;
UInt8 nBugType;
char * szBugDesc;} BugRecord;
typedef struct
{DateType DateEntered;
UInt8 nBugSeverity;
UInt8 nBugType;
char szBugDesc[1];
} PackedBugRecord;
void PackBug(BugRecord *br, MemHandle DBEntry){UInt16 length = 0;
Char *s;
UInt16 offset = 0;
length = (UInt16) (sizeof(BugRecord) + StrLen(br->szBugDesc) + 1);
if (MemHandleResize(DBEntry, length) == errNone) {s = (Char *) MemHandleLock(DBEntry);
DmWrite(s, 0, br, sizeof(*br));
DmStrCopy(s, OffsetOf(PackedBugRecord, szBugDesc), br->szBugDesc);MemHandleUnlock(DBEntry);
}
}
Naturally having packed our bug, we also need to unpack it. This is simply a matter of assigning the right value to the variables within the struct. Obviously, if we had more than one string, we would need to use StrLength to figure out the right position for the start of each string in order to assign them. In The code looks like this.
void UnpackBug(BugRecord *bug, const PackedBugRecord *pBug)
{bug->DateEntered = pBug->DateEntered;
bug->nBugSeverity = pBug->nBugSeverity;
bug->nBugType = pBug->nBugType;
bug->szBugDesc = pBug->szBugDesc;
}
Reading back our records
In this example I have used a GUI component which we have not yet discussed, namely a list. The list has been set to be ownerdrawn, and a callback has been set which will be passed the index of the item to draw. The details of this will be covered in a future article. Our strategy is to use the index passed into the overdrawn function to retrieve the appropriate record from our database and render it. This has the advantage of saving us from making a copy of our entire database, saving both space and processor time. There are two ways to search for a record, by index or by unique ID. The unique ID is not as exciting as it sounds, the search is still sequential and therefore has linear growth in complexity. It's far more common to search by index, but if you have the ID, the API is DmFindRecordByID, and it takes a database, a unique ID and a pointer which returns the index of the item. The DmQueryRecord function takes a database and a record number and returns a record handle or NULL to indicate failure. Here is the full code we use in our list callback to read a record.Err err = 0;MemHandle myRecord = DmQueryRecord(gDB, itemNum);
if (!myRecord)err = DmGetLastErr();
else {PackedBugRecord *prec = (PackedBugRecord *) MemHandleLock(myRecord);
BugRecord * rec = (BugRecord*) MemPtrNew(sizeof(BugRecord));UnpackBug(rec, prec);
Deleting Records
Deleting records is easy, just use DmRemoveRecord(gDB, nIndex), where gDB is your handle to a database, and nIndex is the record to delete.Some other stuff
Records have a 64k limit, there is a way to overcome this, but I am not familiar with it. Each record also has a record attributes area, which is one byte in size and contains a deleted bit, a secret bit, a dirty bit, a busy bit and a 4 bit category. Records when they are deleted are not necesarily removed from the Palm. DmRemoveRecord deletes them entirely, DmDeleteRecord deletes the record but keeps the header and sets the bit, and DmArchiveRecord does not delete the record, but sets the bit. The reason for these differences is syncronisation, another future topic, which basically involves moving data between a Palm and a desktop application. Deleted records are moved to the end of the database and are not visible, even if they are still there. They are typically always removed at the next syncronisation.Databases also have their own header, where data like the name, creator, and type is stored, along with some application specific data. This is the place to store data you want to keep only once for the entire database. Additionally, databases can be sorted, through the provided DmInsertionSort and DmQuickSort functions, both of which use a function pointer to allow the programmer to specify the sort order. Insertion while maintaining sort is provided by the DmFindSortPosition API, inserting into an existing record index causes all records below that one to be moved down accordingly.
Although I am unable to comment beyond what the Palm API can tell you about these functions, they seem worthwhile, we have a database at work with 40,000 records and without some sort of binary search, the search times are somewhat untenable.