Lingoes界面上的‘语言’字串可以选择不同的语言,这样导致其窗口的‘标题’不同,因此对于不同‘语言’界面的Lngoes还需要使用不同的字串传给FindWndow。这个开始还真没注意。
    另一个问题,当前没有找到好的HTML Parser,于是打算采用直接分解‘text’的方式获得结果。这样做会使结果的处理非常的‘受限’,比如如果选择了多个词典,text方式处理起来就非常麻烦了。因此当前就先采用‘text’方式,处理一个默认字典先。
    今天发现
wxSQLite3好用,和其封装MySQL++类似,又能迎合wxWidgets的类型,用起来比较顺手。今天的主要动作也是集中在LingosHook本地数据库的设计和访问接口的实现上,应该说写好了,就差合并使用了,这个明天再说吧。
    wxSQLite3相关代码如下,记录一下,下次再用wxSQLite3就有参考了。第一次用,有错误再说吧,嘿嘿~

 #include <vector>
#include <vector>

 #include "wx/wx.h"
#include "wx/wx.h"

 #include "wx/wxsqlite3.h"
#include "wx/wxsqlite3.h"

 class CDBAccess
class CDBAccess


 {
{
 public:
public:
 static const wxString TABLENAME_WORD;
    static const wxString TABLENAME_WORD;
 static const wxString TABLENAME_DICTIONARY;
    static const wxString TABLENAME_DICTIONARY;
 static const wxString TABLENAME_RESULT;
    static const wxString TABLENAME_RESULT;

 static const wxString WORDCLASS_NOUN;
    static const wxString WORDCLASS_NOUN;
 public:
public:

 enum WordClass
    enum WordClass  { WC_UNKNOWN = -1, WC_NOUN = 0 };
{ WC_UNKNOWN = -1, WC_NOUN = 0 };
 typedef std::pair<int, wxString> TResultPair;//wordclass + result
    typedef std::pair<int, wxString> TResultPair;//wordclass + result
 typedef std::vector<TResultPair> TResultVector;
    typedef std::vector<TResultPair> TResultVector;
 typedef std::pair<wxString, TResultVector> TRecordPair;//dictionary+result vector
    typedef std::pair<wxString, TResultVector> TRecordPair;//dictionary+result vector
 typedef std::vector<TRecordPair> TRecordVector;
    typedef std::vector<TRecordPair> TRecordVector;
 typedef struct _RecordData_t
    typedef struct _RecordData_t

 
     {
{
 wxString m_strWord;
        wxString m_strWord;
 wxString m_strSymbol;
        wxString m_strSymbol;
 TRecordVector m_vctResult;
        TRecordVector m_vctResult;
 wxString m_strHTML;
        wxString m_strHTML;
 } TRecordData;
    } TRecordData;
 public:
public:
 CDBAccess();
    CDBAccess();
 virtual ~CDBAccess();
    virtual ~CDBAccess();

 int Init(const wxString& dbfile);
    int Init(const wxString& dbfile);
 
    
 int Insert(const TRecordData& record);
    int Insert(const TRecordData& record);
 int Remove(const wxString& word);
    int Remove(const wxString& word);
 int Search(TRecordData& record);
    int Search(TRecordData& record);
 protected:
protected:
 int InitTables();
    int InitTables();
 void Close();
    void Close();

 int InsertWordTable(const TRecordData& record, wxLongLong& id);
    int InsertWordTable(const TRecordData& record, wxLongLong& id);
 int InsertDictTable(const wxString& dict, wxLongLong& id);
    int InsertDictTable(const wxString& dict, wxLongLong& id);
 int InsertResultTable(const wxLongLong& wordid, const wxLongLong& dictid, const TResultPair& result);
    int InsertResultTable(const wxLongLong& wordid, const wxLongLong& dictid, const TResultPair& result);

 WordClass GetWordClass(const wxString& type) const;
    WordClass GetWordClass(const wxString& type) const;

 int RemoveWordTable(const wxString& word, wxLongLong& id);
    int RemoveWordTable(const wxString& word, wxLongLong& id);
 int RemoveResultTable(const wxLongLong& wordid);
    int RemoveResultTable(const wxLongLong& wordid);

 int SearchWordTable(TRecordData& record, wxLongLong& id);
    int SearchWordTable(TRecordData& record, wxLongLong& id);
 int SearchResultTable(const wxLongLong& wordid, TRecordData& record);
    int SearchResultTable(const wxLongLong& wordid, TRecordData& record);
 const wxString SearchDictTable(const wxLongLong& dictid);
    const wxString SearchDictTable(const wxLongLong& dictid);
 protected:
protected:
 wxString _strDBFile;
    wxString _strDBFile;

 wxSQLite3Database _DB;
    wxSQLite3Database _DB;
 };
}; #include <map>
#include <map>

 #include "wx/wx.h"
