VIA Selle SMS 系列之—存储篇

在短信菜单的设置选项中,有一项是 Save Sent message,如果选为开启,则会保存发送短信,否则则不会保存所发送短信。

在做Sms Service的时候,要求不保存所发送短信,但其它正常的短信仍得能存储。
所以要实现针部部分短信不存储的设置。

在发送短信前,会执行一个函数:
bool SmsControllerC::CheckStorageBeforeSendMsg(bool &HasOpenDialog,bool IsFromEditMsg,bool IsForEditAddress)
{
……
if (mModelP->GetSettings()->mAutoSave) //mAutoSave为设置是否保存的参数
{
//Check if Uim valid when sms storage is uim only.

uint32 Result = mModelP->CheckStorageAndDoAutoDelete(RecordNum);
……
}
……
}
此时如果把这里的IF条件置为FASLE,则就不会存储。针对特殊短信,加一条件判断即可,如:
if ((mModelP->GetSettings()->mAutoSave)&&(mModelP->notSmsServiceNum))

但现在的问题是为什么在这里置为False则不会存储,这里并没有存储的动作啊!并且,此时短信还没有发送,也不可能在这时候就存储下来。

这里折腾了很久,用模拟器跟发现mAutoSave在发送过程中影响三个地方,第一处如上,第二处是发送短信的时候: AslSmsResultT Result = AslSmsSendMessage(*SmsRecordP, &RecordId, &MessageId, GetSettings()->mAutoSave,IsLMS);
第三处是,短信发送成功反馈的时候:
bool SmsModelC::MessageSent(AslSmsSendStatusT *StatusP)
发送短信的时候没有明显进行保存短信的动作。
于是问题定位在第三个函数(先前一直没有注意到它,调试许久:!)

bool SmsModelC::MessageSent(AslSmsSendStatusT *StatusP)
{
……
AslSmsReplaceAddMessage(*SmsRecordP);//这里进行了保存动作,但没那么简单
……
}

AslSmsResultT AslSmsReplaceAddMessage(SmsRecordC &SmsRecord)
{
#ifdef FEATURE_LSM
VectorC SmsRecList;

SmsRecord.Split(&SmsRecList);

for(int i=0; i<SmsRecList.GetSize();i++)
{
SmsRecordC *TempRec = (SmsRecordC *)SmsRecList.GetElement(i);
if (AslGetIdFromReplaceIdArray(&recid)) // 问题的最终原因在此!!!
{
result = (AslSmsResultT)ValSmsReplaceTxtMessage(*TempRec,recid);
}
delete TempRec;
}
#endif
return result;
}

bool AslGetIdFromReplaceIdArray(uint16* RecId)
{

if( IsEqual(0, mReplaceIdArray.GetSize()) )
{
return FALSE; //若在CheckStorageBeforeSendMsg时,把那条IF置为False,此在这里返回
}
……
return TRUE;
}

现在大致的流程清晰了许多,首先在发送前在CheckStorageBeforeSendMsg会判断mAutoSave的状态,若为TRUE,则预留一个空间用来保存此短信,若为FALSE,则不预留。在短信成功发送后,进行保存的时候,MessageSent中的AslSmsReplaceAddMessage会判断是否有预留空间,没有的话,无论mAutoSave怎么设置,则都不会保存。

针对Sms service的疑虑解决了,但预留的方式没有进一步的深入,如何申请预留空间的,如何添加删除等。留给读者自己深入分析吧:)

VIA Selle Sms系列的文章,到此告一段落,回顾这段时间在整SMS相关,一言以蔽之短信模块博大精深,这个系列的文章也只是水面之上冰山一角。但应该是个引子,顺着这些大的线索深入下去,终有一日能深入到冰山之底的
 

ThinkingIn

每当翻开一本其作者对软件表现出如此挚爱的书,都会今我激动不已,他们对技术工作的热爱,对软件之美的追求,慷慨地激励着我。最近在读Martin的《敏捷软件开发》一书,感受良多。不愧为经典之作,想与大家分享,于是将新建一栏目,名为:ThinkingIn,主要想跟大家讨论一些关于敏捷,极限编程,软件项目管理等方面的话题,还有一些关于所读过的软件开发领域的经典之作,分享一些好的设计思想及实践方法。

软件之美

      
除了我的家庭,软件是我的挚爱。通过它,我可以创造出美的东西。软件之美在于它的功能,在于它的内部结构,还在于团队创建它的过程。对用户来说,通过直观,简单的界面呈现出恰当特性的程序就是美的。对软件设计者来说,被简单,直观地分割,并具有最小内部耦合的内部结构就是美的。对开发人员和管理者来说,每周都会取得重大进展,并且生产出无缺陷代码的具有活力的团队就是美的。美存在于所有这些层次之中,它们都是本书内容的一部分。
 

