CRichEditCtrl和数据库交互!

exceed_me 2009-11-12 04:11:37
怎样才能把 CRichEditCtrl 控件当前选中的或者全部的内容,包括格式化的文本,图形图像,Ole 对象等存储到数据库中,比如 Access 中,然后需要的时候又可以从数据库中读取显示到 CRichEditCtrl 中,我本来想生成一个 RTF 文件,然后把 RTF 文件存储到数据库中,但这样太占用空间,而且读取速度是不是也会跟不上啊,我想应该有直接存储和读取的方法的吧,先谢谢大家了!
...全文
529 18 打赏 收藏 转发到动态 举报
写回复
用AI写文章
18 条回复
切换为时间正序
请发表友善的回复…
发表回复
passionHard 2011-12-08
  • 打赏
  • 举报
回复
如何才能把数据库里的全部读取出来而不是一条一条的呢,就像QQ的聊天记录那样、、、、盼解答
exceed_me 2011-12-08
  • 打赏
  • 举报
回复
[Quote=引用 17 楼 passionhard 的回复:]

如何才能把数据库里的全部读取出来而不是一条一条的呢,就像QQ的聊天记录那样、、、、盼解答
[/Quote]

额,遍历数据库啊,全部显示!
passionHard 2011-12-07
  • 打赏
  • 举报
回复
数据库里的读不进去的说、、楼主有啥解决办法么、、就是用你的示例啊
狂风暴雨 2011-06-01
  • 打赏
  • 举报
回复

CString user=GetUserName();
CAdo ado;
CString username,password,id,text;
CString sTime,sYear,sMonth,sDay;
ado.InitADOConn(); //建立连接
CString sql1,sql2;
sql1="SELECT [MemId] FROM [TL_Member] WHERE UserName='" + user+"'";
ado.m_pRecordset=ado.OpenRecordset(sql1); //获得MemId记录集
id=(char*)(_bstr_t)ado.m_pRecordset->GetCollect("MemId"); //获得MemId
m_Log.GetWindowText(text);
if (text.IsEmpty())
{
MessageBox("日志不能为空!");
return ;
}


测试下。。
狂风暴雨 2011-06-01
  • 打赏
  • 举报
回复
{0}
int main()
{
printf("hello world");
return 0;
}
{1}
havocbs1987 2011-05-11
  • 打赏
  • 举报
回复
楼主真是辛苦了!小弟们非常感谢!
exceed_me 2009-11-18
  • 打赏
  • 举报
回复
我已经把写好的例子上传到下载中心了,http://download.csdn.net/source/1826843,可以下载察看,比我这样说更加容易理解吧。。。

不好意思,晚了一天,我把实现功能的主要代码贴一下,把 RTF 数据写入数据库,这里是 access ,和 sb3day 的差不多,只是我是直接把数据流存进数据库,而没有通过文件这一中介,这个很简单,对于从数据库中提取数据并显示,其实就是 RichEdit 显示 RTF 文件的问题,我用的是http://www.codeproject.com/KB/edit/COleRichEditCtrl.aspx 这里的这个例子,这个例子很有名,说的就是怎样把 RTF 文件读取并显示到 RichEdit 上,感谢他,我改写了 StreamInFromResource 函数,让它可以直接从内存数据显示其内容,就这样,主要是那位作者的类写的好,我自己很清楚自己几斤几两,COM 的知识基本不知道,所以只能这样看看别人的。然后很可能会出现复制不起作用,所以要改写一下 COleRichEditCtrl::IExRichEditOleCallback::GetClipboardData 函数,让它返回 E_NOTIMPL 而不是S_OK 就可以了
HRESULT STDMETHODCALLTYPE 
COleRichEditCtrl::IExRichEditOleCallback::GetClipboardData(CHARRANGE FAR *lpchrg, DWORD reco, LPDATAOBJECT FAR *lplpdataobj)
{
return E_NOTIMPL;
}