#include "wx/wx.h"

 #include "DBAccess.h"
#include "DBAccess.h"


 const wxString CDBAccess::TABLENAME_WORD            =    _("WordTable");
const wxString CDBAccess::TABLENAME_WORD            =    _("WordTable");
 const wxString CDBAccess::TABLENAME_DICTIONARY        =    _("DictionaryTable");
const wxString CDBAccess::TABLENAME_DICTIONARY        =    _("DictionaryTable");
 const wxString CDBAccess::TABLENAME_RESULT            =    _("ResultTable");
const wxString CDBAccess::TABLENAME_RESULT            =    _("ResultTable");

 const wxString CDBAccess::WORDCLASS_NOUN            =    _("n.");
const wxString CDBAccess::WORDCLASS_NOUN            =    _("n.");

 CDBAccess::CDBAccess()
CDBAccess::CDBAccess()


 {
{
 }
}

 CDBAccess::~CDBAccess()
CDBAccess::~CDBAccess()


 {
{
 Close();
    Close();
 }
}

 int CDBAccess::Init(const wxString &dbfile)
int CDBAccess::Init(const wxString &dbfile)


 {
{
 try
    try

 
     {
{
 Close();
        Close();

 _DB.Open(dbfile);
        _DB.Open(dbfile);
 if(InitTables() != 0)
        if(InitTables() != 0)
 return -1;
            return -1;
 }
    }
 catch(const wxSQLite3Exception& e)
    catch(const wxSQLite3Exception& e)

 
     {
{
 return -1;
        return -1;
 }
    }
 return 0;
    return 0;
 }
}

 int CDBAccess::InitTables()
int CDBAccess::InitTables()


 {
{
 try
    try

 
     {
{
 const char* wordtable = "CREATE TABLE IF NOT EXISTS WordTable (ID INTEGER PRIMARY KEY AUTOINCREMENT,Word VARCHAR(32) UNIQUE,Symbol VARCHAR(64),HTML TEXT,UpdateTime DATE)";
        const char* wordtable = "CREATE TABLE IF NOT EXISTS WordTable (ID INTEGER PRIMARY KEY AUTOINCREMENT,Word VARCHAR(32) UNIQUE,Symbol VARCHAR(64),HTML TEXT,UpdateTime DATE)";
 _DB.ExecuteUpdate(wordtable);
        _DB.ExecuteUpdate(wordtable);
 const char* dicttable = "CREATE TABLE IF NOT EXISTS DictionaryTable (ID INTEGER PRIMARY KEY AUTOINCREMENT,Title VARCHAR(64),UpdateTime DATE)";
        const char* dicttable = "CREATE TABLE IF NOT EXISTS DictionaryTable (ID INTEGER PRIMARY KEY AUTOINCREMENT,Title VARCHAR(64),UpdateTime DATE)";
 _DB.ExecuteUpdate(dicttable);
        _DB.ExecuteUpdate(dicttable);
 const char* resulttable = "CREATE TABLE IF NOT EXISTS ResultTable (WordID INTEGER,DictID INTEGER,ClassID INTEGER,Result VARCHAR(255))";
        const char* resulttable = "CREATE TABLE IF NOT EXISTS ResultTable (WordID INTEGER,DictID INTEGER,ClassID INTEGER,Result VARCHAR(255))";
 _DB.ExecuteUpdate(resulttable);
        _DB.ExecuteUpdate(resulttable);
 }
    }
 catch(const wxSQLite3Exception& e)
    catch(const wxSQLite3Exception& e)

 
     {
{
 return -1;
        return -1;
 }
    }    

 return 0;
    return 0;
 }
}

 void CDBAccess::Close()
