感谢蒋晟的系列文章,让我学到了很多关于浏览器编程的技术。现在我已经在网页里定义好了表格 <table id="tableid"></table>  只要往里面插入数据就行了,用put_innerHTML的方法是可以的,感觉不“专业”啊,呵呵!现在我知道怎样获取网页元素的IHTMLElement接口,但它只能操作其 innerHTML 之类的字符串,但不能创建表行表列;IHTMLTable接口又只能创建、删除表行表列,不能设置其内容;这两个接口可以通过QuerryInterface()相互获取吗?
对于这个问题谁能给小弟指条明路吗?非常感谢!

解决方案 »

  1.   

    很不幸,大多数元素都能通过put_innerHTML或者insertAdjacentHTML来插入子元素,唯独table元素例外。table元素添加行列数据必须通过IHTMLTable的方法来逐个添加行,在行中逐个添加列。但是有变通的办法来添加一段<tr><td>...</td></tr>的HTML代码到table中,原理大概是这样的:假设有一个HTML片段:rows = "<tr><td>1</td><td>2</td></tr><tr><td>3</td><td>4</td></tr>";
    1、通过tmp=document.createElement("div")创建一个临时元素;
    2、在这个div元素中添加表格元素的HTML串:tmp.innerHTML = "<table>" + rows + "</table>";
    3、通过ID或者其它导航方式获得目标table元素tab(例如tab=document.getElementById("tableid");)
    4、通过循环方式来添加tab的行列数据:
      while(tmp.childNodes[0].tBodies[0].rows.length>0)
        tab.tBodies[0].appendChild(tmp.childNodes[0].tBodies[0].rows[0]);为了方便表达,上面的代码用的js语法,请自行翻译成C++语法。
      

  2.   

    感谢jameshooo确实有点麻烦
    我已经通过IHTMLElementCollection::item()方法获得了该Table的IDispatch接口,现在只是将这个IDispatch接口强制类型转换转成IHTMLTable,不知道这样是否可行?如果可以的话,那么在我得到了一个TD的IHTMLTableCell接口之后如何设置它的值呢?因为IHTMLTableCell接口并没有提供象innerHTML的方法,这肯定是我理解上的不足,所以还望高人指点,帮我澄清一下,谢谢!
      

  3.   

    就因为IHTMLTable没有提供innerHTML方法,而且它的IHTMLElement的innerHTML方法也不可用,所以比较麻烦,只能按照变通方案来做。其实这种变通方案原理很简单,创建一个临时元素来容纳一个临时表格,里面存放着所有新增的行,把临时元素中的行通过appendChild逐个移到目标表格中。
      

  4.   

    谢谢,我用你的方法试一下吧。这是我用来插入表格的代码:void CMyDHtmlDialog::InsertRow(CString* strCols, int num, CString className) 

     CComPtr<IHTMLElement> pElem = NULL; 
     CComPtr<IHTMLTableRow> pRow = NULL; 
     CComPtr<IHTMLTableCell> pCell = NULL;  if( !m_pTable ) return;   //m_pTable就是这个表的IHTMLTable接口 m_pTable->insertRow( 0, (IDispatch**)&pRow );  //在表头插入 for( int i=0; i<num; i++) 
     { 
      pRow->insertCell( -1, (IDispatch**)&pCell ); 
      pElem = pCell; 
      pElem->put_innerText( strCols[i].AllocSysString() ); 
      pCell.Release(); 
      pElem.Release(); 
     }  pElem = pRow; 
     pElem->put_className( className.AllocSysString() ); 
     pElem.Release(); 
     pRow.Release(); 

    可惜上面的代码运行起来很不稳定,经常“跑飞”(有时候在insertRow,有时候在insertCell),以至程序挂了,谁能解释一下吗?
    真的非常感谢!
      

  5.   

    我是参考了这个例子的:
    http://www.codeproject.com/KB/cpp/whotfixcheck.aspx
      

  6.   

    COM接口指针是不能强制转换的,只能使用QueryInterface来转换,所以你的代码是错误的,应该像这样:
    CComPtr<IDispatch> spDisp;
    m_pTable->insertRow(0, &spDisp);
    CComQIPtr<IHTMLTableRow> pRow = spDisp;
    或者
    CComPtr<IHTMLTableRow> pRow;
    spDisp.QueryInterface(&pRow);其余代码也类似。
      

  7.   

    谢谢!我试过这些方法了,发现在DHtmlDialog里用IHTMLTable操作表格很不稳定,经常在一些地方Crash。我用了一个替代的方法,就是在HTML里嵌入一个ActiveX控件,它能获取到要在表格里显示的数据,然后它通过触发事件的方式让javascript执行表格操作(insertRow、insertCell...)。
    而且我发现这个方法效率还挺好,对于数据量很大的表格,由于“事件队列”的缓冲使得界面不至于假死。