vc动态遍历word中的书签名(使用自动化接口)

首先定义几个函数,主要用于动态获取接口属性和方法

STDMETHODIMP CTestntkoView::GetProperty(LPDISPATCH pDisp, LPOLESTR pszName, VARIANT* pvResult)
{
   if (NULL == pDisp) return E_POINTER;

	DISPID dwDispID;
	DISPPARAMS dispparamsNoArgs = {NULL, NULL, 0, 0};

	HRESULT hr = pDisp->GetIDsOfNames(IID_NULL, &pszName, 1, LOCALE_USER_DEFAULT, &dwDispID);
	if(SUCCEEDED(hr)) {

		hr = pDisp->Invoke(dwDispID, IID_NULL, LOCALE_USER_DEFAULT,
			DISPATCH_METHOD | DISPATCH_PROPERTYGET, &dispparamsNoArgs,
			//DISPATCH_PROPERTYGET, &dispparamsNoArgs,
			pvResult, NULL, NULL);
   }

	return hr;
}

STDMETHODIMP CTestntkoView::CallMethod(LPDISPATCH pDisp, LPOLESTR pszName, VARIANT* pvResult, UINT cArgs, VARIANTARG* rgVarParams)
{
    if (NULL == pDisp) return E_POINTER;
    DISPID dwDispID;
    DISPPARAMS dispparams = {NULL, NULL, 0, 0};
    dispparams.rgvarg = rgVarParams;
    dispparams.cArgs = cArgs;

    HRESULT hr = pDisp->GetIDsOfNames(IID_NULL, &pszName, 1, LOCALE_USER_DEFAULT, &dwDispID);
    if(SUCCEEDED(hr)) {
        hr = pDisp->Invoke(dwDispID, IID_NULL, LOCALE_USER_DEFAULT,
                DISPATCH_METHOD, &dispparams, pvResult, NULL, NULL);

        if (FAILED(hr)) {
            hr = pDisp->Invoke(dwDispID, IID_NULL, LOCALE_USER_DEFAULT,
                    DISPATCH_METHOD | DISPATCH_PROPERTYGET, &dispparams, pvResult, NULL, NULL);
        }

    }

	return hr;
}
STDMETHODIMP CTestntkoView::GetPropertyWithParam(LPDISPATCH pDisp, LPOLESTR pszName, VARIANT* pvResult,UINT cArgs, VARIANTARG* rgVarParams)
{
    if (NULL == pDisp) return E_POINTER;
    DISPID dwDispID;
    DISPPARAMS dispparams = {NULL, NULL, 0, 0};
    dispparams.rgvarg = rgVarParams;
    dispparams.cArgs = cArgs;

    HRESULT hr = pDisp->GetIDsOfNames(IID_NULL, &pszName, 1, LOCALE_USER_DEFAULT, &dwDispID);
    if(SUCCEEDED(hr))
	{
        hr = pDisp->Invoke(dwDispID, IID_NULL, LOCALE_USER_DEFAULT,
                DISPATCH_METHOD| DISPATCH_PROPERTYGET, &dispparams, pvResult, NULL, NULL);
    }
	return hr;
}

这次主要是想实现三个功能:

  1. 定位指定书签名的书签
  2. 添加一个书签(当前选中位置插入书签)
  3. 遍历文档中的书签名

废话不多说,贴代码

