On the way

Even when I wasn't sure where I was going, I was always in a hurry.

  博客园 :: 首页 :: 联系 :: 订阅 订阅 :: 管理
  18 Posts :: 0 Stories :: 10 Comments :: 0 Trackbacks

公告

昵称:On the way
园龄:5年10个月
粉丝:1
关注:0

搜索

 
 

常用链接

最新评论

阅读排行榜

评论排行榜

推荐排行榜

2011年11月24日 #

摘要: 概要网上VC对Excel的操作资料虽然很多,但是很乱,这里做下总结,以后要用了可以参考,免得放在硬盘里时间一长找不到了。本文最后列出了主要的参考源,进一步信息可以从这些网站中获得。代码段均在WinXP+SP3 Excel2007 VS2008+SP1环境下调试通过。这里对Excel OLE对象的调用方式采用了MFC的type Lib。正文准备工作通过type Lib方式引入Excel OLE封装源码文件后,对要用到的头文件做修改。注释import语句,添加Excel对象引用代码(参考资源[2]),注释掉冲突的代码。要引用哪对象就添加哪些对象的头文件,一般下面这些头文件是会被用到的。#incl.阅读全文
posted @ 2011-11-24 10:18 On the way 阅读(73) 评论(0) 编辑

2011年11月23日 #

#import <msxml4.dll>

void Exit()
{
       CoUninitialize();
}

int main(int argc, char *argv[])
{
       CoInitialize(NULL); // 初始化COM环境
       atexit(Exit);

       MSXML2::IXMLDOMDocumentPtr pDOMDoc;

       pDOMDoc.CreateInstance(__uuidof(MSXML2::DOMDocument40)); // 创建XMLDOMDocument对象

       MSXML2::IXMLDOMProcessingInstructionPtr pDOMPI=pDOMDoc->createProcessingInstruction("xml", "version=\"1.0\""); // 创建XML声明

       pDOMDoc->appendChild(pDOMPI); // 添加XML声明

       MSXML2::IXMLDOMElementPtr pDOMRoot;

       pDOMDoc->raw_createElement((_bstr_t)"China", &pDOMRoot); // 创建[根]节点
       pDOMRoot->setAttribute("Area", "3600000"); // 设置[根]节点属性
       pDOMDoc->appendChild(pDOMRoot); // 向Document中添加根节点

       MSXML2::IXMLDOMElementPtr pDOMNode;

       pDOMDoc->raw_createElement((_bstr_t)"City", &pDOMNode);
       pDOMNode->Puttext("Chongqing"); // 为节点赋值
       pDOMRoot->appendChild(pDOMNode); // 向[根]节点中添加子节点

       pDOMDoc->raw_createElement((_bstr_t)"City", &pDOMNode);
       pDOMNode->Puttext("Beijing");
       pDOMRoot->appendChild(pDOMNode);

       pDOMDoc->save("Test.xml"); // 储存XML Document

       return 0;
}

-----------------------------------------------------------------------------xml存在的基础上,读写xml

CoInitialize(NULL);  
    CComPtr<IXMLDOMDocument> spXmldoc;  
    HRESULT hr = spXmldoc.CoCreateInstance(L"MSXML2.DOMDocument.6.0");  


    if(SUCCEEDED(hr))  
    {  
        VARIANT_BOOL isSuccessFul;  
        CComVariant varXmlFile(L"tlacd.xml");  

        //spXmldoc->put_async(VARIANT_FALSE);  
        HRESULT hr= spXmldoc->load(varXmlFile, &isSuccessFul);  

        if(isSuccessFul==VARIANT_TRUE)  
        {  
            CComBSTR bstrXml;  
            CComPtr<IXMLDOMElement> spRoot=NULL;  
            CComPtr<IXMLDOMElement> spTheBook=NULL;  
            CComPtr<IXMLDOMElement> spTheElem=NULL;  
            CComPtr<IXMLDOMNode> spNewNode=NULL;  

            hr = spXmldoc->get_documentElement(&spRoot);  
            spRoot->get_xml(&bstrXml);  
            AfxMessageBox(L"1, 原始的XML");  
            AfxMessageBox(bstrXml);  


            spXmldoc->createElement(L"book", &spTheBook);  
            spXmldoc->createElement(L"name", &spTheElem);  
            spXmldoc->put_text(L"新书");  
spTheBook->appendChild(spTheElem, &spNewNode);  
            spTheElem.Release();  
            spNewNode.Release();  

            spXmldoc->createElement(L"price", &spTheElem);  
            spTheElem->put_text(L"20");  
            spTheBook->appendChild(spTheElem, &spNewNode);  
            spTheElem.Release();  
            spNewNode.Release();  

            spXmldoc->createElement(L"memo", &spTheElem);  
            spTheElem->put_text(L"新书的更好看。");  
spTheBook->appendChild(spTheElem, &spNewNode);  
            spNewNode.Release();  
            spTheElem.Release();  

            spRoot->appendChild(spTheBook, &spNewNode);  
            spNewNode.Release();  
            spTheBook.Release();  

            spRoot->get_xml(&bstrXml);  
            AfxMessageBox(L"2, 新建一本书完成");  
AfxMessageBox(bstrXml);  
            ////---  新建一本书完成 ----  


////---  下面对《哈里波特》做一些修改。 ----  
////---  查询找《哈里波特》----  
CComPtr<IXMLDOMNode> spTheNode=NULL;  
            spRoot->selectSingleNode(L"/books/book[name='哈里波特']", &spTheNode);  
            hr=spTheNode.QueryInterface(&spTheBook);  
            spTheNode.Release();  

            spTheBook->get_xml(&bstrXml);  
            AfxMessageBox(L"3,《哈里波特》的XML");  
            AfxMessageBox(bstrXml);  

            ////---  此时修改这本书的价格 -----  
CComPtr<IXMLDOMNodeList> spNodeList=NULL;  
            CComPtr<IXMLDOMNode> spListItem=NULL;  
            spTheBook->get_childNodes(&spNodeList);  
            spNodeList->get_item(1, &spListItem);  
            spNodeList.Release();  
            spListItem->put_text(L"15");  

            ////---  另外还想加一个属性id,值为B01 ----  
CComVariant varId(L"B01");  
            spTheBook->setAttribute(L"id", varId);  
            varId.Clear();  

            spTheBook->get_xml(&bstrXml);  
            spTheBook.Release();  
            AfxMessageBox(L"4, 对《哈里波特》修改完成。");  
AfxMessageBox(bstrXml);  
            ////---  对《哈里波特》修改完成。 ----  


////---  要用id属性删除《三国演义》这本书  ----  
spRoot->selectSingleNode(L"/books/book[@id='B02']", &spTheNode);  
            hr=spTheNode.QueryInterface(&spTheBook);  
            spTheNode.Release();  

            spTheBook->get_xml(&bstrXml);  
            AfxMessageBox(L"5, 《三国演义》的XML");  
            AfxMessageBox(bstrXml);  

            CComPtr<IXMLDOMNode> spParentNode=NULL;  
            spTheBook->get_parentNode(&spParentNode);  
            spParentNode->removeChild(spTheBook, &spTheNode);  
            spTheNode.Release();  
            spParentNode.Release();  
            spTheBook.Release();  

            spRoot->get_xml(&bstrXml);  
            AfxMessageBox(L"6, 删除《三国演义》后的XML");  
            AfxMessageBox(bstrXml);  


            ////---  再将所有价格低于10的书删除  ----  
spRoot->selectNodes(L"/books/book[price<10]", &spNodeList);  
            CComQIPtr<IXMLDOMSelection> spSomeBooks=spNodeList;  
            spNodeList.Release();  

            spSomeBooks->removeAll();  
            spSomeBooks.Release();  

            spXmldoc->get_xml(&bstrXml);  
            AfxMessageBox(L"7, 已经删除价格低于10的书");  
AfxMessageBox(bstrXml);  

            spRoot.Release();  
            bstrXml.Empty();  

            //spXmldoc->save(varXmlFile); //保存xml。  
}  
varXmlFile.ClearToZero();  
    }  

    spXmldoc.Release();  

    CoUninitialize();  

