BEGIN_MESSAGE_MAP(...
消息映射宏的一部分。
ON_WM_CREATE()产生一个消息处理函数映射项目,把WM_CREATE和OnCreate函数联系起来。
参数的个数和类型是系统已经定义好的。
ON_COMMAND(ID_FILE_NEW,CWinApp::OnFileNew)是把 ID_FILE_NEW 与OnFileNew 联系起来吗
BEGIN_MESSAGE_MAP(参数1,参数2)
参数1:当前类;参数2:在消息映射中处于上一层的类。
参数2 是参数1 的父类了.
通常是,但是未必是。如果父类没有消息映射,则应该映射到父类的第一个有消息映射的基类。
MFC不想用一堆虚函数(全用虚函数会产生一个很大的vtable,开销太大,而且现在虚函数已经很多了)来处理每个消息,而是使用消息映射,把需要自己处理的消息映射到处理函数。
// 用于应用程序“关于”菜单项的 CAboutDlg 对话框 class CAboutDlg : public CDialogEx { public: CAboutDlg(); // 对话框数据 enum { IDD = IDD_ABOUTBOX }; protected: virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV 支持 // 实现 protected: DECLARE_MESSAGE_MAP() }; CAboutDlg::CAboutDlg() : CDialogEx(CAboutDlg::IDD) { } void CAboutDlg::DoDataExchange(CDataExchange* pDX) { CDialogEx::DoDataExchange(pDX); } BEGIN_MESSAGE_MAP(CAboutDlg, CDialogEx) END_MESSAGE_MAP()
// Test1Dlg.cpp : implementation file // #include "stdafx.h" #include "Test1.h" #include "Test1Dlg.h" #include "afxdialogex.h" #include "expat.h" #include "sqlite3.h" #include <iostream> #include <string> #include <vector> #include <stack> #include <cassert> #ifdef _DEBUG #define new DEBUG_NEW #endif #define NODE_ORG (0) // ORG #define NODE_VIEW (1) // View #define NODE_GROUP (2) // Group #define NODE_USER (3) // User list <string> g_IdList; // 保存各级的ID,是一个栈的模式开始标记时添加,结束标记时删除 sqlite3 *g_db = NULL; void TableInit(); void InsertTable(int Id, char* NameValue, int ParentId, char* NodeName); //HTREEITEM HtParent; CString t_name; // CAboutDlg dialog used for App About class CAboutDlg : public CDialogEx { public: CAboutDlg(); // Dialog Data enum { IDD = IDD_ABOUTBOX }; protected: virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support // Implementation protected: DECLARE_MESSAGE_MAP() }; CAboutDlg::CAboutDlg() : CDialogEx(CAboutDlg::IDD) { } void CAboutDlg::DoDataExchange(CDataExchange* pDX) { CDialogEx::DoDataExchange(pDX); } BEGIN_MESSAGE_MAP(CAboutDlg, CDialogEx) END_MESSAGE_MAP() // CTest1Dlg dialog CTest1Dlg::CTest1Dlg(CWnd* pParent /*=NULL*/) : CDialogEx(CTest1Dlg::IDD, pParent) { m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME); } void CTest1Dlg::DoDataExchange(CDataExchange* pDX) { CDialogEx::DoDataExchange(pDX); DDX_Control(pDX, IDC_TREE1, m_CTreeCtrl); } BEGIN_MESSAGE_MAP(CTest1Dlg, CDialogEx) ON_WM_SYSCOMMAND() ON_WM_PAINT() ON_WM_QUERYDRAGICON() ON_BN_CLICKED(IDC_BN_LOAD, &CTest1Dlg::OnBnClickedBnLoad) ON_BN_CLICKED(ID_DISPLAY, &CTest1Dlg::OnBnClickedDisplay) ON_NOTIFY(TVN_ITEMEXPANDING, IDC_TREE1, &CTest1Dlg::OnDblClkTree) //子项目列表正将展开或收起 //ON_NOTIFY(TVN_GETDISPINFO, IDC_TREE1, &CTest1Dlg::OnDblClkTree) //子项目列表被展开或收起 ON_WM_RBUTTONDBLCLK() ON_WM_NCLBUTTONDBLCLK() END_MESSAGE_MAP() // CTest1Dlg message handlers BOOL CTest1Dlg::OnInitDialog() { CDialogEx::OnInitDialog(); // Add "About..." menu item to system menu. // IDM_ABOUTBOX must be in the system command range. ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX); ASSERT(IDM_ABOUTBOX < 0xF000); CMenu* pSysMenu = GetSystemMenu(FALSE); if (pSysMenu != NULL) { BOOL bNameValid; CString strAboutMenu; bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX); ASSERT(bNameValid); if (!strAboutMenu.IsEmpty()) { pSysMenu->AppendMenu(MF_SEPARATOR); pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu); } } // Set the icon for this dialog. The framework does this automatically // when the application's main window is not a dialog SetIcon(m_hIcon, TRUE); // Set big icon SetIcon(m_hIcon, FALSE); // Set small icon // TODO: Add extra initialization here return TRUE; // return TRUE unless you set the focus to a control } void CTest1Dlg::OnSysCommand(UINT nID, LPARAM lParam) { if ((nID & 0xFFF0) == IDM_ABOUTBOX) { CAboutDlg dlgAbout; dlgAbout.DoModal(); } else { CDialogEx::OnSysCommand(nID, lParam); } } // If you add a minimize button to your dialog, you will need the code below // to draw the icon. For MFC applications using the document/view model, // this is automatically done for you by the framework. void CTest1Dlg::OnPaint() { if (IsIconic()) { CPaintDC dc(this); // device context for painting SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0); // Center icon in client rectangle int cxIcon = GetSystemMetrics(SM_CXICON); int cyIcon = GetSystemMetrics(SM_CYICON); CRect rect; GetClientRect(&rect); int x = (rect.Width() - cxIcon + 1) / 2; int y = (rect.Height() - cyIcon + 1) / 2; // Draw the icon dc.DrawIcon(x, y, m_hIcon); } else { CDialogEx::OnPaint(); } } // The system calls this function to obtain the cursor to display while the user drags // the minimized window. HCURSOR CTest1Dlg::OnQueryDragIcon() { return static_cast<HCURSOR>(m_hIcon); } void startElement(void *userdata, const char *name, const char **atts) { // 处理根节点情况 if (name == string("ORG")) { InsertTable(0, "ORG", -1, ""); g_IdList.push_front("0"); // 进栈一个“0” } else // 一般情况 { string NodeId = atts[3]; string pID = g_IdList.front(); // 父亲节点ID就是ID栈的前面第一个元素 char* NodeName = const_cast<char*>(atts[1]); InsertTable(atoi(NodeId.c_str()), NodeName, atoi(pID.c_str()), const_cast<char*>(name)); g_IdList.push_front(atts[3]); // 当前ID进栈 } return; } void endElement(void *userdata, const char *name) { g_IdList.pop_front(); // ID出栈 return; } void CTest1Dlg::OnBnClickedBnLoad() { // TODO: Add your control notification handler code here char buf[1024] = {0}; int nRead = 0; FILE *fp = NULL; XML_Parser parser; int done; int depth = 0; void *userData; const char *name; const char **atts; fp = fopen("E:\org.xml","r"); if(fp == NULL) return; TableInit();//初始化表结构 parser = XML_ParserCreate(NULL); XML_SetUserData(parser, &depth); XML_SetElementHandler(parser, startElement, endElement); do { nRead = fread(buf, sizeof(char),1024, fp); if(nRead == 0) break; else if(nRead == 1024) done = 0; else done = 1; if(XML_Parse(parser, buf, nRead, done) == XML_STATUS_ERROR) { return; } }while(!done); XML_ParserFree(parser); fclose(fp); return; } //初始化表结构 void TableInit() { int rc = sqlite3_open("xml.db", &g_db); if (rc) { fprintf(stderr, "can't open db! ", sqlite3_errmsg(g_db)); sqlite3_close(g_db); exit(1); } else { printf("db open successfully! "); } sqlite3_exec(g_db, "CREATE TABLE XMLDATA(INT NODEID PRIMARY KEY, NAMEVALUE VARCHAR(20) NOT NULL, PARENTID INT DEFAULT NULL, NODENAME VARCHAR(10));", 0, 0, 0); return; } // 插入数据到数据库中的XMLDATA表中 void InsertTable(int Id, char* NameValue, int ParentId, char* NodeName) { char sql[200] = ""; sprintf(sql, "INSERT INTO XMLDATA VALUES (%d, '%s', %d, '%s')", Id, NameValue, ParentId, NodeName); sqlite3_exec(g_db, sql, 0, 0, 0); } // 显示按钮 void CTest1Dlg::OnBnClickedDisplay() { // TODO: Add your control notification handler code here // 插入根节点 ////HTREEITEM Ht1 = m_CTreeCtrl.InsertItem(CString("0"),TVI_ROOT); // 显示ID HTREEITEM Ht1 = m_CTreeCtrl.InsertItem(CString("ORG"),TVI_ROOT); // 指定含有子节点,节点前方有加号 TVITEM tvItem = {0}; tvItem.mask = TVIF_HANDLE | TVIF_CHILDREN; tvItem.hItem = Ht1; tvItem.cChildren = 1; m_CTreeCtrl.SetItem(&tvItem); return; } // 展开事件处理函数 void CTest1Dlg::OnDblClkTree(NMHDR* pNMHDR, LRESULT* pResult) { // TODO: Add your control notification handler code here CPoint pt; pt=GetCurrentMessage()->pt; m_CTreeCtrl.ScreenToClient(&pt); UINT uFlag = 0; // //HTREEITEM hCur = m_CTreeCtrl.GetSelectedItem(); //双击节点进行操作 LPNMTREEVIEW pNMTreeView = reinterpret_cast<LPNMTREEVIEW>(pNMHDR); // 点击“+”号有反应 HTREEITEM hCur = pNMTreeView->itemNew.hItem; HTREEITEM hItem = m_CTreeCtrl.HitTest(pt, &uFlag); //if (hItem) //{ //if ((m_CTreeCtrl.GetItemState(hItem,TVIS_EXPANDEDONCE )&TVIS_EXPANDEDONCE )!=0 ) //判断是否扩展过一次,若是直接调用EXPAND //{ // m_CTreeCtrl.SelectItem(hItem); //收缩节点时,必须先选择改节点 //m_CTreeCtrl.Expand(hItem,TVE_TOGGLE); //} if ((m_CTreeCtrl.GetItemState(hItem,TVIS_EXPANDEDONCE )&TVIS_EXPANDEDONCE ) == 0) { int rc = sqlite3_open("xml.db", &g_db); if (rc) { fprintf(stderr, "can't open db! ", sqlite3_errmsg(g_db)); sqlite3_close(g_db); exit(1); } // 得到节点文本值 CString S1 = m_CTreeCtrl.GetItemText(hCur); int iTextLen = WideCharToMultiByte ( CP_UTF8, 0, S1, -1, NULL, 0, NULL, NULL); char* pElementText = new char[iTextLen + 1]; memset((void*)pElementText, 0, sizeof(char)*(iTextLen + 1)); WideCharToMultiByte( CP_UTF8,0, S1, -1, pElementText, iTextLen, NULL, NULL ); int i, nrows, ncols; char *errmsg = NULL; char **results; char sql[200] = ""; /*sprintf(sql, "SELECT * FROM XMLDATA WHERE PARENTID = %d", _ttoi(S1)); sqlite3_get_table(g_db, sql, &results, &nrows, &ncols, &errmsg);*/ //显示ID sprintf(sql, "SELECT * FROM XMLDATA WHERE NAMEVALUE = '%s'", pElementText); // 由nodename得到当前ID,作为父节点ID查找所有子节点并显示 (LPSTR)(LPCTSTR)s; sqlite3_get_table(g_db, sql, &results, &nrows, &ncols, &errmsg); results[4]; int nrows1, ncols1; char *errmsg1 = NULL; char **results1; char sql1[200] = ""; sprintf(sql1, "SELECT * FROM XMLDATA WHERE PARENTID = %d", atoi(results[4])); sqlite3_get_table(g_db, sql1, &results1, &nrows1, &ncols1, &errmsg1); //AfxMessageBox(CString(results[5])); for (i = 1; i < nrows1+1; i++) // 插入该节点所有的子节点 { WCHAR wtext[MAX_PATH] = {0}; int nReturn = MultiByteToWideChar(CP_UTF8, 0, results1[4*i+1], -1, wtext, MAX_PATH);// 将namaAttribute转换为宽字符wtext CString NameValue(wtext, nReturn); HTREEITEM Ht = m_CTreeCtrl.InsertItem(NameValue, hCur, TVI_LAST); // 插入子节点 CString NodeName = CString(results1[4*i+3]); //HTREEITEM Ht = m_CTreeCtrl.InsertItem(CString(results[4*i]), hCur, TVI_LAST); //显示ID if (NodeName != "User") // 节点类型不是User,为节点前面添上加号 { TVITEM tvItem = {0}; tvItem.mask = TVIF_HANDLE | TVIF_CHILDREN; tvItem.hItem = Ht; tvItem.cChildren = 1; m_CTreeCtrl.SetItem(&tvItem); } } sqlite3_close(g_db); } //} //AfxMessageBox(S1); *pResult = 0; } /* //从数据库中查找PARENTID为PID的所有节点,将其添加到父节点ht下 void CTest1Dlg::m_InsertTree(char* PId, HTREEITEM ht) { int i, nrows, ncols; char *errmsg = NULL; char **results; char sql[200] = ""; sprintf(sql, "SELECT * FROM XMLDATA WHERE PARENTID = %d", atoi(PId)); sqlite3_get_table(g_db, sql, &results, &nrows, &ncols, &errmsg); for (i = 1; i < nrows+1; i++) // 插入该节点所有的子节点 { WCHAR wtext[MAX_PATH] = {0}; int nReturn = MultiByteToWideChar(CP_UTF8, 0, results[4*i+1], -1, wtext, MAX_PATH);// 将namaAttribute转换为宽字符wtext CString NodeName(wtext, nReturn); HTREEITEM htt = m_CTreeCtrl.InsertItem(NodeName, ht, TVI_LAST); // 插入子节点 m_InsertTree(results[4*i], htt); // 递归调用,插入该子节点的子节点 } sqlite3_free_table(results); // free return; } */