VIA Selle SMS 系列之—设置篇

Sms的相关设置问题曾经有过介绍,比较简略,这次以在编写短信过程中设置发送属性的过程,再来讨论下SMS中复杂消息的处理过程,示例的操作步骤如下:
Message—>Write
Message—>Options—>Sending options[A]—>(Mark
One)[B]—>Done[C]
这里主要说的是从A到C的过程。
A.在Options菜单中选择Sending
Options的选项:
触发消息:
MessageID APPMSG_SMS_NEWMSG
      Parameters:APPMSG_SMS_PARAM_NEWMSG_OPTION_SENDING_OPTION
 响应消息:
    case APPMSG_SMS_NEWMSG:
      return
HandleMessage(
SmsMessageHandlerNewmsgTable, MsgId, Param1,
               APPMSG_SMS_PARAM_NEWMSG_MAX);
由“APPMSG_SMS_NEWMSG”这条消息,会继续查找一个表,这个表中有相对于触发消息所带参数的具体动作。
const SmsMessageHandlerT SmsMessageHandlerNewmsgTable[] =
{
 { //APPMSG_SMS_PARAM_NEWMSG_OPTION_SENDING_OPTION
   
APPSMS_TABLE_ITEM(
APPMSG_SMS_PARAM_NEWMSG_OPTION_SENDING_OPTION)// 这条消息告诉我们要
   
SMS_CONTROLLER_COMMAND_OPEN_DIALOG,
//  
打开一个Dialog
    APPSMS_DIALOGID_NEWMSG_OPTIONS_SENDING_OPTIONS, //   所打开的DialogID
   
SMS_CONTROLLER_COMMAND_CLOSE_DIALOG,
//  
关闭一个Dialog
   
APPSMS_DIALOGID_NEWMSG_OPTIONS_MENU,
// 所关闭DialogID
   
APPSMS_DIALOGID_NULL,
// 要运行Dialog定义里的SetDataDialogID ,此时为空
   
&SmsControllerC::HandleNewMsgOptionSendingOption
// 执行触发消息的额外函数
 },
}
总的来说,在Options菜单中选择Sending
Options选项,会打开一个Dialog,关闭此Options的Dialog,并执行一个函数,设置此编缉短信的Sending
Options的始初化状态,即从SmsEditMsgManagerC中具体的短信对象的状态来设置SmsEditMsgManagerC当中的几个表示状态的临时变量。
B.在打开Options的Dialog时所执行的动作:
//dialog information table
const SmsDialogIdInfoT
SmsDialogIdInfoTable[] =
{
 {
   APPSMS_TABLE_ITEM(APPSMS_DIALOGID_NEWMSG_OPTIONS_SENDING_OPTIONS)
  
IDD_DLG_SMS_NEWMSG_OPTIONS_SENDING_OPTIONS,
   FALSE,
  
&SmsViewC::UpdateViewNewMsgOptionSendingOption,
 // 打开此Dialog后,更新此Dialog视图的函数,立即执行
  
&SmsViewC::SetDataNewMsgOptionSendingOption,
// 针对此Dialog的设置数据的函数,非立即执行,由其它函数调用
  
&SmsViewC::HandleWinNotifyCheckBoxMenuSettingDlg
// 处理Dialog中控件发生变化时的响应函数,当控件状态变化时调用此函数
 },
}
在更新视图的函数中,会根据之前的设置项(SmsEditMsgManagerC中临时的成员变量)(在上面的执行触发消息的额外函数中初始化的状态),来改变Dialog的显示内容。
当前Sending
Options里的Dialog中有两项,改变是否选中的状态,就会调用“HandleWinNotifyCheckBoxMenuSettingDlg”并在UI上显示变化,即选中,没选中,SoftKeyBar显示发生变化,即标记,未标记
C.改变完状态后,按“Done”所执行的动作:
触发消息:
          MessageID
:APPMSG_SMS_NEWMSG
         
Parameters
APPMSG_SMS_PARAM_NEWMSG_OPTION_SENDING_OPTION_DONE
 响应消息:
case APPMSG_SMS_NEWMSG:
      return
HandleMessage(
SmsMessageHandlerNewmsgTable, MsgId, Param1,
               APPMSG_SMS_PARAM_NEWMSG_MAX);