posted @ 2011-11-23 17:10 On the way 阅读(40) 评论(0) 编辑

2011年11月18日 #

转自http://www.newxing.com/Tech/Program/Cpp/703.html

// XmlCreationDemo.cpp

 

#include <stdlib.h>

#include <stdio.h>

 

// 引入MSXML解析器

#import <msxml4.dll>

using namespace MSXML2;

 

class InitializeCom

{

public:

    InitializeCom()    {        CoInitialize(NULL); // Initializes the COM library    }

    ~InitializeCom() {        CoUninitialize(); // Closes the COM library    }

}InitCom;

 

int main()

{

    char *szXmlFile = "D:\\china.xml"; // xml文件

    IXMLDOMDocumentPtr pDoc = NULL; // xml文档

    IXMLDOMProcessingInstructionPtr pProInstruction = NULL; // xml声明

    IXMLDOMCommentPtr pComment = NULL; // 注释

    IXMLDOMElementPtr pRootElement = NULL, pElement = NULL; // 根节点(元素)

    IXMLDOMNodePtr pNode = NULL, pNode1 = NULL, pNode2 = NULL; // 节点

    IXMLDOMAttributePtr pAttrNode = NULL; // 属性

 

    HRESULT hr = pDoc.CreateInstance(__uuidof(DOMDocument40)); //

    if (FAILED(hr))

    {

        printf("无法创建DOMDocument40对象,请检查是否安装并初始化了MsXml Parser库!");

        return EXIT_FAILURE;

    }

   

    // (1)创建xml文档声明(或insertBefore根节点)

    pProInstruction = pDoc->createProcessingInstruction((_bstr_t)(char*)"xml", (_bstr_t)(char*)"version=\"1.0\" encoding=\"utf-8\"");

    pDoc->appendChild((IXMLDOMNode*)pProInstruction);

 

    // (2)创建根节点<China>

    pRootElement =  pDoc->createElement((_bstr_t)(char*)"China");   

    pDoc->PutRefdocumentElement(pRootElement); // pXMLDomDoc->documentElement = pRootElement;

 

    // (3)创建节点<China><Continent>   

    pComment = pDoc->createComment((_bstr_t)(char*)"所在的洲");

    pRootElement->appendChild((IXMLDOMNode*)pComment); // 注释

   

    pNode = pDoc->createNode((_variant_t)(long)NODE_ELEMENT, (_bstr_t)(char*)"Continent", (_bstr_t)(char*)"");

    pNode->Puttext((_bstr_t)(char*)"Asia"); // pNode->text = "Asia";

    pRootElement->appendChild(pNode); // 节点

 

    // (4)创建节点<China><Population>

    pComment = pDoc->createComment((_bstr_t)(char*)"人口数量");

    pRootElement->appendChild((IXMLDOMNode*)pComment); // 注释

 

    pElement = pDoc->createElement((_bstr_t)(char*)"Population");

    pAttrNode = pDoc->createAttribute((_bstr_t)(char*)"Units");

    pAttrNode->Puttext((_bstr_t)(char*)"Million Person");

    pElement->setAttributeNode(pAttrNode); // 统计单位

    pElement->setAttribute((_bstr_t)(char*)"StatisticalYear", (_variant_t)(char*)"2000"); // 统计年份

    pElement->Puttext((_bstr_t)(char*)"1,296");

    pRootElement->appendChild(pElement); // 节点

 

    // (5)创建节点<China><Municipality>

    pComment = pDoc->createComment((_bstr_t)(char*)"四个直辖市");

    pRootElement->appendChild((IXMLDOMNode*)pComment); // 注释

 

    pNode = pDoc->createNode((_variant_t)(long)NODE_ELEMENT, (_bstr_t)(char*)"Municipality", (_bstr_t)(char*)"");

    pRootElement->appendChild(pNode); // 节点

 

    // (6)创建节点<China><Municipality><TianJin>

    pNode1 = pDoc->createNode((_variant_t)(long)NODE_ELEMENT, (_bstr_t)(char*)"TianJin", (_bstr_t)(char*)"");

   

    //    创建节点<China><Municipality><TianJin><Area>

    pElement = pDoc->createElement((_bstr_t)(char*)"Area");

    pElement->setAttribute((_bstr_t)(char*)"Units", (_variant_t)(char*)"Thousand Square kilometers"); // 统计单位

    pElement->Puttext((_bstr_t)(char*)"12");

    pNode1->appendChild((IXMLDOMNode*)pElement); // 节点

   

    //    创建节点<China><Municipality><TianJin><Population>

    pElement = pDoc->createElement((_bstr_t)(char*)"Population");

    pElement->setAttribute((_bstr_t)(char*)"Units", (_variant_t)(char*)"Million Person"); // 统计单位

    pElement->setAttribute((_bstr_t)(char*)"StatisticalYear", (_variant_t)(char*)"2000"); // 统计年份

    pElement->Puttext((_bstr_t)(char*)"10.01");

    pNode1->appendChild((IXMLDOMNode*)pElement); // 节点

 

    pNode->appendChild(pNode1);

    // (7)创建节点<China><Municipality><BeiJing>并插入<TianJin>前

    pNode2 = pDoc->createNode((_variant_t)(long)NODE_ELEMENT, (_bstr_t)(char*)"BeiJing", (_bstr_t)(char*)"");

 

    //    创建节点<China><Municipality><BeiJing><Area>

    pElement = pDoc->createElement((_bstr_t)(char*)"Area");

    pElement->setAttribute((_bstr_t)(char*)"Units", (_variant_t)(char*)"Thousand Square kilometers"); // 统计单位

    pElement->Puttext((_bstr_t)(char*)"17");

    pNode2->appendChild((IXMLDOMNode*)pElement); // 节点

   

    //    创建节点<China><Municipality><BeiJing><Population>

    pElement = pDoc->createElement((_bstr_t)(char*)"Population");

    pElement->setAttribute((_bstr_t)(char*)"Units", (_variant_t)(char*)"Million Person"); // 统计单位

    pElement->setAttribute((_bstr_t)(char*)"StatisticalYear", (_variant_t)(char*)"2000"); // 统计年份

    pElement->Puttext((_bstr_t)(char*)"13.82");

    pNode2->appendChild((IXMLDOMNode*)pElement); // 节点

 

    pNode->insertBefore(pNode2, (_variant_t)(IDispatch*)pNode1);

    //

    // (8)创建节点<China><Municipality><ShangHai>

    // (9)创建节点<China><Municipality><ChongQing>

 

    pDoc->save((_variant_t)szXmlFile);

 

    return EXIT_SUCCESS;

}

===========================生成的china.xml文档内容:======================================================

<?xml version="1.0" encoding="utf-8"?>

<China>

<!--所在的洲-->

  <Continent>Asia</Continent>

  <!--人口数量-->

  <Population Units="Million Person" StatisticalYear="2000">1,296</Population>

  <!--四个直辖市-->

  <Municipality>

    <BeiJing>

      <Area Units="Thousand Square kilometers">17</Area>

      <Population Units="Million Person" StatisticalYear="2000">13.82</Population>

    </BeiJing>

    <TianJin>

      <Area Units="Thousand Square kilometers">12</Area>

      <Population Units="Million Person" StatisticalYear="2000">10.01</Population>

    </TianJin>

    <ShangHai>

      <Area Units="Thousand Square kilometers">6.4</Area>

      <Population Units="Million Person" StatisticalYear="2000">16.74</Population>

    </ShangHai>

    <ChongQing>

      <Area Units="Thousand Square kilometers">84</Area>

      <Population Units="Million Person" StatisticalYear="2000">30.90</Population>

    </ChongQing>

  </Municipality>

</China>

=================================

二.MsXml解析XML文档示例:

// XmlParsingDemo.cpp

 

#include <stdlib.h>

#include <stdio.h>

 

// 引入MSXML解析器

#import <msxml4.dll>

using namespace MSXML2;

 

class InitializeCom

{

public:

    InitializeCom()    {        CoInitialize(NULL); // Initializes the COM library    }

    ~InitializeCom() {        CoUninitialize(); // Closes the COM library    }

}InitCom;

 

int main()

{

    char *szXmlFile = "D:\\china.xml"; //上篇创建的xml文档

    IXMLDOMDocumentPtr pDoc = NULL; // xml文档

    IXMLDOMNodeListPtr pNodeList = NULL; // 节点链表

    IXMLDOMElementPtr pRootElement = NULL, pElement = NULL; // 根节点(元素)

    IXMLDOMNodePtr pNode = NULL, pNode1 = NULL; // 节点

    IXMLDOMNamedNodeMapPtr pAttrList = NULL; // 属性链表

    IXMLDOMAttributePtr pAttrNode = NULL; // 属性

    long lChilds, lAttr, i;

 

    HRESULT hr = pDoc.CreateInstance(__uuidof(DOMDocument40));

    if (FAILED(hr))

    {

        printf("无法创建DOMDocument40对象,请检查是否安装并初始化了MsXml Parser库!");

        return EXIT_FAILURE;

    }

 

    VARIANT_BOOL bXmlLoad = pDoc->load((_variant_t)szXmlFile);

    if (!bXmlLoad) // 加载失败

    {

        printf("加载%s失败!\n", szXmlFile);

        return EXIT_FAILURE;

    }

   

    // (1)根节点

    pRootElement = pDoc->GetdocumentElement();

    printf("root = %s\n", (char*)pRootElement->GetnodeName()); // pRootElement->nodeName

 

    // (2)根节点的一级子节点

    pNodeList = pRootElement->GetchildNodes(); // pRootElement->childNodes

    lChilds = pNodeList->Getlength(); // pNodeList->length

    for (i = 0; i < lChilds; i++)

    {

        pNode = pNodeList->Getitem(i); // pNodeList->item[i]

        if (pNode->GetnodeType() != NODE_COMMENT) // 过滤注释节点

        {

            printf("child[%d] of [%s]: [%s]\n", i ,(char*)pRootElement->GetnodeName(), (char*)pNode->GetnodeName());

        }

    }

 

    // (3)统计文档中所有的<Population>节点

    pNodeList = pDoc->getElementsByTagName((_bstr_t)(char*)"Population");

    lChilds = pNodeList->Getlength();

    printf("文档中[Population]共有%d个\n", lChilds);

 

    // (4)根节点下的<Population>节点

    pNode = pRootElement->selectSingleNode((_bstr_t)(char*)"Population");

    // 已知根节点为<China>时:pNode = pDoc->selectSingleNode((_bstr_t)(char*)"China//Population");

    printf("根节点下的[Population]子节点值为%s\n", (char*)pNode->Gettext());

    pAttrList = pNode->Getattributes();

    lAttr = pAttrList->Getlength();

    for (i = 0; i < lAttr; i++)

    {

        pAttrNode = pAttrList->Getitem(i);

        printf("Attr[%d] of [%s]: %s = %s\n", i, (char*)pNode->GetnodeName(), (char*)pAttrNode->GetnodeName(), (char*)pAttrNode->Gettext());

    }

   

    // (5)查找节点<Municipality>下的所有子节点

    // "//"表示在任意一层寻找Municipality;"//*"查找<Municipality></Municipality>中的所有子节点

    pNodeList = pDoc->selectNodes((_bstr_t)(char*)"//Municipality//*"); // 这里可将pDoc换成pRootElement

    while (pNode = pNodeList->nextNode())

    {

        printf("childs of [Municipality]: %s\n", (char*)pNode->GetnodeName());

    }

 

    // (6)查找节点<Municipality>下的一级子节点

    pNode = pRootElement->selectSingleNode((_bstr_t)(char*)"Municipality");

    pNodeList = pNode->GetchildNodes();

    lChilds = pNodeList->Getlength();

    for (i = 0; i < lChilds; i++)

    {

        pNode1 = pNodeList->Getitem(i); // pNodeList->item[i]

        printf("child[%d] of [Municipality]: %s\n", i, (char*)pNode1->GetnodeName());

    }

 

    // (7)查询父、子、兄、弟节点

    pNode = pRootElement->selectSingleNode((_bstr_t)(char*)"//TianJin");

    pNode1 = pNode->GetparentNode(); // 父节点

    printf("[TianJin]的父节点为[%s]\n", (char*)pNode1->GetnodeName());

 

    pNodeList = pNode->GetchildNodes(); // 子节点

    lChilds = pNodeList->Getlength();

    for (i = 0; i < lChilds; i++)

    {

        pNode1 = pNodeList->nextNode();

        printf("child[%d] of [TianJin]: %s\n", i, (char*)pNode1->GetnodeName());

    }

 

    pNode1 = pNode->GetpreviousSibling(); // 兄节点

    printf("[TianJin]的兄节点为[%s]\n", (char*)pNode1->GetnodeName());

 

    pNode1 = pNode->GetnextSibling(); // 弟节点

    printf("[TianJin]的弟节点为[%s]\n", (char*)pNode1->GetnodeName());

 

    return EXIT_SUCCESS;

}

==================================================

运行结果如下:

root = China
child[1] of <China>: <Continent>
child[3] of <China>: <Population>
child[5] of <China>: <Municipality>
文档中<Population>共有5个
根节点下的<Population>子节点值为1,296
Attr[0] of <Population>: Units = Million Person
Attr[1] of <Population>: StatisticalYear = 2000
childs of <Municipality>: BeiJing
childs of <Municipality>: Area
childs of <Municipality>: Population
childs of <Municipality>: TianJin
childs of <Municipality>: Area
childs of <Municipality>: Population
childs of <Municipality>: ShangHai
childs of <Municipality>: Area
childs of <Municipality>: Population
childs of <Municipality>: ChongQing
childs of <Municipality>: Area
childs of <Municipality>: Population
child[0] of <Municipality>: BeiJing
child[1] of <Municipality>: TianJin
child[2] of <Municipality>: ShangHai
child[3] of <Municipality>: ChongQing
<TianJin>的父节点为<Municipality>
child[0] of <TianJin>: Area
child[1] of <TianJin>: Population
<TianJin>的兄节点为<BeiJing>
<TianJin>的弟节点为<ShangHai>

posted @ 2011-11-18 16:32 On the way 阅读(51) 评论(0) 编辑

2011年11月17日 #

MainFrame: 主框架类

Dlg 是Dialog 的缩写,表示对话框本身

 
App类就是这个SDI作为"程序"的入口,有点像c的Main函数,它不是从CWND中派生出来的。App表示应用程序本身。

 
View表示视图类,负责显示数据,提供编辑数据、修改数据的功能。它是指编辑区里面的事就是那块白色的中间区域,负责绘制和响应一些消息

 
Doc表示文档类,提供对数据的保存和加载。有点像数据库,保存着编辑数据,用于view的Redraw的时候用,还有保存文件。

 一般动态的编辑数据都放在Doc里面。他也不是从CWND中派生出来的,没有继承MessageBox函数,可以用AfxMessageBox函数。

 

 

1)   View中获得Doc指针    

  2)   App中获得MainFrame指针    

  3)   View中获得MainFrame指针    