//转到test书签,新建书签,遍历书签(为了节省地方,三个写在一起)
void CTestntkoView::OnButtonbkmk() 
{
	// TODO: Add your command handler code here
	VARIANT vResult;
	VARIANT vArgs[5];
	VARIANT vtIndex;

	LPDISPATCH pdispDoc = NULL;    //docuemt
	LPDISPATCH pdispApp = NULL;    //Application
	LPDISPATCH pdispSel = NULL;
	LPDISPATCH pdispBookMarks = NULL;  //BookMarks
	LPDISPATCH pdidpRang = NULL;      //Range
	LPDISPATCH pdidpBMCount = NULL;   //BookMarks.Count
	LPDISPATCH pdispBk = NULL;        //BookMark
	
	LONG bkCount = -1;
	BSTR bkName;
	char *pbkName;
	HRESULT hr;

	pdispDoc = m_ntkoocx.GetActiveDocument();
	if(!pdispDoc)
	{
		AfxMessageBox("Unable to get document!\n");
		return;
	}
	
	hr = GetProperty(pdispDoc,OLESTR("Application"),&vResult);
	if(SUCCEEDED(hr) && vResult.pdispVal)
	{
		pdispApp = vResult.pdispVal;
	}
	if(!pdispApp)
	{		
		AfxMessageBox("Unable to get Application!\n");
		goto errorReturn;
	}

	hr = GetProperty(pdispDoc,OLESTR("Bookmarks"),&vResult);
	if(SUCCEEDED(hr) && vResult.pdispVal)
	{
		pdispBookMarks = vResult.pdispVal;
	}
	if(!pdispBookMarks)
	{		
		AfxMessageBox("Unable to get BookMarks!\n");
		goto errorReturn;
	}

	if(!pdispApp)
	{		
		AfxMessageBox("Unable to get BookMarks Count!\n");
		goto errorReturn;
	}

	hr = GetProperty(pdispApp,OLESTR("Selection"),&vResult);
	if(SUCCEEDED(hr) && vResult.pdispVal)
	{
		pdispSel = vResult.pdispVal;
	}
	if(!pdispSel)
	{
		AfxMessageBox("Unable to get Selection!\n");
		goto errorReturn;
	}

	hr = GetProperty(pdispSel,OLESTR("Range"),&vResult);
	if(SUCCEEDED(hr) && vResult.pdispVal)
	{
		pdidpRang = vResult.pdispVal;
	}
	if(!pdidpRang)
	{
		AfxMessageBox("Unable to get Range!\n");
		goto errorReturn;
	}

	//ActiveDocument.Application.Selection.GoTo(-1,0,0,'test');
	vArgs[3].vt = VT_I4;
	vArgs[3].lVal = -1;
	vArgs[2].vt = VT_I4;
	vArgs[2].lVal = 0;
	vArgs[1].vt = VT_I4;
	vArgs[1].lVal = 0;
	vArgs[0].vt = VT_BSTR;
	vArgs[0].bstrVal = ::SysAllocString(OLESTR("test"));

	hr = CallMethod(pdispSel,OLESTR("Goto"),NULL,4,&vArgs[0]);
	VariantClear(&vArgs[0]); //需要释放

	//ActiveDocument.Bookmarks.Add(BookMarkName,saverange);	
	VARIANT vtAdd[2];
	vtAdd[1].vt = VT_BSTR;
	vtAdd[1].bstrVal = ::SysAllocString(OLESTR("wql"));
	vtAdd[0].vt = VT_DISPATCH;
	vtAdd[0].pdispVal = pdidpRang;

	hr = CallMethod(pdispBookMarks,OLESTR("Add"),NULL,2,&vtAdd[0]);
	VariantClear(&vtAdd[0]);

	/*var doc =控件对象.ActiveDocument;
	var bks = doc.Bookmarks;
	var bksCount = bks.Count;
	for(i=1;i<=bksCount ;i++){
		alert(bks(i).Name);
	} 
	ActiveDocumet.BookMarks.Count
	*/

	hr = GetProperty(pdispBookMarks,OLESTR("Count"),&vResult);
	if(SUCCEEDED(hr) && vResult.lVal)
	{
		bkCount = vResult.lVal;
	}
	if(bkCoun < 0)
	{       
		AfxMessageBox("Unable to get BoookMarks Count!\n");
		goto errorReturn;
	}

	for (LONG i=1; i<=bkCount; i++)
	{
		vtIndex.vt = VT_I4;
		vtIndex.lVal = i;
		hr = GetPropertyWithParam(pdispBookMarks,OLESTR("Item"),&vResult,1,&vtIndex);
		if(SUCCEEDED(hr) && vResult.pdispVal)
		{
			pdispBk = vResult.pdispVal;
		}
		if(!pdispBk)
		{
			AfxMessageBox("Unable to get BookMark!\n");
			goto errorReturn;
		}
		hr = GetProperty(pdispBk,OLESTR("Name"),&vResult);
		if(SUCCEEDED(hr) && vResult.bstrVal)
		{
			bkName = vResult.bstrVal;
		}
		pbkName = _com_util::ConvertBSTRToString(bkName);   //转换下
		MessageBox(pbkName);
	}
	VariantClear(&vtIndex);

errorReturn:    //Release
	if(pdispSel)
	{
		pdispSel->Release();
		pdispSel = NULL;
	}
	if(pdispApp)
	{
		pdispApp->Release();
		pdispApp = NULL;
	}
	if(pdispDoc)
	{
		pdispDoc->Release();
		pdispDoc = NULL;
	}
	if (pdispBookMarks)
	{
		pdispBookMarks->Release();
		pdispBookMarks = NULL;
	}
	if (pdispBk)
	{
		pdispBk->Release();
		pdispBk = NULL;
	}
}





你可能感兴趣的:(vc动态遍历word中的书签名(使用自动化接口))