异想天开

What's the true meaning of light, Could you tell me why

族谱软件日志

日期:2014-01-12 23:56:10
  
最后更新日期:2014-01-13 00:07:54
当你最害怕的事却最终发生了,这个软件算是前后写了三次,由于代码没有备份,没有记一些技术笔记,导致后面又花了同样的时间来做重复的事。这曾让我很苦恼。后来遂养成了记笔记和备份的习惯。该软件主要实现的功能是将族谱信息用word报表呈现,主要的技术点为MFC和word的类型库。当然这篇日志会记录一些windows开发用的到的常识,因为笔者工作中并不做windows开发,故该找个地方放下,嘿嘿。
1.新建完MFC工程就是要导入word类型库,我的理解就是,微软定义了一套应用程序通信的接口,那么理所当然按这套接口实现的程序,别的程序就可以与它按这套接口通信。复杂的概念且不论,那些名与相的东西着实会让人糊涂。导入方式:点击菜单栏<查看>->MFC创建向导->增加类,选择from a type libary。然后路径选择你安装office路径中word的目录,我的目录地址是:
C:\Program Files\Microsoft Office\OFFICE11\msword.olb
1 选择导入的类,第一次使用全部选上就是。
Image2
2.word 类型库编程接口
这里word的类型库,提供的是用com的一个接口,当然实话说,com我也不太懂,所以也不想由此变的高大上。我也是使用MFC导入过来,产生msword.cpp文件以及msword.h文件。这两个文件有一些基本的类的是要稍微点出名字的。
[code lang="cpp"]
_Application m_hApp; //word程序
_Document m_hDoc; //操作的文档
Documents m_hDocs; //word程序打开的文档集合
Selection m_hSel; //选择对象
Range m_hRge; //当前操作区域
[/code]
与此相关的资料大多杂而不全,这里当然选择很重要,如果你用vb开发,那么直接用录制宏的功能就应该可以知道怎么使用了,如果你用c#也比较好,微软官网都有使用例子。如果你也是用MFC,那么注定要费一些周折。下面的例子,没有列举很多,如果读者有需要使用例程,可以发邮件过来索要(dream # thinks-bz.com)。

2.1打开word
[code lang="cpp"]
_Application m_hApp;
//打开word程序
if ( !m_hApp.CreateDispatch("word.Application") )
{
AfxMessageBox("打开word失败!");
CoUninitialize();
return ;
}
m_hApp.SetVisible(m_bVisible);
[/code]
2.2退出word
[code lang="cpp"]
CComVariant vOption(DISP_E_PARAMNOTFOUND,VT_ERROR) ;
CComVariant SaveChanges(false),OriginalFormat,RouteDocument;
::VariantInit(&OriginalFormat);
RouteDocument.vt = VT_EMPTY ;
m_hApp.Quit(&SaveChanges,&OriginalFormat,&RouteDocument);
[/code]

2.3保存word
[code lang="cpp"]
CComVariant vOption(DISP_E_PARAMNOTFOUND,VT_ERROR) ;
CComVariant FileName(filepath.c_str());
CComVariant FileFormat(0);
CComVariant LockComments(false),Password(_T(""));
CComVariant AddToRecentFiles(true),WritePassword(_T(""));
CComVariant ReadOnlyRecommended(false),EmbedTrueTypeFonts(false);
CComVariant SaveNativePictureFormat(false),SaveFormsData(false);
CComVariant SaveAsAOCELetter(false);
m_hDoc.SaveAs(&FileName,&FileFormat,&LockComments,&Password,&AddToRecentFiles,&WritePassword,&ReadOnlyRecommended,
&EmbedTrueTypeFonts,&SaveNativePictureFormat,&SaveFormsData,&SaveAsAOCELetter,
&vOption,&vOption,&vOption,&vOption,&vOption);
[/code]
注:
这里会用到两个类型CComVariant以及COleVariant,可以看出这两种类型既可以放整数,字符串,布尔类型。

2.4添加文档
[code lang="cpp"]
Documents docs ;
CComVariant vTm(_T("")),nTm(false),vTrue(TRUE),VFalse(FALSE);
CComVariant vOption(DISP_E_PARAMNOTFOUND,VT_ERROR) ;
docs = m_hApp.GetDocuments();
docs.Add(&vTm,&nTm,&vOption,&vOption);
m_hDoc = m_hApp.GetActiveDocument();
docs.ReleaseDispatch();
[/code]