  4)   获得View(已建立)指针    

  5)   获得当前文档指针    

  6)   获得状态栏与工具栏指针    

  7)   获得状态栏与工具栏变量    

  8)   Mainframe获得菜单指针    

  9)   在任何类中获得应用程序类    

  10)   从文档类取得视图类的指针(1)    

  11)   App中获得文档模板指针    

  12)   从文档模板获得文档类指针    

  13)   在文档类中获得文档模板指针    

  14)   从文档类取得视图类的指针(2)    

  15)   从一个视图类取得另一视图类的指针    

     

  VC中编程对于刚刚开始学习的同学,最大的障碍和问题就是消息机制和指针获取与操作。其实这些内容基本上是每本VC学习工具书上必讲的内容,而且通过MSDN很多问题都能解决。下面文字主要是个人在编程中指针使用的一些体会,说的不当的地方请指正。一般我们使用的框架是VC提供的Wizard生成的MFC App Wizard(exe)框架,无论是多文档还是单文档,都存在指针获取和操作问题。下面这节内容主要是一般的框架,然后再讲多线程中的指针使用。使用到的类需要包含响应的头文件。首先一般获得本类(视,文档,对话框都支持)实例指针this,用this的目的,主要可以通过类中的函数向其他类或者函数中发指针,以便于在非本类中操作和使用本类中的功能。 

    1   View中获得Doc指针    