别的么为了给他增加右键弹出式菜单,所以增加了
afx_msg void OnCopy() { Copy(); }
afx_msg void OnCut() { Cut(); }
afx_msg void OnPaste() { Paste(); }
afx_msg void OnSelectall() { SetSel(0, -1); }
afx_msg void OnUndo() { Undo(); }
afx_msg void OnClear() { Clear(); }
afx_msg void OnSelectFont();

别的么没有改动他的那个类 COleRichEditCtrl
保存数据到数据库,我还是用了文件作为中介,为什么呢,因为 MyStreamOutCallback 函数进行 RichEdit 内的内容输出的时候,一次只输出 4095 字节,它会自己调用若干次,所以用了文件作为中介,让它先把所有数据写入文件完成,再打开文件读取数据,当然了,我想用一个内存区进行连续的读写,每次分配 4095 字节,然后让它一直增加下去,但是由于自己能力不足,弄不出来,哪位高手指点一下,就是这样

void CRichEditDBDlg::DatabaseOperate(int nItem, int nType)
{
CString strNum;
strNum.Format("%d",nItem);

CString sql;

m_pRecord.CreateInstance(__uuidof(Recordset));

if ( nType == 0 )
sql = "select * from info order by id";
else
sql.Format("select * from info where id = '%d'",nItem);

try
{
m_pRecord->Open((_bstr_t)sql,m_pCon.GetInterfacePtr(),adOpenDynamic,adLockOptimistic,adCmdText);

DWORD fileLen;
CFile cFile;
cFile.Open("tmp.rtf",CFile::modeRead);
fileLen = cFile.GetLength();
char *pbBuff = new char[fileLen];
cFile.ReadHuge(pbBuff,fileLen);
cFile.Close();

//保存 Ole 数据到数据库
VARIANT m_VarData;

m_VarData.vt = VT_UI1|VT_ARRAY;
SAFEARRAY *m_pSafe;
SAFEARRAYBOUND bound;
bound.cElements = fileLen;
bound.lLbound = 0;

m_pSafe = ::SafeArrayCreate(VT_UI1,1,&bound);

for ( LONG i = 0;i < fileLen ; i++ )
::SafeArrayPutElement(m_pSafe,&i,pbBuff ++);

m_VarData.parray = m_pSafe;

if ( nType == 0 )
{
m_pRecord->AddNew();

m_pRecord->GetFields()->GetItem("id")->Value = (_bstr_t)strNum;
m_pRecord->GetFields()->GetItem("explain")->Value = (_bstr_t)("第" + strNum + "条数据");
}

m_pRecord->GetFields()->GetItem("rtf")->AppendChunk(&m_VarData);
m_pRecord->Update();
}
catch(_com_error e)
{
::MessageBox(NULL,e.Description(),"错误",MB_ICONERROR);
}

if ( nType == 0 )
::MessageBox(NULL,"插入成功","提示",MB_ICONASTERISK);
else
::MessageBox(NULL,"修改成功","提示",MB_ICONASTERISK);

m_pRecord.Release();
}


void CRichEditDBDlg::OnItemchangedList(NMHDR* pNMHDR, LRESULT* pResult)
{
NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;

int nSel = m_List.GetSelectionMark();

CString sql;
sql.Format("select * from info where id = '%d'",nSel);

m_pRecord.CreateInstance(__uuidof(Recordset));

try
{
m_pRecord->Open((_bstr_t)sql,m_pCon.GetInterfacePtr(),adOpenDynamic,adLockOptimistic,adCmdText);
}
catch(_com_error e)
{
MessageBox(e.Description(),"错误",MB_ICONERROR);
}

LONG lDatasize = m_pRecord->GetFields()->GetItem("rtf")->ActualSize;

if(lDatasize>0)
{
_variant_t m_bitData;

char *m_pBuff;
m_bitData = m_pRecord->GetFields()->GetItem("rtf")->GetChunk(lDatasize);

if(m_bitData.vt == (VT_UI1|VT_ARRAY))
{
if(m_pBuff = new char[lDatasize + 1])
{
memset(m_pBuff,0,lDatasize + 1);
char *pBuff = NULL;
::SafeArrayAccessData(m_bitData.parray,(void**)&pBuff);
memcpy(m_pBuff,pBuff,lDatasize);
::SafeArrayUnaccessData(m_bitData.parray);

m_RichEditCtrl.StreamInFromResource(lDatasize,(BYTE *)m_pBuff);
}
}

}

*pResult = 0;
}