void CDBAccess::Close()


 {
{
 if(_DB.IsOpen())
    if(_DB.IsOpen())
 _DB.Close();
        _DB.Close();
 }
}


 int CDBAccess::Insert(const CDBAccess::TRecordData &record)
int CDBAccess::Insert(const CDBAccess::TRecordData &record)


 {
{
 try
    try

 
     {
{
 _DB.Begin();
        _DB.Begin();

 wxLongLong wordid = 0;
        wxLongLong wordid = 0;
 InsertWordTable(record, wordid);
        InsertWordTable(record, wordid);
 for(TRecordVector::const_iterator it = record.m_vctResult.begin(); it != record.m_vctResult.end(); ++ it)
        for(TRecordVector::const_iterator it = record.m_vctResult.begin(); it != record.m_vctResult.end(); ++ it)

 
         {
{
 wxLongLong dictid = 0;
            wxLongLong dictid = 0;
 InsertDictTable(it->first, dictid);
            InsertDictTable(it->first, dictid);
 for(TResultVector::const_iterator i = it->second.begin(); i != it->second.end(); ++ i)
            for(TResultVector::const_iterator i = it->second.begin(); i != it->second.end(); ++ i)

 
             {
{
 InsertResultTable(wordid, dictid, *i);
                InsertResultTable(wordid, dictid, *i);
 }
            }
 }
        }

 _DB.Commit();
        _DB.Commit();
 }
    }
 catch(const wxSQLite3Exception& e)
    catch(const wxSQLite3Exception& e)

 
     {
{
 _DB.Rollback();
        _DB.Rollback();
 return -1;
        return -1;
 }
    }
 return 0;
    return 0;
 }
}

 int CDBAccess::InsertWordTable(const CDBAccess::TRecordData &record, wxLongLong &id)
int CDBAccess::InsertWordTable(const CDBAccess::TRecordData &record, wxLongLong &id)


 {
{
 wxSQLite3Statement query = _DB.PrepareStatement("SELECT ROWID FROM WordTable WHERE Word = ?");
    wxSQLite3Statement query = _DB.PrepareStatement("SELECT ROWID FROM WordTable WHERE Word = ?");
 query.Bind(1, record.m_strWord);
    query.Bind(1, record.m_strWord);
 wxSQLite3ResultSet res = query.ExecuteQuery();
    wxSQLite3ResultSet res = query.ExecuteQuery();
 if(!res.IsOk())
    if(!res.IsOk())
 throw wxSQLite3Exception(255, _("SELECT ROWID of WordTable FAILED."));
        throw wxSQLite3Exception(255, _("SELECT ROWID of WordTable FAILED."));
 if(!res.Eof())
    if(!res.Eof())

 
     {
{
 id = res.GetInt64(0);
        id = res.GetInt64(0);
 }
    }
 else
    else

 
     {
{
 wxSQLite3Statement query = _DB.PrepareStatement("INSERT INTO WordTable VALUES(NULL, ?, ?, ?, DATETIME('NOW', 'LOCALTIME'))");
        wxSQLite3Statement query = _DB.PrepareStatement("INSERT INTO WordTable VALUES(NULL, ?, ?, ?, DATETIME('NOW', 'LOCALTIME'))");
 query.Bind(1, record.m_strWord);
        query.Bind(1, record.m_strWord);
 query.Bind(2, record.m_strSymbol);
        query.Bind(2, record.m_strSymbol);
 query.Bind(3, record.m_strHTML);
        query.Bind(3, record.m_strHTML);
 query.ExecuteUpdate();
        query.ExecuteUpdate();

 id = _DB.GetLastRowId();
        id = _DB.GetLastRowId();
 }
    }

 return 0;
    return 0;
 }
}

 int CDBAccess::InsertDictTable(const wxString& dict, wxLongLong &id)
