List的动态操作(一)

List的动态操作(一)
出处: 作者:eden 『时代PDA』掌上电脑资讯==智能手机 2003-8-28 11:25:35
List在编程时对于处理比较少的数据时比较好用,你可以不考虑scrollbars以及一些其他会在含有table窗体中会遇到的问题。但是
Conference中却没有动态操作List的函数,因此如果你想在List中实现动态的增加和删除只有自己写函数。现在在SDK4.0中提到了两种
方法,我会依次为大家介绍。
1.LstSetListChoices(ListType *listP,Char **itemsText, Int16 numItems)
这种方法主要原理是通过程序员自己生成一个字符串数组(即Char**)后,利用此函数生成List的Item。下面我将通过实例向大家说明
如何实现的,这个程序因为是一个菜单程序的片断,所以里面涉及了一些价钱字段:
static void buildlist(void)
{FormPtr form;
UInt16 i;
Char price[DB_PRICE_SIZE];
Char* precord;
Char listChoice[DB_NAME_SIZE + DB_PRICE_SIZE];
form = FrmGetActiveForm();
这里price表示价格部分,precord表示记录的指针,listChoice表示选取的部分
*price=NULL;
*listChoice=NULL;
为了防止意外发生,我先将price和listChoice清空
if(number==0)
{offset=0;
list=NULL;}
这里的number主要是判断buildlist是否是第一次运行,如果是那就要重新初始化一些变量,offset表示后一个记录开始与前一个记录开始的偏移量,
list就是我们需要的字符串阵列,就是把需要显示的Item逐项排成一排
hrecord = DmQueryRecord( menuDB, cursor );
precord = MemHandleLock( hrecord );
这一步是取得选取项目在数据库中的指针
StrCopy( listChoice, precord + DB_NAME_START );
StrCat( listChoice, " " );
StrCat( listChoice, precord + DB_PRICE_START );
StrCat(listChoice,"RMB");
把记录的内容复制到listChoice中
if( hchoice == 0 )
{
if( (hchoice = MemHandleNew( StrLen( listChoice ) + 1 )) == 0) {
FrmAlert(MemoryErrorAlert);
offset = 0;
}}
else
{
//MemHandleUnlock( hchoice );
if( (MemHandleResize( hchoice, offset + StrLen( listChoice ) + 1 ))!=0 )
FrmAlert(MemoryErrorAlert);
}
这里主要是定义list,即字符串阵列内存块的大小,这样系统就会分配足够大的内存块给list
StrCopy(price,precord+DB_PRICE_START);
total+=StrAToI(price);
这里是得到价钱后算出总的价钱,大家可以不用管它
list=MemHandleLock(hchoice);
StrCopy( list + offset, listChoice );
offset += StrLen( listChoice ) + 1;
这里就是程序关键的第一步,通过不停的改变offset,就可以把需要显示的item项目逐个排列到以list为首地址的内存块内,从而得到
字符串阵列list!!!
MemHandleUnlock(hchoice);
if( (hpchoice = SysFormPointerArrayToStrings( list, number )) == 0)
得到list后我们就可以通过SysFormPointerArrayToStrings得到字符串数组的句柄
FrmAlert(MemoryErrorAlert);
ppchoices = MemHandleLock( hpchoice );
然后通过MemHandleLock锁定字符串数组句柄hpchoice从而得到字符串数组的指针ppchoices,这样我们的目的就达到了
LstSetListChoices( getObject( form, MenuListList ), ppchoices, number );
前面做了这么多工作就是为了得到ppchoices,这样我们就可以通过LstSetListChoices生成List了
LstDrawList( getObject( form, MenuListList ) );
当然,需要重新画一次List才能看到我们的成果
MemHandleUnlock(hpchoice);
}
相信如果你真的看懂这段程序的话你会发现关键是怎么生成list!!!只要你把想显示的item的内容逐个排列到list中去就可以了。
想实现list的动态操作就只需要改变Char* list就可以了。上面这段程序可以很好的实现增加,那删除怎么办呢,其实也很简单,
你可以在生成Char* list的时候跳过所要删除的这一项就可以了,大家可以看看下面这段程序:
for(i=0;i<pitem;i++){
这里pitem是选择项目在list中的位置,我先把在所要删除项目之前的所有项目排列到list中
s=LstGetSelectionText(plist,i);
if( hchoice == 0 )
{
if( (hchoice = MemHandleNew( StrLen(s) + 1 )) == 0) {
FrmAlert(MemoryErrorAlert);
offset = 0;
}}
else
{
//MemHandleUnlock( hchoice );
if( (MemHandleResize( hchoice, offset + StrLen(s) + 1 ))!=0 )
FrmAlert(MemoryErrorAlert);
}
list=MemHandleLock(hchoice);
StrCopy( list + offset, s );
offset += StrLen(s) + 1;
s=NULL;
MemHandleUnlock(hchoice);}
for(i=pitem+1;i<listnum;i++){
这里就绕过了删除的项目,把它之后的所有项目排列到list中,这样就得到了删除选项之后的list了
s=LstGetSelectionText(plist,i);
if( hchoice == 0 )
{
if( (hchoice = MemHandleNew( StrLen(s) + 1 )) == 0) {
FrmAlert(MemoryErrorAlert);
offset = 0;
}}
else
{
if( (MemHandleResize( hchoice, offset + StrLen(s) + 1 ))!=0 )
FrmAlert(MemoryErrorAlert); }
list=MemHandleLock(hchoice);
StrCopy( list + offset, s );
offset += StrLen(s) + 1;
s=NULL;
MemHandleUnlock(hchoice);}
if( (hpchoice = SysFormPointerArrayToStrings( list, number )) == 0)
FrmAlert(MemoryErrorAlert);
ppchoices = MemHandleLock( hpchoice );
LstSetListChoices( getObject( form, MenuListList ), ppchoices, number );
LstDrawList(plist);
MemHandleUnlock(hpchoice);}
有个网友就曾经问过在同一个Form中有两个List,想通过点击其中一个list中的项目在另一个list中显示,其实可以有两种方法实现,
一种就是直接在数据库中找到选中项目的内容复制到Char* list中去,就象我这段程序一样。还有个方法就是通过tLstGetSelectionText
得到选中项目的内容,然后仍然复制到list中去,最后再显示出来,关键一点还是如何去生成list。
这种方法生成List确实比较麻烦,而且资源占得较多,如果你经常编写程序的话,你会发现如果项目很多的话这简直就是一个噩梦,所以PalmOS
中提过了另外一种方法,通过LstSetDrawFunction来生成,现在我已经实现了这种方法生成List,稍后我会向大家介绍这种方法。 (本文已被浏览 779 次)
 