exceed_me 2009-11-16
  • 打赏
  • 举报
回复
无意间在网上找到了一些资料,终于解决了复制,粘贴问题,待我整理一下,明天贴代码!
exceed_me 2009-11-16
  • 打赏
  • 举报
回复
[Quote=引用 9 楼 sb3day 的回复:]
复制、贴之类不用解决吧,直接RichEdit自己就实现了
楼主加油,成功了把代码贴出来,数据库到RichEdit不经过文件直接转换
[/Quote]

不行的,复制,粘贴不行的,很麻烦的我查了下,也就是这个还未实现,所以我迟迟没有贴代码!正在进行中,想直接用 CRichEditView 算了,这个类直接支持很多的功能,但是东西是封装在内部的,看又看不到,又麻烦,我继续!
sb3day 2009-11-16
  • 打赏
  • 举报
回复
复制、贴之类不用解决吧,直接RichEdit自己就实现了
楼主加油,成功了把代码贴出来,数据库到RichEdit不经过文件直接转换
exceed_me 2009-11-15
  • 打赏
  • 举报
回复
[Quote=引用 7 楼 cphj 的回复:]
看来这个问题快解决了
[/Quote]

还没有完全解决,对于 RichEdit 中的复制、贴之类的(包括 Ole 对象)还没办法实现!
cphj 2009-11-15
  • 打赏
  • 举报
回复
看来这个问题快解决了
exceed_me 2009-11-14
  • 打赏
  • 举报
回复
我已经基本实现了想要的效果了,就是 RichEdit 里的内容,包括 Ole 图片对象,存入数据库,然后从数据库中提取出来,显示在 RichEdit 中,待我把它完善一下,就把代码贴出来,也就是利用 RichEdit 生成 RTF 数据,不生成文件了,直接把数据存入数据库,然后提取的时候,发现提取出来后的数据生成文件后是符合 RTF 文件格式的,在数据库中存储的是二进制数据,然后显示出来就可以了,就是 RTF 文件显示到 RichEdit 上,这个可以参考一下 codeproject 上的一篇文章,http://www.codeproject.com/KB/edit/COleRichEditCtrl.aspx!
exceed_me 2009-11-13
  • 打赏
  • 举报
回复
另外,有没有哪位高人能够指点一下的,我想这个技术应该是已经是实现了的!
exceed_me 2009-11-13
  • 打赏
  • 举报
回复
to sb3day:
恩,我看到你的那份帖子了,我想了想,思路大概可以这样子做,其实呢,我觉得没必要把 RichEdit 里的内容先写入 rtf ,再从 rtf 文件中读取数据然后存入到数据库,可以直接把数据写入数据库,而不是先写入文件,再从文件读取数据,再写入数据库,然后从数据库读取数据显示到 RichEdit 也一样,本身都是处理数据么,我觉得没必要用 rtf 文件作为中介。
对于数据从数据库中其提出来显示到 RichEdit 中,我查了些资料,说是 rtf 文件有其自身的格式,和 HTML 类似吧我觉得,控制格式的,可以用 UltraEdit 打开看看的。
我想你可以这样尝试一下,把从数据库中提取出来的数据,写入 rtf 文件,看看这个 rtf 文件是不是还是符合 rtf 格式的,如果是,那就好办了,如果不是,看来要和昨天看到的一篇文章挂起沟了,里面说 access 存储 ole 对象时,在这里是 rtf 文档,会在前面多加入控制的数据,所以提取的数据写入文件后就不是原来的符合 rtf 格式的文件了,而是在前面加了一些多余的控制信息的,这样的话要先把前面的这些数据先去掉的。我也会抓紧时间测试一下的。
//PS:因为下午要和我老师去趟上海了,所以先发表一下自己的看法,具体的还没有做测试,有时间我一定会试一下的,但是我担心的话这样子存取数据库再显示的话,时间上是不是会产生比较大的延时,个人见解,如果你觉得有尝试的必要性的话,你可以先尝试一下,我也会抓紧时间去试一下的。
wshcdr 2009-11-12
  • 打赏
  • 举报
