最近在使用MFC開發軟體的時候遇到了一個非常困惑的問題。軟體用到了CRichEdit控制元件,用于顯示彩色log,我也成功得使用了該控制元件。
該軟體在有些同事的電腦上能夠正常運行,也能正常顯示彩色字體,但在個別同事的電腦上無法正常運行。而且我們用的電腦系統都是win10的。開發環境也都一樣。軟體在沒有開發環境的電腦上也能正常運行。我用得開發環境是Visual Studio 2008.
RichEdit該加的庫我也加載了。軟體log區顯示一部分內容后就崩了,通過斷點查看,是在RichEdit的函式GetWindowTextW()函式出問題。提示訪問沖突。但之前顯示過的內容肯定也呼叫過這個函式。那時也沒出問題。真不知道是啥原因造成這種現象。
uj5u.com熱心網友回復:
執行緒中直接操作的嗎?uj5u.com熱心網友回復:
對,是在子執行緒中有操作,呼叫函式如下,不過軟體在有的電腦上能正常運行,在有的電腦上不能,不知道咋回事void IMEICHECKDlg::AddLogString(CString strLog,COLORREF color)
{
CString log = CurrentTime();
strLog += _T("\r\n");
int nOldLines = 0;
int nNewLines = 0;
int nScroll = 0;
long nInsertionPoint = 0;
CHARFORMAT cf;
nOldLines = m_richEdit.GetLineCount();
cf.cbSize = sizeof(CHARFORMAT);
cf.dwMask = CFM_COLOR;
cf.dwEffects = 0;
cf.crTextColor = RGB(0,0,0);
nInsertionPoint = m_richEdit.GetWindowTextLengthW();
nInsertionPoint = -1;
m_richEdit.SetSel(nInsertionPoint, -1);
m_richEdit.SetSelectionCharFormat(cf);
m_richEdit.ReplaceSel(log);
cf.crTextColor = color;
nInsertionPoint = m_richEdit.GetWindowTextLengthW();
m_richEdit.SetSel(nInsertionPoint, -1);
m_richEdit.SetSelectionCharFormat(cf);
m_richEdit.ReplaceSel(strLog);
nNewLines = m_richEdit.GetLineCount();
nScroll = nNewLines - nOldLines;
m_richEdit.LineScroll(nScroll);
return;
}
uj5u.com熱心網友回復:
檢查 strLoguj5u.com熱心網友回復:
試試修改下引數型別void AddLogString(CString &strLog,COLORREF color)
除錯版本, 在奔潰的機器上 安裝遠程除錯器,遠程除錯下
uj5u.com熱心網友回復:
遠程除錯工具安裝哪個??uj5u.com熱心網友回復:
strLog是為了換行用的uj5u.com熱心網友回復:
應該還是執行緒操作的問題。打開RichEdit的源檔案afxcmn.inl看一下,我貼一部分上來。
_AFXCMN_INLINE BOOL CRichEditCtrl::CanUndo() const
{ ASSERT(::IsWindow(m_hWnd)); return (BOOL)::SendMessage(m_hWnd, EM_CANUNDO, 0, 0); }
_AFXCMN_INLINE BOOL CRichEditCtrl::CanRedo() const
{ ASSERT(::IsWindow(m_hWnd)); return (BOOL)::SendMessage(m_hWnd, EM_CANREDO, 0, 0); }
_AFXCMN_INLINE UNDONAMEID CRichEditCtrl::GetUndoName() const
{ ASSERT(::IsWindow(m_hWnd)); return (UNDONAMEID) ::SendMessage(m_hWnd, EM_GETUNDONAME, 0, 0); }
_AFXCMN_INLINE UNDONAMEID CRichEditCtrl::GetRedoName() const
{ ASSERT(::IsWindow(m_hWnd)); return (UNDONAMEID) ::SendMessage(m_hWnd, EM_GETREDONAME, 0, 0); }
_AFXCMN_INLINE int CRichEditCtrl::GetLineCount() const
{ ASSERT(::IsWindow(m_hWnd)); return (int)::SendMessage(m_hWnd, EM_GETLINECOUNT, 0, 0); }
_AFXCMN_INLINE BOOL CRichEditCtrl::GetModify() const
{ ASSERT(::IsWindow(m_hWnd)); return (BOOL)::SendMessage(m_hWnd, EM_GETMODIFY, 0, 0); }
_AFXCMN_INLINE void CRichEditCtrl::SetModify(BOOL bModified /* = TRUE */)
{ ASSERT(::IsWindow(m_hWnd)); ::SendMessage(m_hWnd, EM_SETMODIFY, bModified, 0);}
_AFXCMN_INLINE BOOL CRichEditCtrl::SetTextMode(UINT fMode)
{ ASSERT(::IsWindow(m_hWnd)); return (BOOL) ::SendMessage(m_hWnd, EM_SETTEXTMODE, (WPARAM) fMode, 0); }
RichEdit自己的函式都是通過SendMessage實作的,這些函式是執行緒安全的。
GetWindowText是CWnd的函式,這個不能跨執行緒操作。
int CWnd::GetWindowText(_Out_z_cap_post_count_(nMaxCount, return + 1) LPTSTR lpszString, _In_ int nMaxCount) const
{
ASSERT(::IsWindow(m_hWnd) || (m_pCtrlSite != NULL));
if (m_pCtrlSite == NULL)
return ::GetWindowText(m_hWnd, lpszString, nMaxCount);
else
{
CString str;
m_pCtrlSite->GetWindowText(str);
Checked::tcsncpy_s(lpszString, nMaxCount, str, _TRUNCATE);
return lstrlen(lpszString);
}
}
所以你應該用CRichEditCtrl自己的成員函式就沒問題了,就算debug定位到錯誤行,也是莫名其妙的位置,沒什么意義。
我字多,給分吧。
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/246308.html
標籤:界面
下一篇:git 爛筆頭