CYouSDIDoc   *pDoc=GetDocument();一个视只能有一个文档。    

    2)   App中获得MainFrame指针    

  CWinApp   中的   m_pMainWnd变量就是MainFrame的指针    

  也可以:   CMainFrame   *pMain   =(CMainFrame   *)AfxGetMainWnd(); 

    3)   View中获得MainFrame指针 

  CMainFrame   *pMain=(CmaimFrame   *)AfxGetApp()‐>m_pMainWnd; 

    4)   获得View(已建立)指针 

  CMainFrame   *pMain=(CmaimFrame   *)AfxGetApp()‐>m_pMainWnd;    

  CyouView   *pView=(CyouView   *)pMain‐>GetActiveView(); 

    5)   获得当前文档指针 

  CDocument   *   pCurrentDoc   =(CFrameWnd   *)m_pMainWnd‐>GetActiveDocument(); 

    6)   获得状态栏与工具栏指针 

  CStatusBar   *   pStatusBar(CStatusBar   *)AfxGetMainWnd()‐>GetDescendantWindow(AFX_IDW_STATUS_BAR);    

  CToolBar   *   pToolBar=(CtoolBar   *)AfxGetMainWnd()‐>GetDescendantWindow(AFX_IDW_TOOLBAR);    

    7)   如果框架中加入工具栏和状态栏变量还可以这样      

  (CMainFrame   *)GetParent()‐>m_wndToolBar;    

  (CMainFrame   *)GetParent()‐>m_wndStatusBar;    

    8)   Mainframe获得菜单指针 

  CMenu   *pMenu=m_pMainWnd‐>GetMenu(); 

    9)   在任何类中获得应用程序类    

  MFC全局函数AfxGetApp()获得。    

  10)   从文档类取得视图类的指针    

  我是从http://download.cqcnc.com/soft/program/article/vc/vc405.html学到的,    

  从文档获得视图类指针目的一般为了控制同一文档的多个视图的定位问题,我的体会    

  特别是文字处理CEditView当产生多个视图类时,这个功能是非常需要的。      

  CDocument类提供了两个函数用于视图类的定位:    

  GetFirstViewPosition()GetNextView()      

  virtual   POSITION   GetFirstViewPosition()   const;    

  virtual   CView*   GetNextView(POSITION&   rPosition)   const;    

     

  注意:GetNextView()括号中的参数用的是引用方式,因此执行后值可能改变。    

  GetFirstViewPosition()用于返回第一个视图位置(返回的并非视图类指针,而是一    

  POSITION类型值),GetNextView()有两个功能:返回下一个视图类的指针以及用    

  引用调用的方式来改变传入的POSITION类型参数的值。很明显,在Test程序中,只有    

  一个视图类,因此只需将这两个函数调用一次即可得到CTestView的指针如下(需定    

  义一个POSITION结构变量来辅助操作):      

  CTestView*   pTestView;    

  POSITION   pos=GetFirstViewPosition();    

  pTestView=GetNextView(pos);    

     

  这样,便可到了CTestView类的指针pTestView.执行完几句后,变量pos=NULL,因为没    

  有下一个视图类,自然也没有下一个视图类的POSITION.但是这几条语句太简单,不    

  具有太强的通用性和安全特征;当象前面说的那样,当要在多个视图为中返回某个指    

  定类的指针时,我们需要遍历所有视图类,直到找到指定类为止。判断一个类指针指    

  向的是否某个类的实例时,可用IsKindOf()成员函数时行检查,如:    

    pView‐>IsKindOf(RUNTIME_CLASS(CTestView));    

  即可检查pView所指是否是CTestView类。    

     

  有了以上基础,我们已经可以从文档类取得任何类的指针。为了方便,我们将其作    

  为一个文档类的成员函数,它有一个参数,表示要获得哪个类的指针。实现如下:      

      

  其中用了两次视图类的成员函数IsKindOf()来判断,是因为退出while循环有三种    

  可能:    

     

  1.posNULL,即已经不存在下一个视图类供操作;    

  2.pView已符合要求。    

     

  12同是满足。这是因为GetNextView()的功能是将当前视图指针改变成一个视图    

  的位置同时返回当前视图指针,因此pospView的下一个视图类的POSITION,完全    

  有可能既是pos==NULL又是pView符合需要。当所需的视图是最后一个视图是最后一    

  个视图类时就如引。因此需采用两次判断。    

  使用该函数应遵循如下格式(以取得CTestView指针为例):    

  CTestView*   pTestView=(CTestView*)GetView(RUNTIME_CLASS(CTestView));    

  RUNTIME_CLASS是一个宏,可以简单地理解它的作用:将类的名字转化为    

  CRuntimeClass为指针。至于强制类型转换也是为了安全特性考虑的,因为从同一个    

  基类之间的指针类型是互相兼容的。这种强制类型转换也许并不必要,但能避免一    

  些可能出现的麻烦。    

     

  3.从一个视图类取得另一视图类的指针   综合12,很容易得出视图类之间互相获得    

  指针的方法:就是用文档类作中转,先用1的方法得到文档类的指针,再用2的方法,    

  以文档类的视图定位函数取得另一个视图类。同样,可以实现成一个函数:    

  (假设要从CTestAView中取得指向其它视图类的指针)    

   这个函数和2中的GetView()相比,一是多了第一句以取得文档类指针,二是在    

  GetFirstViewPosition()GetNextView()前加上了文档类指针,以表示它们是文档    

  类成员函数。有了此函数;当要从CTestAView中取得CTestBView的指针时,只需如    

  下:CTestBView*   pTestbView=(CTestView*)GetView(RUNTIME_CLASS(CTestBView)); 

 