回复
MK
sb3day 2009-11-12
  • 打赏
  • 举报
回复
这个问题我也想知道,查了很多时间,最后只能用文件保存到Ole 对象,读取数据库的时候先在temp文件夹里生成rtf文件,再发rtf文件读取到RichEditView
DWORD CALLBACK CENBView::MyStreamInCallback(DWORD dwCookie, LPBYTE pbBuff, LONG cb, LONG *pcb)//读取
{
CFile* pFile = (CFile*) dwCookie;
ASSERT_KINDOF(CFile,pFile);
*pcb = pFile->Read(pbBuff, cb);
return 0;
}
DWORD CALLBACK CENBView::MyStreamOutCallback(DWORD dwCookie,LPBYTE pbBuff, LONG cb, LONG *pcb)//输出
{
CFile* pFile = (CFile*) dwCookie;
pFile->Write(pbBuff, cb);
*pcb = cb;
return 0;
}

BOOL CENBView::OnMySave()
{
CMainFrame* m_pMf=(CMainFrame*)AfxGetApp()->GetMainWnd();
CFile fis;
TCHAR tmpPath[_MAX_PATH+1];
GetTempPath(_MAX_PATH,tmpPath);
CString str_FileName;
long l_tempTreeID=m_pMf->m_wndTree.GetCurTreeID();
str_FileName.Format("%s%ld.tmp",tmpPath,l_tempTreeID);
fis.Open(str_FileName, CFile::modeCreate | CFile::modeWrite);
// fis.Open("C:\\a.rtf", CFile::modeRead | CFile::shareExclusive );
EDITSTREAM es;
es.dwCookie = (DWORD) &fis;
es.pfnCallback = MyStreamOutCallback;

CRichEditCtrl &m_edit = GetRichEditCtrl();
m_edit.StreamOut(SF_RTF, es);
CString str_sql; // I put the content in the file
fis.Close();

ADO &myado=theApp.m_Ado;
CENBDoc* m_pENBDoc=(CENBDoc*)m_pMf->GetActiveDocument();
if(!myado.OnInitADO(m_pENBDoc->GetPathName()))
{
AfxMessageBox("init ado出错!"+m_pENBDoc->GetPathName());
//return 0;
}
myado.m_pRecordset.CreateInstance(__uuidof(ADODB::Recordset));
str_sql.Format("select d_content,d_contentTxt from T_Tree WHERE D_TREEID=%ld",l_tempTreeID);
myado.m_pRecordset->Open((_variant_t)str_sql,myado.m_pConnection.GetInterfacePtr(),ADODB::adOpenDynamic,ADODB::adLockOptimistic,ADODB::adCmdText);
try
{
//m_pRecordset->AddNew();//添加新行
VARIANT m_bitdata;
fis.Open(str_FileName,CFile::modeRead);
DWORD m_filelen = fis.GetLength()+1;
char * m_bitbuffer = new char[m_filelen];
fis.ReadHuge(m_bitbuffer,m_filelen);
// fis.Flush();//
fis.Close();
DeleteFile(str_FileName);//删除
m_bitdata.vt= VT_ARRAY|VT_UI1;
SAFEARRAY * m_psafe;
SAFEARRAYBOUND m_band;
m_band.cElements = m_filelen;
m_band.lLbound = 0;
m_psafe = SafeArrayCreate(VT_UI1,1,&m_band);
for(long i=0; i < m_filelen ; i++)
{
SafeArrayPutElement(m_psafe,&i,m_bitbuffer++);
}
m_bitdata.parray = m_psafe;
myado.m_pRecordset->GetFields()->GetItem("d_content")->AppendChunk(&m_bitdata);
CString str_temp;
GetWindowText(str_temp);
myado.m_pRecordset->GetFields()->GetItem("d_contentTxt")->Value=(_bstr_t)str_temp;
myado.m_pRecordset->Update();
}
catch(_com_error e)
{
AfxMessageBox("操作失败:\n"+e.Description());
return 0;
}
CENBDoc *m_pEditDoc = (CENBDoc *)m_pMf->GetActiveDocument();
m_pEditDoc->SetModifiedFlag(0);
m_pMf->m_wndStatusBar.SetPaneText(0,"保存成功!");
// MessageBox("保存成功!",NULL,64);
return 1;
}