同第一步的过程,但这里的参数不一样,对应的MessageHandlerTable有变化:
 { //APPMSG_SMS_PARAM_NEWMSG_OPTION_SENDING_OPTION_DONE
   
APPSMS_TABLE_ITEM(
APPMSG_SMS_PARAM_NEWMSG_OPTION_SENDING_OPTION_DONE)
// 这条消息告诉我们要
   
SMS_CONTROLLER_COMMAND_OPEN_POPUP,
//  
打开一个Pop
up
的窗口
   
APPSMS_DIALOGID_POPUP_SETTINGS_SAVED,
//  
所打开的Pop
up
窗口的ID
   
SMS_CONTROLLER_COMMAND_CLOSE_DIALOG,
//  
关闭一个Dialog
   
APPSMS_DIALOGID_NEWMSG_OPTIONS_SENDING_OPTIONS,
// 所关闭DialogID
   
APPSMS_DIALOGID_NEWMSG_OPTIONS_SENDING_OPTIONS,
// 运行此Dialog定义里的SetData函数    &SmsControllerC::HandleNewMsgOptionSendingOptionDone// 执行触发消息的额外函数
 }
即按“Done”后,关闭此Sending
Options的窗口,打开一个Pop UP的窗口,提示改变成功,然后调用Sending Options的窗口的SetData函数,最后再执行触发消息的额外函数。
 1.
SetData函数:把用户对选项的选择内容保存临时的变量当中
 2. 额外函数:执行具体的保存动作,即把临时变量当中的内容保存到当前所编辑短信的具体对象当中
最后返回短信内容的编辑界面,完成设置动作。
补充一点:
SmsEditMsgManagerC中的短信对象即mEditMsg,并不是在其构造函数中就初始化的,而是在SetEditMsgText时进行初始化,并且读取当前对短信选项的总体设置来初始此单条短信。
bool
SmsEditMsgManagerC::SetEditMsgText(const StringC &StrText)
{
 EnableEditMsg();// 从短信的总体选项设置来初始化此条短信
 mEditMsg.SetUserData(StrText);
 return TRUE;
}
编写新短信时,这个动作是在SmsViewC::SetDataNewMsg(DialogC *DlgP, uint32 MsgId, uint32
Param)里执行的,在Edit Message新建短信窗口按Send键,或Options键都可触发此消息.
 

再补充一点:
       针对类型为
MENU_LIST_CHECKBOX 的MENU风格,当按下时会改变选中状态,此时会立即收到HandleWinNotify消息,SoftKeyBar中间键的自定义消息将不起作用(当系统判断为Checkbox时SoftKeyBar的中间键消息被拦截,默认为选择CheckBox的消息)。
        针对类型为
MENU_LIST_RADIOBOX 的MENU风格,当按下时不改变选中状态,此时不会收到HandleWinNotify消息,SoftKeyBar中定义的消息将会起作用。
可在以UPdateDialogView时,设置一个属性使在MenuItem项中滚动时,可以触发HandleWindNotify消息。
     MenuP->SetNotifyScrollEvent(TRUE);
一个Dialog中,若即有MenuItem项对应的消息,又有此Dialog的SoftKeyBar对应的消息。
若SoftKeyBar的消息不为:WINMSG_SOFT_SELECT_KEY则,以SoftKeyBar中的消息为准执行,而不会执行MenuItem对应的消息。
若SoftKeyBar的消息为:WINMSG_SOFT_SELECT_KEY则实际会执行MenuItem对应的消息。
若SoftKeyBar的消息为空:则什么都不会执行。
有CheckBox的时候按键消息的传递过程:
按下Dialog中包含CheckBox的SoftKeyBar中的按键后的处理过程:
                
1.
当前APP的HandleKey //如果直接返回则按键消息将不会被执行
                 2.
ApplicationC::HandleKey //所有APP的基类按键消息
                 3.
接着消息传递如下(略)
MailClientC::SendMail
MailServerC::SendMail
MailServerC::DispatchMail
WinManagerC::ProcessMail
WindowC::ProcessMail
MailClientC::ProcessMail
MailClientC::MailMapProc
                 4.
DialogC::OnKeyPress //will let dialog’s child control handle key press
first
                 5.
DialogC::PreOnKey //will get the right child to handle the key
message
6.接着消息传递如下(略)
WindowC::ProcessMail
MailClientC::ProcessMail
MailClientC::MailMapProc
    
7.
MenuCtrlC::OnKeyPress // 如果的这里返回则按键消息也不会被执行,CheckBox则在这里Return True;不继续往下处理消息,所以自定义的SoftKeyBar消息将不会被执行,在这里返回
    
8.
MenuCtrlC::CheckItem   //change the check box
status
9.MenuCtrlC::SendNotify //触发CheckBoxHandlWinNotify消息
                   
……
再之后没有继续跟下去,应该是把定义的按键消息发送到Task进行分发处理的操作。
总之,短信方面的处理比较复杂,也是出问题比较集中的地方。