posted @ 2011-11-17 16:51 On the way 阅读(162) 评论(0) 编辑

不管实在C还是C++代码中,typedef这个词都不少见,当然出现频率较高的还是在C代码中。typedef与#define有些相似,但更多的是不同,特别是在一些复杂的用法上,就完全不同了,看了网上一些C/C++的学习者的博客,其中有一篇关于typedef的总结还是很不错,由于总结的很好,我就不加修改的引用过来了,以下是引用的内容(红色部分是我自己写的内容)。

用途一:

定义一种类型的别名,而不只是简单的宏替换。可以用作同时声明指针型的多个对象。比如:

char* pa, pb; // 这多数不符合我们的意图,它只声明了一个指向字符变量的指针,

// 和一个字符变量;

以下则可行:

typedef char* PCHAR;

PCHAR pa, pb;  

这种用法很有用,特别是char* pa, pb的定义,初学者往往认为是定义了两个字符型指针,其实不是,而用typedef char* PCHAR就不会出现这样的问题,减少了错误的发生。

用途二:
用在旧的C代码中,帮助struct。以前的代码中,声明struct新对象时,必须要带上
struct,即形式为: struct 结构名对象名,如:

struct tagPOINT1

 {
    int x;

    int y;
};

struct tagPOINT1 p1;