int CDBAccess::InsertDictTable(const wxString& dict, wxLongLong &id)


 {
{
 wxSQLite3Statement query = _DB.PrepareStatement("SELECT ROWID FROM DictionaryTable WHERE Title = ?");
    wxSQLite3Statement query = _DB.PrepareStatement("SELECT ROWID FROM DictionaryTable WHERE Title = ?");
 query.Bind(1, dict);
    query.Bind(1, dict);
 wxSQLite3ResultSet res = query.ExecuteQuery();
    wxSQLite3ResultSet res = query.ExecuteQuery();
 if(!res.IsOk())
    if(!res.IsOk())
 throw wxSQLite3Exception(255, _("SELECT ROWID of DictTable FAILED."));
        throw wxSQLite3Exception(255, _("SELECT ROWID of DictTable FAILED."));
 if(!res.Eof())
    if(!res.Eof())

 
     {
{
 id = res.GetInt64(0);
        id = res.GetInt64(0);
 }
    }
 else
    else

 
     {
{
 wxSQLite3Statement query = _DB.PrepareStatement("INSERT INTO DictionaryTable VALUES(NULL, ?, DATETIME('NOW', 'LOCALTIME'))");
        wxSQLite3Statement query = _DB.PrepareStatement("INSERT INTO DictionaryTable VALUES(NULL, ?, DATETIME('NOW', 'LOCALTIME'))");
 query.Bind(1, dict);
        query.Bind(1, dict);
 query.ExecuteUpdate();
        query.ExecuteUpdate();

 id = _DB.GetLastRowId();
        id = _DB.GetLastRowId();
 }
    }

 return 0;
    return 0;
 }
}

 int CDBAccess::InsertResultTable(const wxLongLong &wordid, const wxLongLong &dictid, const TResultPair& result)
int CDBAccess::InsertResultTable(const wxLongLong &wordid, const wxLongLong &dictid, const TResultPair& result)


 {
{
 //    WordClass type = GetWordClass(result.first);
//    WordClass type = GetWordClass(result.first);
 
    
 wxSQLite3Statement query = _DB.PrepareStatement("INSERT INTO ResultTable VALUES(?, ?, ?, ?)");
    wxSQLite3Statement query = _DB.PrepareStatement("INSERT INTO ResultTable VALUES(?, ?, ?, ?)");
 query.Bind(1, wordid);
    query.Bind(1, wordid);
 query.Bind(2, dictid);
    query.Bind(2, dictid);
 query.Bind(3, result.first);
    query.Bind(3, result.first);
 query.Bind(4, result.second);
    query.Bind(4, result.second);
 query.ExecuteUpdate();
    query.ExecuteUpdate();    

 return 0;
    return 0;
 }
}

 CDBAccess::WordClass CDBAccess::GetWordClass(const wxString &type) const
CDBAccess::WordClass CDBAccess::GetWordClass(const wxString &type) const


 {
{
 if(type == WORDCLASS_NOUN)
    if(type == WORDCLASS_NOUN)
 return WC_NOUN;
        return WC_NOUN;
 else
    else
 return WC_UNKNOWN;
        return WC_UNKNOWN;
 }
}

 int CDBAccess::Remove(const wxString &word)
int CDBAccess::Remove(const wxString &word)


 {
{
 try
    try

 
     {
{
 _DB.Begin();
        _DB.Begin();
 
        
 wxLongLong wordid = 0;
        wxLongLong wordid = 0;
 RemoveWordTable(word, wordid);
        RemoveWordTable(word, wordid);
 RemoveResultTable(wordid);
        RemoveResultTable(wordid);

 _DB.Commit();
        _DB.Commit();
 }
    }
 catch(const wxSQLite3Exception& e)
    catch(const wxSQLite3Exception& e)

 
     {
{
 _DB.Rollback();
        _DB.Rollback();
 return -1;
        return -1;
 }
    }
 return 0;
    return 0;
 }
}

 int CDBAccess::RemoveWordTable(const wxString &word, wxLongLong &id)
