問題1:RichEditCtrl在用進行數據交換的時候會發生數據丟失問題?為什麼!
當我們在拖了一個控件到程序裡後,通常的做發是Ctrl+W,用類向導給控件關聯一個變量,然後依靠DDX/DDV進行數據交換,如果我們用同樣的方法來給RICHEDIT關聯一個CString類型的變量就會存在一個問題,就是如果我們的數據大於了64K,數據就會丟失。
通過查MSDN發現,WM_GETTEXT消息並沒有設計在RICHEDIT的數據大於64K的時候怎樣處理。而類向導生成的代碼是用DDX_Text來交換控件和CString變量的數據。恰好,DDX_Text函數是調用GetWindowText函數,而這個函數又會發出WM_GETTEXT消息到控件來返回控件裡的數據。WM_GETTEXT消息不能接受超過64K的數據,因此導致了RICHEDIT在數據交換的時候發生了丟失。
為了解決這個問題,我們要用到DDX_RichText函數。添加下面兩個函數到工程
DWORD CALLBACK ES2MemCallBack(DWORD_PTR dwCookie,LPBYTE pbBuff, LONG cb, LONG *pcb)
{
LPTSTR& lpszStrFill = *(LPTSTR*)dwCookie;
memcpy(lpszStrFill, pbBuff, *pcb = cb);
lpszStrFill += cb;
*lpszStrFill = TCHAR('\0');
return 0;
}
void AFXAPI DDX_RichText(CDataExchange* pDX, int nIDC, CString& value)
{
extern void AFXAPI AfxSetWindowText(HWND hWndCtrl, LPCTSTR lpszNew);
HWND hWndCtrl = pDX->PrepareEditCtrl(nIDC);
if (pDX->m_bSaveAndValidate)
{
int nLen = ::GetWindowTextLength(hWndCtrl);
LPTSTR lpszStrFill = value.GetBufferSetLength(nLen);
EDITSTREAM es = { (DWORD_PTR) &lpszStrFill, 0, ES2MemCallBack };
::SendMessage(hWndCtrl, EM_STREAMOUT, SF_TEXT, (LPARAM) &es);
value.ReleaseBuffer();
}
else
{
AfxSetWindowText(hWndCtrl, value);
}
}