而在C++中,则可以直接写:结构名对象名,即:tagPOINT1 p1;

typedef struct tagPOINT
{
    int x;

    int y;
}POINT;

POINT p1; // 这样就比原来的方式少写了一个struct,比较省事,尤其在大量使用的时

候,或许,在C++中,typedef的这种用途二不是很大,但是理解了它,对掌握以前的旧代

码还是有帮助的,毕竟我们在项目中有可能会遇到较早些年代遗留下来的代码。

用途三:

用typedef来定义与平台无关的类型。

比如定义一个叫 REAL 的浮点类型,在目标平台一上,让它表示最高精度的类型为:

typedef long double REAL;

在不支持 long double 的平台二上,改为:

typedef double REAL;

在连 double 都不支持的平台三上,改为:

typedef float REAL;

也就是说,当跨平台时,只要改下 typedef 本身就行,不用对其他源码做任何修改。

标准库就广泛使用了这个技巧,比如size_t。另外,因为typedef是定义了一种类型的新别名,不是简单的字符串替换,所以它比宏来得稳健。
     这个优点在我们写代码的过程中可以减少不少代码量哦!

用途四:

为复杂的声明定义一个新的简单的别名。方法是:在原来的声明里逐步用别名替换一部

分复杂声明,如此循环,把带变量名的部分留到最后替换,得到的就是原声明的最简化

版。举例: 

 原声明:void (*b[10]) (void (*)());

变量名为b,先替换右边部分括号里的,pFunParam为别名一:

typedef void (*pFunParam)();

再替换左边的变量b,pFunx为别名二:

typedef void (*pFunx)(pFunParam);

原声明的最简化版:

pFunx b[10];
 
原声明:doube(*)() (*e)[9];

变量名为e,先替换左边部分,pFuny为别名一:

typedef double(*pFuny)();

再替换右边的变量e,pFunParamy为别名二

typedef pFuny (*pFunParamy)[9];

原声明的最简化版:

pFunParamy e;

理解复杂声明可用的“右左法则”:从变量名看起,先往右,再往左,碰到一个圆括号

就调转阅读的方向;括号内分析完就跳出括号,还是按先右后左的顺序,如此循环,直

到整个声明分析完。举例:

int (*func)(int *p);

首先找到变量名func,外面有一对圆括号,而且左边是一个*号,这说明func是一个指针

;然后跳出这个圆括号,先看右边,又遇到圆括号,这说明(*func)是一个函数,所以

func是一个指向这类函数的指针,即函数指针,这类函数具有int*类型的形参,返回值

类型是int。

int (*func[5])(int *);

func右边是一个[]运算符,说明func是具有5个元素的数组;func的左边有一个*,说明

func的元素是指针(注意这里的*不是修饰func,而是修饰func[5]的,原因是[]运算符

优先级比*高,func先跟[]结合)。跳出这个括号,看右边,又遇到圆括号,说明func数

组的元素是函数类型的指针,它指向的函数具有int*类型的形参,返回值类型为int。

这种用法是比较复杂的,出现的频率也不少,往往在看到这样的用法却不能理解,相信以上的解释能有所帮助。

*****以上为参考部分,以下为本人领悟部分*****

使用示例:

1.比较一:

#include <iostream>

using namespace std;

typedef int (*A) (char, char);

int ss(char a, char b)
{
    cout<<"功能1"<<endl;

    cout<<a<<endl;

    cout<<b<<endl;

    return 0;
}
 
int bb(char a, char b)
{

    cout<<"功能2"<<endl;

    cout<<b<<endl;

    cout<<a<<endl;

    return 0;

}

void main()
{

    A a;

    a = ss;

    a('a','b');

    a = bb;

    a('a', 'b');
}

2.比较二:

typedef int (A) (char, char);

void main()
{

    A *a;

    a = ss;

    a('a','b');

    a = bb;

    a('a','b');
}
 

两个程序的结果都一样:

功能1

a

b

功能2

b

a

 

*****以下是参考部分*****

参考自:http://blog.hc360.com/portal/personShowArticle.do?articleId=57527

typedef 与 #define的区别:

案例一:

通常讲,typedef要比#define要好,特别是在有指针的场合。请看例子:

typedef char *pStr1;

#define pStr2 char *;

pStr1 s1, s2;

pStr2 s3, s4;
在上述的变量定义中,s1、s2、s3都被定义为char *,而s4则定义成了char,不是我们

所预期的指针变量,根本原因就在于#define只是简单的字符串替换而typedef则是为一

个类型起新名字。

案例二:

下面的代码中编译器会报一个错误,你知道是哪个语句错了吗?

typedef char * pStr;

char string[4] = "abc";

const char *p1 = string;

const pStr p2 = string;