int CDBAccess::RemoveWordTable(const wxString &word, wxLongLong &id)


 {
{
 wxSQLite3Statement query = _DB.PrepareStatement("SELECT ROWID FROM WordTable WHERE Word = ?");
    wxSQLite3Statement query = _DB.PrepareStatement("SELECT ROWID FROM WordTable WHERE Word = ?");
 query.Bind(1, word);
    query.Bind(1, word);
 wxSQLite3ResultSet res = query.ExecuteQuery();
    wxSQLite3ResultSet res = query.ExecuteQuery();
 if(!res.IsOk())
    if(!res.IsOk())
 throw wxSQLite3Exception(255, _("SELECT ROWID of WordTable FAILED."));
        throw wxSQLite3Exception(255, _("SELECT ROWID of WordTable FAILED."));
 if(!res.Eof())
    if(!res.Eof())

 
     {
{
 id = res.GetInt64(0);
        id = res.GetInt64(0);

 wxSQLite3Statement query = _DB.PrepareStatement("DELETE FROM WordTable WHERE ID = ?");
        wxSQLite3Statement query = _DB.PrepareStatement("DELETE FROM WordTable WHERE ID = ?");
 query.Bind(1, id);
        query.Bind(1, id);        
 query.ExecuteUpdate();
        query.ExecuteUpdate();
 }
    }
 else
    else

 
     {
{
 throw wxSQLite3Exception(254, _("SELECT WordTable FAILED."));
        throw wxSQLite3Exception(254, _("SELECT WordTable FAILED."));
 }
    }

 return 0;
    return 0;
 }
}

 int CDBAccess::RemoveResultTable(const wxLongLong &wordid)
int CDBAccess::RemoveResultTable(const wxLongLong &wordid)


 {
{
 wxSQLite3Statement query = _DB.PrepareStatement("DELETE FROM ResultTable WHERE WordID = ?");
    wxSQLite3Statement query = _DB.PrepareStatement("DELETE FROM ResultTable WHERE WordID = ?");
 query.Bind(1, wordid);
    query.Bind(1, wordid);        
 query.ExecuteUpdate();
    query.ExecuteUpdate();

 return 0;
    return 0;
 }
}

 int CDBAccess::Search(CDBAccess::TRecordData &record)
int CDBAccess::Search(CDBAccess::TRecordData &record)


 {
{
 try
    try

 
     {
{
 wxLongLong wordid = 0;
        wxLongLong wordid = 0;
 SearchWordTable(record, wordid);
        SearchWordTable(record, wordid);
 SearchResultTable(wordid, record);
        SearchResultTable(wordid, record);
 }
    }
 catch(const wxSQLite3Exception& e)
    catch(const wxSQLite3Exception& e)

 
     {
{
 return -1;
        return -1;
 }
    }
 return 0;
    return 0;
 }
}

 int CDBAccess::SearchWordTable(TRecordData& record, wxLongLong &id)
int CDBAccess::SearchWordTable(TRecordData& record, wxLongLong &id)


 {
{
 wxSQLite3Statement query = _DB.PrepareStatement("SELECT ROWID,Symbol FROM WordTable WHERE Word = ?");
    wxSQLite3Statement query = _DB.PrepareStatement("SELECT ROWID,Symbol FROM WordTable WHERE Word = ?");
 query.Bind(1, record.m_strWord);
    query.Bind(1, record.m_strWord);
 wxSQLite3ResultSet res = query.ExecuteQuery();
    wxSQLite3ResultSet res = query.ExecuteQuery();
 if(!res.IsOk())
    if(!res.IsOk())
 throw wxSQLite3Exception(255, _("SELECT ROWID of WordTable FAILED."));
        throw wxSQLite3Exception(255, _("SELECT ROWID of WordTable FAILED."));
 if(!res.Eof())
    if(!res.Eof())

 
     {
{
 id = res.GetInt64(0);
        id = res.GetInt64(0);
 record.m_strSymbol = res.GetAsString(1);
        record.m_strSymbol = res.GetAsString(1);
 }
    }
 else
    else 

 
     {
{
 throw wxSQLite3Exception(254, _("SELECT WordTable FAILED."));
        throw wxSQLite3Exception(254, _("SELECT WordTable FAILED."));
 }
    }

 return 0;
    return 0;
 }
}

 int CDBAccess::SearchResultTable(const wxLongLong& wordid, CDBAccess::TRecordData& record)