void CENBView::SetRtf(CFile* pInputFile )
{
EDITSTREAM es;
es.dwError = 0;
es.pfnCallback = MyStreamInCallback;
es.dwCookie = (DWORD)pInputFile;
CRichEditCtrl &m_edit = GetRichEditCtrl();
m_edit.StreamIn(SF_RTF, es);
}


BOOL CCoolTreeCtrl::OnTree2Rich()//点Tree跳到RichEditView显示出来
{
CMainFrame* m_pMf=(CMainFrame*)AfxGetApp()->GetMainWnd();
ADO &myado=theApp.m_Ado;
CString str_sql,str_FileName;
// myado.OnInitADO();
long l_TreeID=GetCurTreeID();
str_sql.Format("Select D_CONTENT FROM T_TREE WHERE d_TREEID=%ld",l_TreeID);
TCHAR tmpPath[_MAX_PATH+1];
GetTempPath(_MAX_PATH,tmpPath);

str_FileName.Format("%s%ld.tmp",tmpPath,l_TreeID);
myado.m_pRecordset=myado.GetRecordSet((_bstr_t)str_sql);
long lDataSize = myado.m_pRecordset->GetFields()->GetItem("D_CONTENT")->ActualSize;
char *m_pBuffer; //定义缓冲变量
// CENBDoc *m_pEditDoc = (CENBDoc *)m_pMf->GetActiveView()->GetDocument();//GetActiveDocument();
if(lDataSize > 0)
{
_variant_t varBLOB;
varBLOB = myado.m_pRecordset->GetFields()->GetItem("D_CONTENT")->GetChunk(lDataSize);
if(varBLOB.vt == (VT_ARRAY | VT_UI1))
{
if(m_pBuffer = new char[lDataSize+1]) //分配必要的存储空间
{
char *pBuf = NULL;
SafeArrayAccessData(varBLOB.parray,(void **)&pBuf);
memcpy(m_pBuffer,pBuf,lDataSize); //复制数据到缓冲区m_pBuffer
SafeArrayUnaccessData (varBLOB.parray);

CFile file;
file.Open(str_FileName, CFile::modeCreate | CFile::modeWrite);
file.Write(m_pBuffer,lDataSize);
file.Close();
// CFile fis(str_FileName,CFile::modeRead);
file.Open(str_FileName,CFile::modeRead);
CENBView *m_pEditView = (CENBView *)m_pMf->GetActiveView();
m_pEditView->SetRtf(&file);
// fis.Flush();
file.Close();
DeleteFile(str_FileName);
m_pMf->GetActiveDocument()->SetModifiedFlag(0);
}
}
}
else
{
m_pMf->GetActiveDocument()->OnNewDocument();//DeleteContents
}
return 1;
}

http://topic.csdn.net/u/20091022/16/78c9be49-54ba-466f-a94a-8b84e5f43bb3.html
雪影 2009-11-12
  • 打赏
  • 举报
回复
你这个问题问得返回太大了.
涉及到的东西真不少

3,245

社区成员

发帖
与我相关
我的任务
社区描述
ATL,Active Template Library活动(动态)模板库,是一种微软程序库,支持利用C++语言编写ASP代码以及其它ActiveX程序。
社区管理员
  • ATL/ActiveX/COM社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

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