p1++;

p2++;

  是p2++出错了。这个问题再一次提醒我们:typedef和#define不同,它不是简单的

文本替换。上述代码中const pStr p2并不等于const char * p2。const pStr p2和

const long x本质上没有区别,都是对变量进行只读限制,只不过此处变量p2的数据类

型是我们自己定义的而不是系统固有类型而已。因此,const pStr p2的含义是:限定数

据类型为char *的变量p2为只读,因此p2++错误。虽然作者在这里已经解释得很清楚了,可我在这个地方仍然还是糊涂的,真的希望哪位高手能帮忙指点一下,特别是这一句“只不过此处变量p2的数据类型是我们自己定义的而不是系统固有类型而已”,难道自己定义的类型前面用const修饰后,就不能执行更改运算,而系统定义的类型却可以?

 

刚刚看到楼主写的文章,不错。最后你那个问题:
const char *p1 = string; 你可以这样理解:(const char) *p1 = string, p1是一个指针,指向const char的东西,这个东西就是string(string是一个字符数组的首地址,它的地址声明后肯定是const的,除非该数组销毁),但是p1是一个指针变量,它是可以递增的,即你看到的p1++,它可以完成从数组的来遍历数组的目的。

而const pStr p2 = string;是这样的:由于p2不是指针,const直接修饰到了p2,即现在的p2是常量了,它的类型是pStr(我们自己定义的类型),相当于const int p2, const long p2等等,const都是直接修饰p2的,只不过int,long是系统类型,而pStr是我们定义的类型。为什么会出现这种效果了,就是因为typedef,它把char *定义成一个复合的类型,要从整体上来理解语义,而不是字符替换后来理解语义。

http://www.cnblogs.com/csyisong/archive/2009/01/09/1372363.html

posted @ 2011-11-17 10:39 On the way 阅读(6) 评论(0) 编辑

2011年11月16日 #

Kenny Kerr 一篇名为C++: The Most Powerful Language for .NET Framework Programming文章中的对比表,十分清晰的展示了版本2语言中设计的简洁和与原生语言的接近。值得参考:

 

描述

C++/CLI

C#

创建引用类型的对象

ReferenceType^ h = gcnew ReferenceType;

ReferenceType h = new ReferenceType();

创建值类型的对象

ValueType v(3, 4);

ValueType v = new ValueType(3, 4);

引用类型在堆栈上

ReferenceType h;

N/A

调用Dispose方法

ReferenceType^ h = gcnew ReferenceType;

delete h;

ReferenceType h = new ReferenceType();

((IDisposable)h).Dispose();

实现Dispose方法

~TypeName() {}

void IDisposable.Dispose() {}

实现Finalize 方法

!TypeName() {}

~TypeName() {}

