Archive for 31 8 月, 2008

自己写的黑莓手机IPD编辑工具BBerIPD

星期日, 31 8 月, 2008

黑莓手机的“桌面管理器”能把手机里的信息备份成IPD文件,也能导入IPD文件,这很方便。但在bbs.maxpda.com论坛里没有找到合适的IPD查看、编辑工具。

对我来说,能通过电脑来管理手机的“记事本”、“地址簿”,能导出手机里的“短信”内容是我最想要的,论坛里的IPDManager没办法打开仅包含这些内容的IPD文件,IPDEditor又依赖于.NET Framework 2.0,而我的电脑安装有这个Framework仍不能使用,所以我抽空研究了一下这几类信息的格式,自己写了一个BBerIPD工具,主要功能是:查看和编辑“记事本”、“地址簿”,查看“短信”内容,将选择的内容复制出来。

注意:修改后需要使用“导出IPD”功能才会生效!

(更多…)

发现了一个CListCtrl::GetItemText的Bug及解决方案

星期日, 31 8 月, 2008

近段在写个小程序时发现了CListCtrl::GetItemText的Bug,微软的源代码如下:

VC6对应文件: VC98\MFC\SRC\winctrl2.cpp
VC7.1对应文件: Vc7\atlmfc\src\mfc\winctrl2.cpp
CString CListCtrl::GetItemText(int nItem, int nSubItem) const
{
 ASSERT(::IsWindow(m_hWnd));
 LVITEM lvi;
 memset(&lvi, 0, sizeof(LVITEM));
 lvi.iSubItem = nSubItem;
 CString str;
 int nLen = 128;
 int nRes;
 do
 {
  nLen *= 2;
  lvi.cchTextMax = nLen;
  lvi.pszText = str.GetBufferSetLength(nLen);
  nRes  = (int)::SendMessage(m_hWnd, LVM_GETITEMTEXT, (WPARAM)nItem,
   (LPARAM)&lvi);
 } while (nRes == nLen-1);
 str.ReleaseBuffer();
 return str;
}

问题出在标红色的句子,我发现如果读取的第(lvi.pszText + lvi.cchTextMax - 1)字节刚好是双字节字符的第一个字节时(比如中文汉字的第一个字节),该字节最后被替换为'\0'(这符合lvi.pszText以'\0'结尾的约定),但返回读取的字节数是lvi.cchTextMax而不是预想的(lvi.cchTextMax-1),导致(nRet == nLen-1)结果为FALSE而结束读取数据,但是数据仍没有读完,需要继续读取。

解决办法很简单,把(nRet == nLen-1)改成(nRet >= nLen - 1),真搞不懂为什么没有人向微软反应这个错误并促使他们改过来呢。

我自己写了一个外部函数:

CString GetItemText(CListCtrl& lvw, int nItem, int nSubItem)
{
 ASSERT(::IsWindow(lvw.m_hWnd));
 LVITEM lvi;
 memset(&lvi, 0, sizeof(LVITEM));
 lvi.iSubItem = nSubItem;
 CString str;
 int nLen = 128;
 int nRes;
 do
 {
  nLen *= 2;
  lvi.cchTextMax = nLen;
  lvi.pszText = str.GetBufferSetLength(nLen);
  nRes  = (int)::SendMessage(lvw.m_hWnd, LVM_GETITEMTEXT, (WPARAM)nItem,
   (LPARAM)&lvi);
 } while (nRes >= nLen-1);
 str.ReleaseBuffer();
 return str;
}