int CDBAccess::SearchResultTable(const wxLongLong& wordid, CDBAccess::TRecordData& record)


 {
{
 wxSQLite3Statement query = _DB.PrepareStatement("SELECT DictID, ClassID, Result FROM ResultTable WHERE wordid = ?");
    wxSQLite3Statement query = _DB.PrepareStatement("SELECT DictID, ClassID, Result FROM ResultTable WHERE wordid = ?");
 query.Bind(1, wordid);
    query.Bind(1, wordid);
 wxSQLite3ResultSet res = query.ExecuteQuery();
    wxSQLite3ResultSet res = query.ExecuteQuery();
 if(!res.IsOk())
    if(!res.IsOk())
 throw wxSQLite3Exception(255, _("SELECT ROWID of ResultTable FAILED."));
        throw wxSQLite3Exception(255, _("SELECT ROWID of ResultTable FAILED."));
 
    
 std::map<wxLongLong, TResultVector> mapResult;
    std::map<wxLongLong, TResultVector> mapResult;

        res.NextRow();//add
 while(!res.Eof())
    while(!res.Eof())

 
     {
{
 wxLongLong dictid = res.GetInt64(0);
        wxLongLong dictid = res.GetInt64(0);
 std::map<wxLongLong, TResultVector>::iterator it = mapResult.find(dictid);
        std::map<wxLongLong, TResultVector>::iterator it = mapResult.find(dictid);
 if(it == mapResult.end())
        if(it == mapResult.end())
 it = mapResult.insert(std::make_pair(dictid, TResultVector())).first;
            it = mapResult.insert(std::make_pair(dictid, TResultVector())).first;
 it->second.push_back(std::make_pair(res.GetInt(1), res.GetAsString(2)));
        it->second.push_back(std::make_pair(res.GetInt(1), res.GetAsString(2)));

 res.NextRow();
        res.NextRow();
 }
    }

 for(std::map<wxLongLong, TResultVector>::const_iterator it = mapResult.begin(); it != mapResult.end(); ++ it)
    for(std::map<wxLongLong, TResultVector>::const_iterator it = mapResult.begin(); it != mapResult.end(); ++ it)

 
     {
{
 wxString dict = SearchDictTable(it->first);
        wxString dict = SearchDictTable(it->first);
 record.m_vctResult.push_back(std::make_pair(dict, it->second));
        record.m_vctResult.push_back(std::make_pair(dict, it->second));
 }
    }

 return 0;
    return 0;
 }
}

 const wxString CDBAccess::SearchDictTable(const wxLongLong &dictid)
const wxString CDBAccess::SearchDictTable(const wxLongLong &dictid)


 {
{
 wxSQLite3Statement query = _DB.PrepareStatement("SELECT Title FROM DictionaryTable WHERE ID = ?");
    wxSQLite3Statement query = _DB.PrepareStatement("SELECT Title FROM DictionaryTable WHERE ID = ?");
 query.Bind(1, dictid);
    query.Bind(1, dictid);
 wxSQLite3ResultSet res = query.ExecuteQuery();
    wxSQLite3ResultSet res = query.ExecuteQuery();
 if(!res.IsOk())
    if(!res.IsOk())
 return _("FAILED.");
        return _("FAILED.");
 if(res.Eof())
    if(res.Eof())
 return _("Unknown.");
        return _("Unknown.");
 return res.GetAsString(0);
    return res.GetAsString(0);
 }
}