装箱(Boxing

int^ h = 123;

object h = 123;

拆箱(Unboxing

int^ hi = 123;

int c = *hi;

object h = 123;

int i = (int) h;

定义引用类型

ref class ReferenceType {};

ref struct ReferenceType {};

class ReferenceType {}

定义值类型

value class ValueType {};

value struct ValueType {};

struct ValueType {}

使用属性

h.Prop = 123;

int v = h.Prop;

h.Prop = 123;

int v = h.Prop;

定义属性

property String^ Name
{
    String^ get()
    {
        return m_value;
    }
    void set(String^ value)
    {
        m_value = value;
    }
}

string Name
{
    get
    {
        return m_name;
    }
    set
    {
        m_name = value;
    }
}

posted @ 2011-11-16 17:52 On the way 阅读(14) 评论(0) 编辑

 

Lvalues and Rvalues

An object is a region of storage that can be examined and stored into. An lvalue is an expression that refers to such an object. An lvalue does not necessarily permit modification of the object it designates. For example, a const object is an lvalue that cannot be modified. The termmodifiable lvalue is used to emphasize that the lvalue allows the designated object to be changed as well as examined. The following object types are lvalues, but not modifiable lvalues:

  • An array type
  • An incomplete type
  • const-qualified type
  • An object is a structure or union type and one of its members has a const-qualified type

 

Because these lvalues are not modifiable, they cannot appear on the left side of an assignment statement.

The term rvalue refers to a data value that is stored at some address in memory. An rvalue is an expression that cannot have a value assigned to it. Both a literal constant and a variable can serve as an rvalue. When an lvalue appears in a context that requires an rvalue, the lvalue is implicitly converted to an rvalue. The reverse, however, is not true: an rvalue cannot be converted to an lvalue. Rvalues always have complete types or the void type.

C ISO C defines a function designator as an expression that has function type A function designator is distinct from an object type or an lvalue. It can be the name of a function or the result of dereferencing a function pointer. The C language also differentiates between its treatment of a function pointer and an object pointer.

C++ On the other hand, in C++, a function call that returns a reference is an lvalue. Otherwise, a function call is an rvalue expression. In C++, every expression produces an lvalue, an rvalue, or no value.

In both C and C++, certain operators require lvalues for some of their operands. The table below lists these operators and additional constraints on their usage. 

Operator Requirement
& (unary) Operand must be an lvalue.
++ -- Operand must be an lvalue. This applies to both prefix and postfix forms.
= += -= *= %= <<= >>= &= ^= |= Left operand must be an lvalue.

For example, all assignment operators evaluate their right operand and assign that value to their left operand. The left operand must be a modifiable lvalue or a reference to a modifiable object.

The address operator (&) requires an lvalue as an operand while the increment (++) and the decrement (--) operators require a modifiable lvalue as an operand. The following example shows expressions and their corresponding lvalues. 

Expression Lvalue
x = 42 x
*ptr = newvalue *ptr
a++ a
C++int& f() 
The function call to f()

Mac OS X C The remainder of this section is platform-specific and pertains to C only.

When compiled with the GNU C language extensions enabled, compound expressions, conditional expressions, and casts are allowed as lvalues, provided that their operands are lvalues. The use of this language extension is deprecated for C++ code.

A compound expression can be assigned if the last expression in the sequence is an lvalue. The following expressions are equivalent:

(x + 1, y) *= 42; x + 1, (y *=42);

The address operator can be applied to a compound expression, provided the last expression in the sequence is an lvalue. The following expressions are equivalent:

&(x + 1, y); x + 1, &y;

A conditional expression can be a valid lvalue if its type is not void and both of its branches for true and false are valid lvalues. Casts are valid lvalues if the operand is an lvalue. The primary restriction is that you cannot take the address of an lvalue cast.

 

---------------------------------------------------

 

今天看C++模板的资料,里面说到lvalue,rvalue的问题,这个问题以前也看到过,也查过相关资料,但是没有考虑得很深,只知道rvalue不能取地址,不能赋值等等一些规则。今天则突然有了更深层次的理解(也可以说是顿悟,耗时不过几秒钟),记录下来。

下面是我对这两个单词字面的意思的猜测:

  • lvalue估计来源于left value。 在赋值语句中lvalue = rvalue;位置处于左边。就是可以修改的值。
  • rvalue估计来源于right value。处于赋值语句右边,是只读的不可修改的值。

接下来是我所悟到内容的详细分析

  • lvalue是可以赋值的,说明它是一个变量,它在内存中一定存在,一定有地址。所以&lvalue是有效的,能取到在内存中的地址。

    访问lvalue一定会导致CPU访问存储器(相对较慢的操作)。

    lvalue的例子:

    1. int a;  
    2. a = 10; // a是lvalue。   
    3. int* p = &a; // &a是rvalue。   
    4. &a = 0; //错误,&a不是lvalue,因为a的地址一旦分配好了,就不能改变了。  
  • rvalue是不可以赋值的,它不是一个变量,在内存中没有存在,没有地址。它要么是存在于CPU的寄存器中,要么是存在于指令中(立即数)。所以只要对rvalue取地址,那么就一定是错误的(编译器会抱怨的)。

    访问rvalue不会导致CPU访问存储器(对立即数和寄存器的访问很快)。

    rvalue的例子:

    1. int a;  
    2. a = 10; // 10是rvalue,它没有地址,&10就是错误的表达式。从汇编语言的角度来看,10是直接存在于MOV指令中的立即数。   
    3. 10 = a; // 错误,10是rvalue,不可赋值。   
    4. //函数返回值属于rvalue,因为返回值通常用CPU寄存器传递,没有地址。   
    5. int foo()  
    6. {  
    7.     return 0;  
    8. }  
    9. int b = foo(); //没问题,函数返回值是rvalue。   
    10. int* p = &foo(); //错误,rvalue没有地址。   
    11. void bar(int& i)  
    12. {  
    13. }  
    14. bar(foo()); //错误,bar函数参数需要的是lvalue。  
  • 函数的返回值是rvalue,对于返回int, char 等这样最基本的类型,是通过CPU寄存器返回的,因此返回值没有地址是可以理解的。但是如果函数返回的是一个用户自定义类型的对象,肯定不可能通过寄存器来返回这个对象值的(寄存器大小数量都有限,对象的大小可以非常大),那究竟是怎样返回对象的呢?

     

    1. class UDT  
    2. {  
    3.   int data[100];  
    4. public:  
    5.   UDT()  
    6.   {  
    7.     printf("construct/n");  
    8.   }  
    9.   BBB& operator = (BBB& )  
    10.   {  
    11.     printf("operator =/n");  
    12.     return *this;  
    13.   }  
    14. };  
    15. UDT foo()  
    16. {  
    17.   return UDT();  
    18. }  
    19. void main()  
    20. {  
    21.   UDT obj = foo();  
    22. }  
    23. //输出:   
    24. construct  

     

    带着疑问,我查了查vc编译出来的代码,原来obj这个局部变量的地址被压入了堆栈,foo函数内部以堆栈上的obj地址作为this指针调用了UDT的构造函数。噢,难怪执行UDT obj = foo();这个语句只有调用了一次构造函数,而没有调用operator =,这都是因为函数返回值必须是rvalue这个规则所带来的好处,如果返回值是一个lvalue,那么这个语句一定会调用operator = 运算符。

http://blog.csdn.net/rogerhe/article/details/6410993

posted @ 2011-11-16 16:58 On the way 阅读(22) 评论(0) 编辑

2011年11月9日 #

摘要: 讲讲volatile的作用 254 推荐 一个定义为volatile的变量是说这变量可能会被意想不到地改变,这样,编译器就不会去假设这个变量的值了。精确地说就是,优化器在用到这个变量时必须每次都小心地重新读取这个变量的值,而不是使用保存在寄存器里的备份。下面是volatile变量的几个例子: 1).并行设备的硬件寄存器(如:状态寄存器) 2).一个中断服务子程序中会访问到的非自动变量(Non-automaticvariables) 3).多线程应用中被几个任务共享的变量 回答不出这个问题的人是不会被雇佣的。我认为这是区分C程序员和嵌入式系统程序员的最基本的问题。嵌入式系统程序员经常同硬件、中.阅读全文
posted @ 2011-11-09 11:11 On the way 阅读(5) 评论(0) 编辑

2011年11月8日 #

摘要: 利用C++/CLI 封装Native C++ 提升.NET web game性能 原帖:http://www.cnblogs.com/warensoft/archive/2010/03/07/1680290.html 这段时间在做新项目的技术论证,其基本想法就是利用Flex调用远程WCF以及发送Socket请求,来实现远程通信,WCF负责实时性要求不高的操作,如聊天,邮件,交易,买卖等,而Socket的目的是提供实时战斗的服务。 无论是WCF,还是Socket,都会提供不少的游戏逻辑,当然,大家心里都有数,与C++相比C#在纯数值运算上慢的太多,但是提到语法简洁性,MS的数据访问组件支持...阅读全文
posted @ 2011-11-08 14:44 On the way 阅读(43) 评论(0) 编辑

2008年4月2日 #

摘要: 1英寸=1440twip1毫米=56.47twip 那么 1毫米 = 56.47/1440 = 0.0392 英寸阅读全文
posted @ 2008-04-02 10:56 On the way 阅读(70) 评论(0) 编辑