List的动态操作(二)
出处: 作者:eden 『时代PDA』掌上电脑资讯==智能手机 2003-8-28 11:26:02
2.LstSetDrawFunction (ListType *listP,ListDrawDataFuncPtr func)
这种方法主要原理是通过调用函数func实现List的生成,在接触具体程序前先向大家介绍一下Char str[][],表示字符窜数组指针,如Char str[3][80]表示一个字符窜数组指针,它包含了3个字符窜,str[1]就表示第一个字符窜的首地址,str[2]就表示第一个字符窜的首地址,每个字符窜长度为80。相信看到这里有c编程经验的人应该明白字符窜数组指针的好处了,下面我们来看看具体的函数(注:为了方便我不在重复“关于List的动态增加和删除一”(以后简称“一”)中的程序,所以有些注释如果不明白的话请对照“一”中的程序来看):

static Char str[20][80];
先定义全局变量str:
static void buildlist(void)
{FormPtr form;
i=0;
这里i是全局变量,控制依次绘出list的item
Char price[DB_PRICE_SIZE];
Char* precord;
Char listChoice[DB_NAME_SIZE + DB_PRICE_SIZE];
form = FrmGetActiveForm();
这里price表示价格部分,precord表示记录的指针,listChoice表示选取的部分
*price=NULL;
*listChoice=NULL;
为了防止意外发生,我先将price和listChoice清空,因为这里可以直接用Char *str[],所以不再需要
offset和list了。

hrecord = DmQueryRecord( menuDB, cursor );
precord = MemHandleLock( hrecord );
这一步是取得选取项目在数据库中的指针
StrCopy( listChoice, precord + DB_NAME_START );
StrCat( listChoice, " " );
StrCat( listChoice, precord + DB_PRICE_START );
StrCat(listChoice,"RMB");
把记录的内容复制到listChoice中
StrCopy(price,precord+DB_PRICE_START);
total+=StrAToI(price);
这里是得到价钱后算出总的价钱,大家可以不用管它
StrCopy(str[number],listChoice);

这里number是UInt16类型,主要是控制list的item个数,当我选好选项后按下ok时number就加一,这样就动态的控制了item的个数,
所以str[number]总是指向最后一个字符窜的首地址!!!然后把listChoice的内容复制过去,这就完成了字符窜数组指针的初始化。

LstSetListChoices( getObject( form, MenuListList ), NULL, number );
因为用到了LstSetDrawFunction,所以LstSetListChoices只是设置item的个数,同时控制回调函数ListDrawFunc调用的次数!!!
LstSetDrawFunction(list, (ListDrawDataFuncPtr)ListDrawFunc);
这里就是设置了回调函数ListDrawFunc,list就是通过这个函数绘制出来的!!!
}
看了这段函数大家会发现它比“一”中的函数简单了很多,这里我直接就将得到的字符窜排到字符窜数组指针中去,大大简化了
程序结构,同时也省去了对handle的操作,因为在palm里面对内存的操作是很麻烦的事!同时通过这种方法可以节约很多系统资源,
在上面的程序注释中打了惊叹号的是这个程序的关键部分,大家注意理解。下面再看看ListDrawFunc函数:
static void ListDrawFunc(UInt16 itemNum, RectanglePtr bounds, Char** data)
{
WinDrawChars(str, StrLen(str), bounds->topLeft.x, bounds->topLeft.y);
这里就是画出了item的内容,方便吧
i+=1;
这里是程序的关键,在buildlist()中,LstSetListChoices控制回调函数ListDrawFunc调用的次数,第一次调用时我们画
第一项,当调用第一次后会调用第二次,那我们就画第二项,因此i理所当然的要加一次!!!
}

好了,通过ListDrawFunc和字符窜数组指针结合动态控制LIST确实很方便,而且结构简单。我想通过“一”“二”两篇帖子
中程序的比较,大家能够看出写程序最重要的是结构和算法,只要选折好的结构和算法你真正写程序的时间会很少,而且结构简单明了,
所以大家应该多提高在这方面的能力!对于list的动态删除我在这里就不写了,主要希望大家也动动手,因为只有自己动手了才
能真正理解程序,如果有什么问题可以发帖子或者给我email。另外对于miken的方法:定义一个全局的字符指针,使用
MemPtrNew
MemMove
StrCopy
MemPtrFree
....
等函数进行操作的方法其实也很不错,大家也可以试试,这种方法也很不错的!由于时间比较紧,所以里面有些东西也是我个人的理解,如果
有错误的地方还希望大家予于批评指正!
 
 
 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值