最近我们测A4 的系统信息,同事的读取Flash 容量大小总有点问题,有时候出现误差很大,可看看wince系统读出来的值很正确,于是我就找到控制面板里的那些代码(D:/WINCE600/PUBLIC/WCESHELLFE/OAK/CTLPNL/STGUI),自己写了个读flash 容量的程序,测试ok,主要代码如下:
void CStoragManagerTestDlg::OnBnClickedRead()
{
// TODO: Add your control notification handler code here
HANDLE hStore;
STOREINFO storeInfo = {0};
CString szStorageName = L"";
CComboBox *pComboBox = (CComboBox *)GetDlgItem(IDC_STOR_TYPE);
pComboBox->GetLBText(pComboBox->GetCurSel(), szStorageName);
DEBUGMSG(1, (L"szStorageName=%s /r/n", szStorageName));
storeInfo.cbSize = sizeof(STOREINFO);
hStore = OpenStore(szStorageName);
if(INVALID_HANDLE_VALUE != hStore)
{
GetStoreInfo(hStore, &storeInfo);
CloseHandle(hStore);
}
else
{
AfxMessageBox(L"Open storeage failed!");
}
DEBUGMSG(1, (L"%d,%d /r/n",storeInfo.snNumSectors, storeInfo.dwBytesPerSector));
//show the storage information
if (Size2String(storeInfo.snNumSectors*storeInfo.dwBytesPerSector,(LPTSTR)(LPCTSTR)szStorageName,MAX_PATH))
{
m_strCapacity = szStorageName;
SetDlgItemText(IDC_EDIT_CAP, m_strCapacity);
}
if (Size2String(storeInfo.dwBytesPerSector, (LPTSTR)(LPCTSTR)szStorageName, MAX_PATH))
{
m_strSectorSize = szStorageName;
SetDlgItemText(IDC_EDIT_SECTOR, m_strSectorSize);
}
//UpdateData(FALSE);
/*
if(Size2String(storeInfo.snNumSectors*storeInfo.dwBytesPerSector,(LPTSTR)(LPCTSTR)m_strCapacity,MAX_PATH)
&&
Size2String(storeInfo.dwBytesPerSector, (LPTSTR)(LPCTSTR)m_strSectorSize, MAX_PATH))
{
SetDlgItemText(IDC_EDIT_CAP, m_strCapacity);
SetDlgItemText(IDC_EDIT_SECTOR, m_strSectorSize);
}
*/
}
BOOL Size2String(LONGLONG llBytes, LPTSTR pszSize, DWORD dwLen)
{
double bytes = (double)llBytes;
DWORD dwUnit = 0;
LPCTSTR pszUnits[] = { _T("B"), _T("KB"), _T("MB"), _T("GB"), _T("TB") };
DWORD dwUnitNum = sizeof(pszUnits) / sizeof(pszUnits[0]);
// move from bytes to kb, to mb, to gb and so on diving by 1024
while(bytes >= 1024 && dwUnit < (dwUnitNum - 1))
{
bytes /= 1024;
dwUnit++;
}
_sntprintf(pszSize, dwLen, _T("%.2f %s"), bytes, pszUnits[dwUnit]);
return TRUE;
}
在如上代码中要注意几个问题:
1. OpenStore, GetStoreInfo 等这几个函数在wince 5.0 和 wince6.0 有点不一样,wince5.0,把Storemgr 模块放在一个Storeapi.lib 库里,没有放在内核里,而到了wince6.0,把Storemgr 模块放到了内核里, 所以这几个函数包含在coredll.lib 库里;
2. 同事获得flash大小用到的是GetDiskFreeSpaceEx 这个函数,这个函数得到的是指定的分区容量,而不是整个flash容量;For Example,我们把1G flash 分成几个分区,我们底层用于存nboot,toc, eboot, logo, nk, hive registry 等等分了几个区,而把剩下的空间取名NANDFLASH提供用户使用,而用GetDiskFreeSpaceEx 这个函数去读NANDFLASH 大小,获得的就仅仅是flash 的NANDFLASH 这个分区的大小,所以有很大的出入;
3. 就是我在调这个程序遇到的问题,现在想想其实也是我们经常提到的注意指针的问题,可在实际中一不小心就跨入雷池了;我在程序中把CString m_strCapacity ,m_strSectorSize 分别与一个编辑框关联起来,用他们来show 出获得的FLash 容量及扇区大小,这两个变量都初始化为:m_strCapacity = L“”;m_strSectorSize = L“”; 开始我用
if(Size2String(storeInfo.snNumSectors*storeInfo.dwBytesPerSector,(LPTSTR)(LPCTSTR) m_strCapacity,MAX_PATH)
&&
Size2String(storeInfo.dwBytesPerSector, (LPTSTR)(LPCTSTR)m_strSectorSize, MAX_PATH))
去更新它们的值,再UpdateData(FALSE)去show 出来,结果两个都是 2 KB, 也就是说它们的值都是扇区的大小,我当时就很奇怪了,为什么呢?更奇怪的是, 我写了一个Clear 函数,清除它们的内容,
void CStoragManagerTestDlg::OnBnClickedClear()
{
// TODO: Add your control notification handler code here
// if (m_strCapacity.GetLength() > 0 && m_strSectorSize.GetLength() > 0)
{
m_strCapacity = L"";
m_strSectorSize = L"";
DEBUGMSG(1, (L"m_strCapacity=%s /r/n", m_strCapacity));
SetDlgItemText(IDC_EDIT_CAP, m_strCapacity);
DEBUGMSG(1, (L"m_strSectorSize=%s /r/n", m_strSectorSize));
SetDlgItemText(IDC_EDIT_SECTOR, m_strSectorSize);
}
}
结果怎么着,还是2KB,当时我真是苦想了半天,终于想通了:
初始化m_strCapacity = L""; m_strSectorSize = L""; 就使得它们成员指针m_pszData地址都是指向同一段地址L“”;只要没给它们重新分配地址,它们的内容就一定是一样的,所以当执行
Size2String(storeInfo.snNumSectors*storeInfo.dwBytesPerSector,(LPTSTR)(LPCTSTR) m_strCapacity,MAX_PATH) 这个函数时它们的内容就都是flash 容量值了,而到执行
Size2String(storeInfo.dwBytesPerSector, (LPTSTR)(LPCTSTR)m_strSectorSize, MAX_PATH)) 这个函数时又都变成扇区的值了,也就是2KB了, 而我清除它们的内容时候,又用这个语句:m_strCapacity = L""; m_strSectorSize = L""; 也就是说它们的地址还是没变,此时的L“” 的地址内容不是空的,而是“2KB”; 说到这里就知道怎么改了........
看来指针这块真的很诡异,也许说起来我们都很清楚,一到实际用起来估计就不是那么清楚了,只要多练了!
最后再说一下UpdateData 这个函数吧,以前也用,但不是很明白,只知道UpdaeData(false) 不行就用UPdateData(true),其实没明白它们真正作用,感觉msdn上说的也很简单,我的理解是:
UPdateData(true) 就是用于把控件中输入的值更新到与该控件相关联的变量中(获取输入的数据);
UpdaeData(false) 就是用于把更新了的变量值在相关联的控件中显示出来(显示获得的数据);