MFC的CRichEdit控件使用问题

秦风楚月汉宫阙 2021-01-08 03:09:32
最近在使用MFC开发软件的时候遇到了一个非常困惑的问题。软件用到了CRichEdit控件,用于显示彩色log,我也成功得使用了该控件。
该软件在有些同事的电脑上能够正常运行,也能正常显示彩色字体,但在个别同事的电脑上无法正常运行。而且我们用的电脑系统都是win10的。开发环境也都一样。软件在没有开发环境的电脑上也能正常运行。我用得开发环境是Visual Studio 2008.
RichEdit该加的库我也加载了。软件log区显示一部分内容后就崩了,通过断点查看,是在RichEdit的函数GetWindowTextW()函数出问题。提示访问冲突。但之前显示过的内容肯定也调用过这个函数。那时也没出问题。真不知道是啥原因造成这种现象。
...全文
245 14 打赏 收藏 转发到动态 举报
写回复
用AI写文章
14 条回复
切换为时间正序
请发表友善的回复…
发表回复
  • 打赏
  • 举报
回复
谢谢,大家的建议,花了两天的时间终于找到到了问题的原因:我的工程界面是DLL库工程,在使用钩子函数的时候,出现了很奇怪的现象:我的钩函数是用来捕获回车,结果钩函数在捕获回车发消息的时候,在有的电脑上是发一次,在有些电脑上发2次,而且电脑系统都是一样的。发送1次的那个把键按下和抬起当成一个信号发送,发送2次 的那个把键按下和键抬起当成两个消息发送,结果处理完前一个消息后,处理第二个消息的时候找不到发消息的对象了。出现这种情况让我很纳闷,还好通过栈函数的调用顺序查询到了问题的原因。不知道有没有遇到和 我这一样的情况
  • 打赏
  • 举报
回复
全部改成CRichEdit的成员函数还是不行,把子线程中的对RichEdit控件的函数全部去掉还是不行
  • 打赏
  • 举报
回复
RichEdit是在子线程中用到了,但我换成RichEdit的成员函数还是有问题
  • 打赏
  • 举报
回复
就是这情况,反正软件不让用,怕出问题
mmcanyu 2021-01-09
  • 打赏
  • 举报
回复
一般开发的电脑上运行都没问题,别的电脑上运行要看运气,有时可以,有时崩溃。
  • 打赏
  • 举报
回复
引用 7 楼 mmcanyu 的回复:
应该还是线程操作的问题。
打开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定位到错误行,也是莫名其妙的位置,没什么意义。
我字多,给分吧。
那为啥程序在有些电脑上能正常运行有些不行
mmcanyu 2021-01-09
  • 打赏
  • 举报
回复
那还发消息的方式吧

线程中
CString *pstr = new CString("......");
COLORREF color = RGB(255,0,0);
::PostMessage(hMsgWnd, (WPARAM)pstr, (LPARAM)color);

窗口收到消息之后
CString *pstr = (CString *)WParam;
.......
delete pstr;

这里用PostMessage是怕滥用SendMessage发生锁死的现象,比如窗口在等线程结束,同时线程又在等窗口返回。
mmcanyu 2021-01-08
  • 打赏
  • 举报
回复
应该还是线程操作的问题。
打开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定位到错误行,也是莫名其妙的位置,没什么意义。
我字多,给分吧。
  • 打赏
  • 举报
回复
引用 3 楼 schlafenhamster 的回复:
检查 strLog
strLog是为了换行用的
  • 打赏
  • 举报
回复
远程调试工具安装哪个??
zgl7903 2021-01-08
  • 打赏
  • 举报
回复
试试修改下参数类型 void AddLogString(CString &strLog,COLORREF color) 调试版本, 在奔溃的机器上 安装远程调试器,远程调试下
schlafenhamster 2021-01-08
  • 打赏
  • 举报
回复
检查 strLog
  • 打赏
  • 举报
回复
对,是在子线程中有操作,调用函数如下,不过软件在有的电脑上能正常运行,在有的电脑上不能,不知道咋回事 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; }
mmcanyu 2021-01-08
  • 打赏
  • 举报
回复
线程中直接操作的吗?

15,979

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 界面
社区管理员
  • 界面
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