2.5插入表格
[code lang="cpp"]
CComVariant vOption(DISP_E_PARAMNOTFOUND,VT_ERROR);
Tables tables = m_hDoc.GetTables();
GetCurRge();
tables.Add(m_hRge,m_iRows,m_iCols,&vOption,&vOption);
Table table ;
int index = tables.GetCount();
CComVariant crow(2),ccol(1);
table = tables.Item(index);
[/code]
3.连接数据库,我使用的是微软的数据源的方式。MFC中使用数据库。项目工程头文件stdafx.h包含头文件afxdb.h ,即可使用mfc框架的类
[code lang="cpp"]
CDatabase db;
CString str ;
str = "ODBC;DSN=";
str += Odbc ; //Odbc为数据源的字符串
db.Open(str);
// 类似这样的字符串 db.OpenEx(TEXT("Driver={MySQL ODBC 3.51 Driver};Server=127.0.0.1;Port=3306;Database=TEST;User=root; Password=root;Option=3;"), CDatabase::openReadOnly))
CString father;
CRecordset rst(&db);
sql = "SELECT * FROM tbl_node where nodeid = " ;
sql += root ;
rst.Open(CRecordset::forwardOnly,sql);
rst.GetFieldValue("parentid",father);
[/code]
4.vc基础
正如前文所讲,这是一篇笔记,我希望藉由此文能够找到使用vc的感觉,所以在此记一个看似无关的。
vc方式获得控件的输入值
[code lang="cpp"]
hWnd->GetDlgItemText(IDC_NAME1,name1);
hWnd->GetDlgItemText(IDC_NAME2,name2);
BOOL flag ;
pai = hWnd->GetDlgItemInt(IDC_PAI,&flag );

MFC只有设置该控件为CEIDT就行
比如 class { m_edit;};
CString str;
m_edit.GetWindowText(str);

直接用vc 应该是通过id得到窗口
GetDialogItem(ID_**)->;
[/code]
5.问题解决
5.1 odbc连接数据库的使用出现乱码。我以为数据乱码问题应该不会再遇到了,结果还是不能幸免。当然是由于使用odbc连接数据库时,数据源驱动不是最新的。我使用odbc 5.1去连接mysql 5.6.1。这里讲一下分析思路:
[code lang="cpp"]
show variables like "%char%";
+--------------------------+--------
| Variable_name | Value
+--------------------------+--------
| character_set_client | utf8
| character_set_connection | utf8
| character_set_database | utf8
| character_set_filesystem | binary
| character_set_results | utf8
| character_set_server | latin1
| character_set_system | utf8
[/code]
这里character_set_database表示数据库用什么方式存放,可以select charset(name) from tblname 来查看表使用的编码。character_set_connection表示连接层使用编码方式,character_set_client表示客户端使用的方式。在这里我遇到过两个问题。当客户端使用utf8时,那么你source db.sql这来执行sql脚本时,需要确保sql脚本式utf8编码。其他编码类似。
5.2 odbc连接乱码
当然一开始,我还以为是问题一,找那样的方法尝试了,不管用,后来网上有人说是odbc驱动问题。我立马用程序将从数据库得到的结果打印,打印出来是乱码。所以后来更新了驱动odbc 5.2,选择了gbk编码,odbc是不能选择的。

5.3运行环境起不来
当时给人使用的时候,程序怎么点都没有反应,我在自己的win8电脑上测试也打不开,当时也没在意,因为程序是xp下编译的。在给他尝试了几种方法后,无效。后来突然想到用windbg在我电脑上跟踪一下,发现程序死在加载common ctrol的dll。我立马想到了我使用到了ado与microsoft datagrid control sp6.0控件来做数据库显示结果。网上找到解决方法:
1. 先到C:\WINDOWS\system32目录下看看你的系统里是否已经有了MSADODC.ocx和MSDATGRD.ocx这两个文件,没有就去下载, 下载下来这两个文件后放到C:\WINDOWS\system32目录下;
2.注册MSADODC.ocx和MSDATGRD.ocx这两个控件。 方法是打开命令提示符窗口,输入如下命令: regsvr32 msadodc.ocx 回车regsvr32 msdatgrd.ocx回车
后来这样果然可以使用了。
最终效果图:
Image3