HTML(3):IE浏览器编程

Q求救!!! 取ie浏览器文字乱码问题,高分相赠!!! 
T我所写的一个程序中有这样一个功能:用户选取了ie浏览器中的一段文字copy到剪贴板,我的程序从剪贴板中取出文字并显示在edit框中,这在中文系统下没有任何问题,而当程序运行在英文日文98下时,ie中的中文字符从剪贴板中取后在edit框中显示为
乱码,edit框已设了MS Song体,能正确显示gb2312编码的汉字,估计ie中的中文为unicode什么的,我就想把它转为ascii码,但试了很多方法都不行.

if(OpenClipboard())
{
   if(IsClipboardFormatAvailable (CF_UNICODETEXT))
  {
    WCHAR *s;
    CString string;
    HANDLE handle=GetClipboardData(CF_UNICODETEXT);
    s=(WCHAR*)handle;
    string=s;
    string.TrimLeft();
    string.TrimRight();
    if(string!="")
   {
     char dest[256];
     len=string.GetLength();
     int len = WideCharToMultiByte(CP_ACP,0,s,len,dest,256,NULL,NULL);
     GetDlgItem(IDC_EDIT1)->SetWindowText(dest);//显示乱码
   }
   EmptyClipboard();
   CloseClipboard();
}

到底ie中的中文字符是什么编码,怎样转成gb2312,请各位高人指点,一定高分相赠!!!
AIMultiLanguage::ConvertStringFromUnicode Method

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

Translates the source Unicode string to the specified multibyte code page.

Syntax

HRESULT ConvertStringFromUnicode(
    DWORD *pdwMode,
    DWORD dwEncoding,
    WCHAR *pSrcStr,
    UINT *pcSrcSize,
    CHAR *pDstStr,
    UINT *pcDstSize
);

Parameters

pdwMode
[in, out] Storage for conversion context. A calling function should only provide storage that is initialized with zero at the first call to the method. The caller should not modify the value.
dwEncoding
[in] Code page identifier value for the destination multibyte string. This value is equivalent to the uiCodePage member of the MIMECPINFO structure assigned to dwEncoding.
pSrcStr
[in] Address of the Unicode string that is to be converted.
pcSrcSize
[in, out] Address of the buffer that stores the length of the source string, in character counts. If this is NULL, or if -1 is specified as the length, the API assumes pSrcStr is null-terminated. When conversion is successful, the method returns the number of characters processed to this buffer.
pDstStr
[in] Address of the string buffer where the conversion result will be stored.
pcDstSize
[in, out] Address of the buffer that stores the length of pDstStr, in byte counts. When conversion is successful, the method returns the number of bytes copied to pDstStr to this buffer.
Return Value

Returns one of the following values:

S_OK Success. 
S_FALSE The specified conversion is not supported on the system. 
E_FAIL An error occurred. 

Remarks

Note that the size of the Unicode string to be converted is specified with a character count, while the size of the multibyte string returned is given in bytes.

See Also

IMultiLanguage2::ConvertStringFromUnicodeEx, IMultiLanguage2::ConvertStringInIStream, IMultiLanguage2::ConvertStringToUnicodeEx

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

http://www.batutis.com/i18n/papers/mlang/
Using IMultiLanguage2
 

To access the methods provided by IMultiLanguage2, a program must instantiate a MultiLanguage object and request the IMultiLanguage2 interface. This is can be done via the COM API CoCreateInstance. For example:

 

   hr = CoCreateInstance(

                           CLSID_CMultiLanguage, //Class identifier (CLSID) of the object

                           NULL,                                              //Pointer to controlling IUnknown

                           CLSCTX_INPROC_SERVER,   //Context for running executable code

                           IID_IMultiLanguage2 ,                  //Reference to the identifier of the interface

                           (void**) &pMultiLanguage2               //Address of output variable that receives

                                                                              // the interface pointer requested in riid

                           );

 

This call will return the address of the IMultiLanguage2 interface in pMultiLanguage2.

 

Note that if you are using Microsoft Visual C++ (MSVC) to create an IMultiLanguage2 client you will need to install a recent version of the Microsoft Platform SDK (the April 2000 version is sufficient). The Mlang.h and UUID.LIB that are supplied with MSVC itself do not support IMultiLanguage2.

 

Once the program has retrieved the interface pointer, it can then make calls into the IMultiLanguage2 API methods. For example:

 

    pMultiLanguage2->ConvertString(            pdwMode,

                                                            1252,

                                                            437,

                                                            pSrcStr,

                                                            pcSrcSize,

                                                            pDstStr,

                                                            pcDstSize

                                                            );

 

This call copies characters from the source buffer to the destination buffer while doing an encoding conversion from code page 1252 to code page 437.

 

One might wonder why Microsoft created this API when there’s a pair of perfectly good Win32 APIs that can be used to do the same thing: MultibyteToWideChar and WideCharToMultibyte. Not only can this pair of calls do what IMultiLanguage2::ConvertString can do, but also you can supply a number of additional options in the Win32 APIs to control the conversion more completely. In addition, the Win32 APIs return more useful error codes.

 

One reason might be the apparent inability of MultibyteToWideChar and WideCharToMultibyte to support popular Internet encodings like EUC‑KR and ISO‑2022‑JP on Windows NT 4 and Windows 95/98 even with the appropriate language pack installed. (There is no such limitation on Windows 2000.) Perhaps the Windows and IE development teams are finally in synch in this respect. However, at this writing, there are some useful options available via the MLang Converter object that are not available via the Win32 APIs (see below).

Q关于网址过滤 
T似乎用BHO可以控制IE,但是对ATL,COM还没怎么接触,哪位用过BHO的给讲解一下吧。111222的那篇我看过了,还是感觉不知道怎么开始。。。。
ABHO只对IE有效,除非你规定用户只能用IE或者你自己编写的浏览器,否则用户用其他浏览器可以绕过你的限制
另外一种方法是写一个防火墙……但是防火墙也是可以被绕过去的
要想真正屏蔽一个站点,可以使用屏蔽某搜索引擎时使用的方法

是从中国电信的出国网关那里做文章……你的办法可能只对基于IE的浏览器有效,但是你怎么禁止用户使用Netscape?

MSDN

Web Development (General)

Technical Articles  

Browser Helper Objects: The Browser the Way You Want It

在函数
Invoke(DISPID dispidMember, REFIID riid, LCID lcid, WORD wFlags,
 DISPPARAMS* pDispParams, VARIANT* pvarResult,
    EXCEPINFO*  pExcepInfo,  UINT* puArgErr)
中捕获DISPID_BEFORENAVIGATE2事件,如果需要过滤网址的话,pDispParams取得第五个参数并判断(参见BEFORENAVIGATE2事件的文档)并适当设置第一个参数(参见BEFORENAVIGATE2事件的文档)

注意看Browser Helper Objects: The Browser the Way You Want It的这一段

By calling the IConnectionPoint's Advise() method, the BHO lets the browser know that it is interested in receiving notifications about events. Due to the COM event-handling mechanism, all this actually means that the BHO provides the browser with a pointer to its IDispatch interface. The browser will then call back the IDispatch's Invoke() method, passing the ID of the event as the first argument.

HRESULT CViewSource::Invoke(DISPID dispidMember, REFIID riid,
   LCID lcid, WORD wFlags, DISPPARAMS* pDispParams,
   VARIANT* pvarResult, EXCEPINFO* pExcepInfo, UINT* puArgErr)
{
  if (dispidMember == DISPID_DOCUMENTCOMPLETE) {
      OnDocumentComplete();
      m_bDocumentCompleted = true;
  }
  :
}

It's important to remember to disconnect from the browser when events are no longer needed. If you forget to do this, the BHO will remain locked even after you close the browser's window. (Among other things, this means you can't recompile or delete the object.) A good time to disconnect is when you receive the OnQuit event.
Q急,急!用Script解释组件实现的一个脚本解释程序,如何自行解释windows等IE内置对象??? 
T使用MS的VBScript,JScript解释器能够解释脚本了,但IE是如何做到,当用户调用windows.open方法就打开一个新的IE文档,我该怎么做,使得用户一调用open方法,我就自行解释打开自己程序的文档??? IE下的脚本并且可以使用一些内置的IE变量,IE是如何编程做到的???
一句话,使用MS的脚本解释器,如何让脚本语言执行时能识别调用,父程序明白的函数与变量。
Aexternal.yourfuntion?

Extending the Dynamic HTML Object Model
It is possible for the hosting application to extend the Dynamic HTML Object Model so that scripts can refer to functionality implemented by the host. Such scripts refer to the host by specifying the external object that is available from the window object. For example, a reference to "window.external.speech" will call the host to resolve the name "speech." All standard script within the document will be executed normally.

This extension mechanism is implemented in the host by providing an IDispatch interface for the object model extension that will have IDispatch::GetIDsOfNames and IDispatch::Invoke called on it to resolve any references to the external object. The IDispatch that the host provides is obtained by the WebBrowser Control or MSHTML component by calling the host's IDocHostUIHandler::GetExternal method.

For an example of how to extend the Dynamic HTML Object Model, see the Driller Sample Source Page
Q请教:如何用VC得到当前IE正在浏览的网页的网址和title?
T我想在IE右键快捷菜单中加入一项,选择时即可获得当前网页的网址和title,我该如何做?
AKnowledge Base Articles  

HOWTO: Connect to a Running Instance of Internet Explorer
Q176792

Q如何获得IE Frame 当中的scroll bar 的位置 masterz Jiangsheng help!!!! 
T使用给位已经提供的方法可以获得IE Scroll bar 的位置

但是如果是一个子frame 中,简单的使用IHTMLBody的方法,在有些IE版本 无法获得相对应的scroll bar 的位置 (总是0)请问如何获得frame 中的滚动条的位置
AFrame.document.Body是否支持IHTMLTextContainer?
Q急!!!!!关于IE控件 500分相送!!! 
T请问我已经得到IHTMLDocument2 如何把它显示到CWebBrowser2控件中呢?
Aquery IPersistStream for HtmlDocument object,and then call IPersistStream::Load from a memory stream created by CreateStreamOnHGlobal.

1 Create a WebBrowser host in Microsoft Visual C++ 6.0 or 7.0. For a sample implementation that uses the Active Template Library (ATL), see the following Microsoft Developer Network (MSDN) Web site:

Web and Internet Samples: ATLBrowser
http://msdn.microsoft.com/downloads/samples/internet/default.asp?url=/Downloads/samples/Internet/browser/atlbrowser/Default.asp

2 Sink DWebBrowserEvents2 on the WebBrowser control. For more information about sinking WebBrowser events, see the following MSDN Web site:


Reusing the WebBrowser Control: Working with WebBrowser Events
http://msdn.microsoft.com/library/default.asp?url=/workshop/browser/webbrowser/webbrowser.asp

3 When your application is created, call the IWebBrowser2 Navigate() method to move the WebBrowser to "about:blank".


4 Add code to your DWebBrowserEvents2::DocumentComplete() event handler to load a file from memory:


    If (m_bInitial)  //m_bInitial is used to prevent the DocumentComplete event from being fired recursively, set it to TRUE
after the Navigate() call.
    {
        HRESULT hr = E_FAIL;

        CComPtr<IStream> spStream;
        DWORD dwWritten = 0;
        DWORD dwBytes = 0;

        HANDLE handle = CreateFile("c://temp//test.htm", GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
        if (handle != INVALID_HANDLE_VALUE)
        {
                TCHAR szBuffer[10240];
                DWORD dwBytesRead;

                if (ReadFile(handle, szBuffer, sizeof(szBuffer) - 1, &dwBytesRead, NULL))
                {
                    szBuffer[dwBytesRead] = '/0';
                    CloseHandle(handle);
       
                    if (SUCCEEDED(CreateStreamOnHGlobal(NULL, TRUE, &spStream))) {
                        dwBytes = lstrlenA(szBuffer) + 1;
                        dwWritten = 0;
                        hr = spStream->Write(szBuffer, dwBytes, &dwWritten);
                        LARGE_INTEGER li = {0, 0};
                        spStream->Seek(li, STREAM_SEEK_SET, NULL);

                        CComPtr<IDispatch> spDispatch;
                        hr = m_pWebBrowser->get_Document(&spDispatch);
       
                        if (SUCCEEDED(hr)) {
                            CComQIPtr<IPersistStreamInit> spPersistStreamInit(spDispatch);
                            if (spPersistStreamInit != NULL) {
                                hr = spPersistStreamInit->InitNew();
                                if (SUCCEEDED(hr)) {
                                    hr = spPersistStreamInit->Load(spStream);
                                }
                           }
                      }
                 }
             }
         } 
    }
    m_bInitial = FALSE;

#include "mshtml.h"
//在SourceView中填写HtmlView中网页的源程序
void CMainFrame::OnMethod2()
{
    IHTMLDocument2 *pHTMLDocument=NULL;
    IPersistStreamInit *pPSI=NULL;

    IStream *pStream=NULL;
    HGLOBAL  hHTMLText;

    if  (!(pHTMLDocument = (IHTMLDocument2*)m_pHtmlView->m_browser.GetDocument()))
 return;
 
    if  (FAILED(pHTMLDocument->QueryInterface(&pPSI)))
    {
//   pHTMLDocument->Release();
 return;
    }

    hHTMLText = GlobalAlloc(GMEM_FIXED, MAX_SIZE);
    CreateStreamOnHGlobal(hHTMLText, TRUE, &pStream);
    pPSI->Save(pStream, FALSE);

//   m_pSourceView->SetWindowText((char*)hHTMLText);

    long nEditLength = m_pSourceView->GetEditCtrl().GetWindowTextLength();
    m_pSourceView->GetEditCtrl().SetSel(0, nEditLength);
    m_pSourceView->GetEditCtrl().ReplaceSel("");
    char *pText = (char*)hHTMLText;
    long lHtmlLength = strlen(pText);
    CString str("");
    long n = 0;
    for (long i=0; i < lHtmlLength; i++)
    {
     if  (*pText != 0x0d && *pText != 0x0a)
     {
      str += *pText;
      pText++;
     }
     else
     {
      pText++;
      if  (*pText == 0x0a)
   pText++;
      str += "/r/n";
      nEditLength = m_pSourceView->GetEditCtrl().GetWindowTextLength();
      m_pSourceView->GetEditCtrl().SetSel(nEditLength, nEditLength);
      m_pSourceView->GetEditCtrl().ReplaceSel(str);
      str.Empty();
     }
    }

    pStream->Release();
    pPSI->Release();
//   pHTMLDocument->Release();
}

三、修改HTML源代码以改变网页的显示

    这部分比较有意思,可以当作是一个小的HTML编辑器,看看预演效果。特别的不是显示一个新文件,而是修改原来的HTML文件。
关键代码:

//根据SourceView里的HTML文本改变HtmlView里的显示
void CMainFrame::OnChangehtml()
{
 IHTMLDocument2 *pHTMLDocument=NULL;
 IPersistStreamInit *pPSI=NULL;

 IStream *pStream=NULL;
 HGLOBAL  hHTMLText;

 if (!(pHTMLDocument = (IHTMLDocument2*)m_pHtmlView->m_browser.GetDocument()))
  return;
 
 if (FAILED(pHTMLDocument->QueryInterface(&pPSI)))
 {
//  pHTMLDocument->Release();
  return;
 }

 pHTMLDocument->clear();
 pPSI->InitNew();

 LPCTSTR strText = m_pSourceView->LockBuffer();
 DWORD dwLength = strlen(strText);
 hHTMLText = GlobalAlloc(GMEM_FIXED, dwLength);
 memset(hHTMLText, 0, dwLength);
 memcpy(hHTMLText, strText, dwLength);
 m_pSourceView->UnlockBuffer();
 CreateStreamOnHGlobal(hHTMLText, TRUE, &pStream);
 ULARGE_INTEGER libNewSize;
 libNewSize.QuadPart = dwLength;
 pStream->SetSize(libNewSize);这一步必须要,否则显示时会有多余字符出现
 pPSI->Load(pStream);

 pStream->Release();
 pPSI->Release();
// pHTMLDocument->Release();
}
Q请问 ie如何实现复制文字到剪贴板中? 
Tie本身显示的不是文本文件但通过复制在剪贴板中保留的却是文本文件,难道也是拦截的api? 我应该怎么做!
AIE复制的剪贴板内容有多种格式,比如text,html,image等等。
http://expert.csdn.net/Expert/topic/1462/1462971.xml?temp=.6424677
Q   包含IE控件的问题(如何得到IE页面输入值) 
T我想做一个包含IE控件的程序,然后在这个控件的页面上有几个文本框。

请问:当这个页面提交时,我如何得到文本框中输入的值?
ABOOL CDlgEdit::SaveData()
{
 _variant_t varVal;
 try{
  //given id?
  if(m_varItemID.vt!=VT_CLSID){
   //new record,add new
   m_rst->AddNew();
  }
  FieldsPtr pFields=m_rst->Fields;
  FieldPtr pItem;
  CString strFieldName;
  long lFields=pFields->Count;
  //for each field
  for(long i=0;i<lFields;i++){
   pItem=pFields->Item[i];
   strFieldName=(LPCTSTR)pItem->Name;
   IHTMLInputTextElementPtr pElement;
   //get html element by id
   GetElementInterface(strFieldName,IID_IHTMLInputTextElement,reinterpret_cast <void**>(&pElement));
   if(pElement){
    CComBSTR bstrFieldValue;
    pElement->get_value(&bstrFieldValue);
    //if natural data type
    CString strDataType=DataTypeGetFieldProperty(m_strDataType,strFieldName,"FieldType");
    //clear before use
    varVal=g_varEmpty;

    if(strDataType.IsEmpty()){//default translate
     g_SetValueString(varVal,_bstr_t(bstrFieldValue),g_AdoType2VARTYPE(pItem->Type));
    }
    else{//find alias or name
     g_SetValueString(varVal,_bstr_t(bstrFieldValue),strDataType,TRUE);
    }
    pItem->Value=varVal;
   }
  }  
  m_rst->Update();
 }
 catch(_com_error &e){
  ESErrPrintProviderError(g_connection);
  ESErrPrintComError(e); 
  return FALSE;
 }
 return TRUE;
}

说明
m_strDataType 编辑对象的数据类型
m_varItemID 编辑对象的ID(VT_CLSID或者VT_NULL类型)
m_rst 编辑对象的记录集
GetElementInterface 获得HTML元素的函数,定义可以在我的文章http://www.csdn.net/Develop/read_article.asp?id=14752中找到
DataTypeGetFieldProperty 获得字段的数据类型
g_SetValueString 根据数据类型设置字段的值
g_AdoType2VARTYPE ADO数据类型和VARIANT数据类型的转换
ESErrPrintProviderError和ESErrPrintComError是从MSDN ADO的示例中的函数g_PrintProviderError和g_PrintComError改编而来

参考文档http://www.csdn.net/Develop/read_article.asp?id=9408

http://www.csdn.net/Develop/read_article.asp?id=9408…

那你要捕获Form的Submit事件,去看www.codeproject.com/shell/dlgdhtmlevents.asp
msdn.microsoft.com/workshop/browser/mshtml/tutorials/sink.asp
Q如何得到IE的网页内容的cache位置(用什么函数)
T我想从ie的cache的内容里得到下载下来的falsh文件。可如何得到IE的网页内容的cache位置,具体的平台,可以看到cache的位置,可用程序如何实现(用什么函数)
AURLDownloadToCacheFile
Using this function ensures that a file name is returned without unnecessary copying of data.
Q如何知道在一个IE页面中,确定按钮被按下? 
T 
Amsdn.microsoft.com/workshop/browser/mshtml/tutorials/sink.asp
COM的钩子就是Event sink
我上面提到的那篇文章里就是讲这个的。
http://www.csdn.net/develop/article/18/18998.shtm
Q用控件自制的ie浏览器,产生新窗口时,完全不在我的ie控件范围内,将我整个对话框都占了,我该怎样控制显示页面位置,
T 
A填写数据的话,可以看看
在对话框中使用网页输入数据 (jiangsheng原创)
http://www.csdn.net/develop/read_article.asp?id=9408
我用的是DHTML控件,用webbeowser控件也是可以的,需要改一下代码。
Q请jiangsheng(蒋晟.Net)接分
T3Q!
A8过以后这种问题还是直接贴出来让大家回答吧,一个人的意见不一定准确,大家一起来讨论比较好
你这个问题偶还想收藏的说,说不定什么时候还有用(主要是下次抢分的时候直接贴链接用)
1 .  能否通过挂接事件连接点拦截脚本运行。如果可以是挂接哪一个接口。
    在IE对脚本进行解释运行前,IE插件能够得到通知,并能够阻止它运行。
    就像实现IShellExecuteHook接口拦截外壳程序运行一样。
2.  通过调用IHTMLElement的get_innerText,可以得到嵌入元素的整个文本。
   那么怎么得到该文本中鼠标下的那个单词呢?
Q关于web控件在使用时的一个小问题,如何过滤掉提示信息对话框? 
T使用web控件,通过该控件浏览已经保存在硬盘上的网页内容。有的时候浏览器会提示“出现了运行时错误,是否需要调试?”或者“你查看的网页正在试图关闭窗口,是否关闭窗口?”。有谁知道答案,谢谢
A www.csdn.net/develop/read_article.asp?id=19627

1
为你的宿主程序实现IDocHostShowUI(重载MFC7的COleControlTontainer,或者使用微软知识库Q236312 HOWTO: Disable the Default Pop-up Menu for CHtmlView里面的方法)
2 innerText

QDHTML应用于windows Applicatoin界面?!讨论! 
T
开发过基于MFC的windows程序设计的朋友都知道,MFC提供的窗体效果和windows本身一样,无法提供很丰富的表现形式,也没有办法随便更改,
虽然有一些界面组件和界面控件,例如cj60,activeSkin之类的,我觉得也不够灵活。

有没有直接用HTML做界面,利用DHTML内部元素与应用程序交互的可能性呢?我已经看到一些程序使用了这些技术,通过IHTMLDocument接口,通过HTML hook技术来进行交互。

可我很难在网上找到比较详尽的技术介绍,请问大家有什么自己的想法吗?!
大家积极讨论,分大大的有!
A
sure
Norton Antivirus UI is HTML pages
use CDHtmlDialog for dialog based app and CHtmlView for SDI/MDI

http://www.csdn.net/develop/read_article.asp?id=21702

每一步都需要检查操作结果和返回的指针
可以用res协议访问

Yes
see BEGIN_EVENTSINK_MAP in MFC
QVC中如何调用Script中的函数?
T
脚本中传来的函数指针是LPDISPATCH,如果直接用ChangeType转为String,得到的结果是包含函数代码在内的整个函数而不是函数名[即便能通过分析来获得...],请问我要如何能够通过这个Dispatch指针来调用这个函数呢?
难道只能生成一个调用字符串插入执行吗?
AJavaScript Calls from C++
http://www.codeguru.com/ieprogram/JSCalls.html

通过GetTypeInfo可以获得类型信息
参见http://www.csdn.net/develop/read_article.asp?id=21702
HRESULT CIEAutomationView::DumpTypeInfo(LPDISPATCH pDisp)
{
 if(pDisp==NULL)return OLE_E_BLANK;
 CComPtr<ITypeInfo> pTypeInfo;
 HRESULT hr = S_OK;
 hr= pDisp->GetTypeInfo(0, GetUserDefaultLCID(), &pTypeInfo);
 if(FAILED(hr))return hr;
 CSmartTypeAttr pTypeAttr( pTypeInfo );
 CSmartFuncDesc pFuncDesc( pTypeInfo );
 hr= pTypeInfo->GetTypeAttr( &pTypeAttr );
 if(FAILED(hr))return hr;
 for(int iMethod = 0; iMethod < pTypeAttr->cFuncs; iMethod++){
  hr= pTypeInfo->GetFuncDesc(iMethod, &pFuncDesc);
  if(FAILED(hr))return hr;
  CString strInvokeType;
  switch(pFuncDesc->invkind){
  case INVOKE_FUNC   :strInvokeType="Function";break;
  case INVOKE_PROPERTYGET :strInvokeType="Property(Get)";break;
  case INVOKE_PROPERTYPUT :strInvokeType="Property(Put)";break;
  case INVOKE_PROPERTYPUTREF:strInvokeType="Property(Putref)";break;
  default:break;
  }
  CComBSTR bstrName;
  unsigned int nNames;
  hr= pTypeInfo->GetNames(pFuncDesc->memid, &bstrName, 1,&nNames );
  if(FAILED(hr))return hr;
  ASSERT( nNames == 1 );
  TRACE("%s/t%s/r/n",CString(bstrName.m_str),strInvokeType);
  pFuncDesc.Release();
 }
 return S_OK;
}
void CIEAutomationView::OnDocumentComplete(LPDISPATCH pDisp, LPCTSTR lpszUrl)
{
 // make sure the main frame has the new URL.  This call also stops the animation
 ((CChildFrame*)GetParentFrame())->SetAddress(lpszUrl);
 CString strURL(lpszUrl);
 IUnknown* pUnkBrowser = NULL;
    IUnknown* pUnkDisp = NULL;
 TRACE(_T("Document %s Done/r/n"),lpszUrl);
 //is it top level document?
 HRESULT hr = m_pBrowserApp->QueryInterface( IID_IUnknown,  (void**)&pUnkBrowser);
 if ( SUCCEEDED(hr) ){
        hr = pDisp->QueryInterface( IID_IUnknown,  (void**)&pUnkDisp );
        if ( SUCCEEDED(hr) ){
            if ( pUnkBrowser == pUnkDisp ){
    //top level
    m_spHtmlDoc=NULL;
    hr=m_pBrowserApp->get_Document(&m_spHtmlDoc);
    TRACE(_T("Downloading Complete/r/n"),lpszUrl);
    DumpTypeInfo(m_spHtmlDoc);
    CComQIPtr<IHTMLDocument2> pHtmlDoc(m_spHtmlDoc);
    IShellBrowser* pShellBrowser=(IShellBrowser*)m_wndBrowser.SendMessage(WM_USER+7,0,0);
    if(pHtmlDoc){
     CComPtr<IHTMLWindow2> pWindow;
     pHtmlDoc->get_parentWindow(&pWindow);
     CComQIPtr<IDispatch> spWindow(pWindow);
     m_domExternal.SetMenuArguments(spWindow);
    }
    if(pShellBrowser){
     CComPtr<IShellView>  pIShellView;
     pShellBrowser->QueryActiveShellView(&pIShellView);
     if(pIShellView){
      FOLDERSETTINGS fs;
      pIShellView->GetCurrentInfo(&fs);
      CComQIPtr<IFolderView>  pIFolderView(pIShellView);
      if(pIFolderView){
       pIFolderView->SetCurrentViewMode(FVM_DETAILS);
      }
     }
     TRACE("Get Shell Browser/r/n");
    }
   }
   pUnkDisp->Release();
  }
  pUnkBrowser->Release();

 }
}

void CIEAutomationView::CallScript(IHTMLWindow2* pWindow2
  ,BSTR bstrCode
  ,BSTR bstrLanguage)
{
 ASSERT(pWindow2);
 HRESULT hr = S_OK;
 COleVariant ret;
 hr = pWindow2->execScript(bstrCode, bstrLanguage, &ret);
}
void CIEAutomationView::CallScriptDirect(IHTMLWindow2* pWindow2
  ,BSTR bstrMethod)
{
 DISPID dispidScriptObject, dispidMethodToInvoke;
 IDispatch *pDispScriptObject;
 DISPPARAMS dispparamsNoArgs = { NULL, NULL, 0, 0};
 HRESULT hr;
 OLECHAR *szScript = L"script";
 OLECHAR *szFuncName = bstrMethod;
 
 IHTMLDocument2* pDocument2 = NULL;
 hr = pWindow2->get_document(&pDocument2);
 ASSERT(SUCCEEDED(hr) && pDocument2);

 IDispatch* pDocDisp = NULL;

 hr = pDocument2->QueryInterface(IID_IDispatch, (void**)&pDocDisp);
 ASSERT(SUCCEEDED(hr) && pDocDisp);

 // Get the DISPID of the document's Script property.
 hr = pDocDisp->GetIDsOfNames(IID_NULL, &szScript,
  1, LOCALE_USER_DEFAULT, &dispidScriptObject);
 ASSERT(SUCCEEDED(hr));

 COleVariant varResult;
 
 // Get the document's Script property.
 hr = pDocDisp->Invoke(dispidScriptObject,
  IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_PROPERTYGET,
  &dispparamsNoArgs, &varResult, NULL, NULL);
 ASSERT(SUCCEEDED(hr) && varResult.pdispVal);

 pDispScriptObject = varResult.pdispVal;

 varResult.Clear();
 // Get the DISPID of the script method to invoke.
 hr = pDispScriptObject->GetIDsOfNames(IID_NULL, &szFuncName, 1,
  LOCALE_USER_DEFAULT, &dispidMethodToInvoke);
 ASSERT(SUCCEEDED(hr));

 // Invoke the script method.
 hr = pDispScriptObject->Invoke(dispidMethodToInvoke, IID_NULL,
  LOCALE_USER_DEFAULT, DISPATCH_METHOD, &dispparamsNoArgs,
  &varResult, NULL, NULL);
 ASSERT(SUCCEEDED(hr));

 pDocDisp->Release();
 pDocument2->Release();

}
Q怎么得到IE容器包含的对象的服务的接口指针
T
我的IE页面:
<OBJECT
<OBJECT ID=p1
CLASSID="CLSID:1546B217-B1B4-42A9-B954-003CEA26E0FC">
</OBJECT>

<iframe id=p2 HEIGHT=50% WIDTH=100% src=./11.doc> </IFRAME>

我页面上有一个我的p1控件,还有一个word服务器
我想用我的p1去操作11.doc的Word服务器。

我得到IE的IOleContainer容器接口,然后用IOleContainer::EnumObjects来枚举包含的对象。可以得到两个对象,一个是我自p1对象(可以得到IOleObject),一个却是iframe对象(能访问到IHTMLIFrameElement),但得到IHTMLIFrameElement后怎么也得到对应word的IOleObject或理Word对象_Documnet这些接口。

我又用另一种方式,我先得到页面的IHTMLDocument2,再得到p2的IHTMLElement,但还是不能进而得到Word对象。

有哪们大虾告诉我怎么才得到到IE容器内的Word对象接口?我500分谢。
A使用Frame对象的IWebbrowser2接口(可以从IHTMLElement或者IHTMLIFrameElement查询)的document属性可以获得word.appacation对象的IDispatch接口

http://www.csdn.net/develop/author/netauthor/jiangsheng/files/webbrowserAutomationsrc.zip

用这个程序打开一个doc文档,然后看VC的output窗口的debug部分

需要最新版本的platform SDK
http://www.microsoft.com/msdownload/platformsdk/sdkupdate/
IWebbrowser2::get_Documnet只在载入了文档之后才不为空

装了之后要设置包含目录顺序的
载入了文档就是顶层框架documentcomplete事件触发之后
Q***200分,如何取得链接所属的网页url和该链接名称?****
T
在FlashGet中可以做到,从IE中拖一个链接到FlashGet中,它能取得该链接所指向的url,
还能取到引用Referer(即该链接所属网页的url,例http://www.xxx//xxx.html),和能取到注释Comment(即该链接的名称,例如'点这里下载-> 本地下载')

而我用了网上某个类只能取到链接所指向的url,
请教,不知如何才能取得链接所属的网页url和该链接名称?

A
The hyperlink object
A hyperlink object implements the IHlink interface and encapsulates four pieces of reference information: a moniker to the hyperlink target; a string for the location within the target; a friendly name for the target; and additional parameters.

The hyperlink object completely encapsulates the behavior of navigating to a referenced location. It also supports the ability to save and load itself through the IPersistStream interface, and the ability to be transferred through the clipboard or through drag-and-drop operations by means of IDataObject. A standard hyperlink object implementation is provided with the system, and it is not advisable to implement another version. A document can use the standard hyperlink object to represent hyperlinks within itself, thus encapsulating the work of navigating, saving, loading, dragging, dropping, cutting, and pasting hyperlinks. Standard hyperlink objects are created through the HlinkCreateFromData, HlinkCreateFromMoniker, HlinkCreateFromString, and OleLoadFromStream functions. The standard hyperlink object implements the IHlink, IPersistStream, and IDataObject interfaces.

IHlink::GetHlinkSite Method

The hyperlink container
A hyperlink container is a document or application that contains hyperlinks. The container supports hyperlinks by implementing the IHlinkSite interface and, if the container's objects can be targets of other hyperlinks, the IHlinkTarget interface.

Note   Generally, an object that acts as a hyperlink container can also act as a hyperlink target. An HTML page, for example, can contain a number of hyperlinks to other pages, while at the same time it can be the target of hyperlinks from other HTML pages.
The hyperlink site
A hyperlink site is a COM object that implements the IHlinkSite interface and supplies either the moniker or interface identifier of its hyperlink container. One hyperlink site can serve multiple hyperlinks. The moniker supplied by the hyperlink site is used to evaluate relative monikers to the hyperlink target. If the relative moniker is NULL, the target of the link is in the same container object, and IHlink::Navigate can result in an efficient internal jump

Note   The standard hyperlink object performs internal jumps by retrieving the container's IHlinkTarget moniker using IHlinkTarget::GetMoniker (which avoids an unnecessary moniker bind). The object then asks the container to navigate directly through the IHlinkTarget::Navigate method
Q用VC如何获取网页中的链接和鼠标点击处的链接?
T各位给个例子看看?
A
anchors Property (IHTMLDocument2)

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

Retrieves an interface pointer to a zero-based collection of all the A objects in an HTML document. The elements are in the same order as they appear in the document.

Syntax

HRESULT IHTMLDocument2::get_anchors(IHTMLElementCollection **p);
activeElement Property (IHTMLDocument2)

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

Retrieves the object that has the focus when the parent document has focus.

Syntax

HRESULT IHTMLDocument2::get_activeElement(IHTMLElement **p);
Parameters

p
Address of a pointer to an IHTMLElement interface that receives the element that has the focus.
Return Value

Returns S_OK if successful, or an error value otherwise.
Remarks

Set the active element with the setActive or focus methods. Using the setActive method has no effect on document focus. Using the focus method on an individual element causes the element to gain focus and become the active element.

The active element remains the active element even when focus has been placed outside the parent document. If no particular object is given focus when focus returns to the parent document, then the active element will gain focus. Select the title bar of a different application and then select the initial browser title bar to confirm this. Focus is shifted to the other application initially, but returns to the same active element as before the selection


see WorkAll Sample in Platform SDK.

http://www.csdn.net/expert/topic/478/478341.shtm
Q怎样判断IE已经加载完成,并取得IDocument2指针,网页高手快来
T
源码如下:
ShellExecute(NULL, _T("open"), "www.csdn.net", NULL,NULL, SW_HIDE|SW_MINIMIZE);
hWnd=::FindWindow("IEFrame",NULL);
 CoInitialize( NULL );
 {
  HINSTANCE hInst = ::LoadLibrary( _T("OLEACC.DLL") );
 if ( hInst != NULL )
 {
  if(hWnd!= NULL )
 {
  HWND hWndChild=NULL;
    // Get 1st document window
  ::EnumChildWindows(hWnd, EnumChildProc, (LPARAM)&hWndChild );
  if(hWndChild)
  {
  CComPtr<IHTMLDocument2> spDoc;
  LRESULT lRes;  
  UINT nMsg = ::RegisterWindowMessage( _T("WM_HTML_GETOBJECT") );
  ::SendMessageTimeout( hWndChild, nMsg, 0L, 0L, SMTO_ABORTIFHUNG, 1000, (DWORD*)&lRes );
  LPFNOBJECTFROMLRESULT pfObjectFromLresult = (LPFNOBJECTFROMLRESULT)::GetProcAddress( hInst, _T("ObjectFromLresult") );
  if ( pfObjectFromLresult != NULL )
  {
   HRESULT hr;
   hr = (*pfObjectFromLresult)( lRes, IID_IHTMLDocument, 0, (void**)&spDoc );
  if ( SUCCEEDED(hr) )
  {
   CComPtr<IDispatch> spDisp;
   CComQIPtr<IHTMLWindow2> spWin;
  
   spDoc->get_Script( &spDisp );
   spWin = spDisp;
   spWin->get_document( &spDoc.p);
  
   // Change background color to red
   //spDoc->put_bgColor( CComVariant("red") );
   //下面的代码填写登陆表单
   IHTMLElementCollection *objAllElement=NULL;
   spDisp.p=NULL;
  // IHTMLDocument2 *objDocument=spDoc;
   spDoc->get_all(&objAllElement);
objAllElement->item(COleVariant("a"),COleVariant((long)0),&spDisp);
//spDisp提示为空,表明没有找到"a",怎么回事
                         
A
主  题:MsHtml的问题
作  者:111222
所属论坛:Visual C++
问题点数:300
回复次数:36
发表时间:2001-11-1 19:19:18
 
 
网页里<table>怎么找出来?
http://www.csdn.net/expert/topic/351/351580.shtm

原理是一样的啊
通过DOM来访问元素

HOWTO: Get IHTMLDocument2 from a HWND

Q249232


--------------------------------------------------------------------------------
The information in this article applies to:

Microsoft Internet Explorer (Programming) versions 4.0, 4.01, 4.01 SP1, 4.01 SP2, 5, 5.5


Q
I use the Active Accessibility SDK to obtain an IHTMLDoc-ument2 pointer from a window handle (HWND). Is there any way to obtain an IWebBrowser2 pointer from the IHTMLDocument2 pointer? I抳e tried QueryInterface on both the document pointer as well as the IHTMLWindow2 pointer without results. I also tried the IOmNavigator * from get_navigator on the HTMLWindow2 pointer. Any ideas?

A
This is a common cause for COM consternation. You have the window, document, or browser and you know you should be able to get the others, but everywhere you turn, QueryInterface delivers a big fat NULL. The answer lies in the mysterious IServiceProvider whose job it is, well, to provide services. IServiceProvider is a great interface: it has only one method, QueryService. If you抮e using ATL smart pointers, it looks like this. First, you have to get the IServiceProvider.

CComQIPtr<IServiceProvider> isp = pIHTMLDocument2;

This does a QueryInterface on the document for IServiceProvider. Once you have it, you can get the browser like so.

CComQIPtr<IWebBrowser2> iwb2;
isp->QueryService(IID_IWebBrowserApp,
    IID_IWebBrowser2, (void**)&iwb2);

      If all this seems confusing, there抯 a good reason for it. A cardinal rule of COM is that QueryInterface must always return an interface to the object queried. But the document doesn抰 implement IWebBrowser2; it only knows how to get the object that does. The document, browser, and window are all separate objects. In general, IServiceProvider is used whenever a bunch of separate but related COM objects together implement some kind of service. QueryInterface asks an object, do you implement this interface? QueryService tells a service provider, "get me whatever object implements this interface, please." With QueryService, the interface pointer returned may or may not be the same object as the one queried. Figure 6 illustrates the system. All the objects implement their various interfaces and store internal pointers to one another; IServiceProvider is your way to get whichever object implements a particular interface. IServiceProvider::QueryService chases the internal pointers to retrieve the object that implements the interface you want.


Figure 6 Many Objects, One IServiceProvider

      IServiceProvider is essential for navigating the DHTML object hierarchy. Say you抮e writing an ActiveX&reg; control and you want to navigate the object model. How do you do it? First, query your IOleClientSite for IServiceProvider like so:

CComQIPtr<IServiceProvider> isp = pSite;

then, once you have IServiceProvider, you can QueryService it for the application object.

CComQIPtr<IWebBrowserApp> iwba;
isp->QueryService(IID_IWebBrowserApp,
    IID_IWebBrowserApp, (void **)&iwba);

Now you can navigate the object hierarchy (the app object is at the top). If you want the Web browser, it抯 the same as before.

CComQIPtr<IWebBrowser2> iwb2;
isp->QueryService(IID_IWebBrowserApp,
 IID_IWebBrowser2, (void **)&iwb2));

      In all these examples, SID_SWebBrowserApp identifies the service, but you抣l often see code that uses IID_IWebBrowserApp as the service ID. Either will work, since <shlguid.h> #defines SID_SWebBrowserApp to IID_IWebBrowserApp, but for programming pedants SID_SWebBrowserApp is technically more correct, and more clear to anyone reading your code.
      By the way, if you抮e brave enough to implement some far-reaching colossal object system such as the DHTML object model (Lord help you!), then you should implement IServiceProvider too.




webbrowser没初始化完的话,IHTMLDocument2是空。也就是说,新的IE窗口在一段时间内肯定没有文档(要是默认主页很大的话,这个时间可以很长)
看来要用BHO解决了。

QIE6编程问题,真的是难呀!不是高手就别浪费时间了,100分!(决无贬义,只求广告效应)
T
调用IE的ExecWB(...)想弹出“另存为”的窗口,  
CHtmlView.ExecWB OLECMDID_SAVEAS,  OLECMDEXECOPT_DODEFAULT
但是 
  我不想显示弹出的“另存为”的窗口,还想存为下拉框中的某种非默认格式,
  如何实现?难吧!
  请指教。
  谢谢!

A

 
主  题:  超超超超超级难题!!!!给你10个URL,你能把自动他们都存成*.mht文件吗??????
作  者:  111222 (张小白) 
 
http://www.csdn.net/expert/topic/786/786376.xml
 回复人: masterz() (  ) 信誉:98  2002-6-7 17:42:45  得分:300 
 
 
  #import "c:/program files/common files/system/ado/msado15.dll" no_namespace rename("EOF", "EndOfFile")
#import <cdosys.dll> no_namespace rename("EOF", "EndOfFile")
............
void CSavemhtDlg::OnOK()
{
 // save url as a single file, in fact I don't know if it is mht file, but it can be opened by IE, can someone tell me?
 CoInitialize(NULL);
 {
  IMessagePtr       iMsg(__uuidof(Message));
  IConfigurationPtr iConf(__uuidof(Configuration));
  iMsg->Configuration = iConf;
  try
  {
    iMsg->CreateMHTMLBody(
       "http://example.microsoft.com",
       cdoSuppressNone,
       "domain//username",
       "password");
  }
  catch(_com_error err)
  {
    // handle exception
  }
  _StreamPtr pStream=iMsg->GetStream();
  pStream->SaveToFile("test.mht",adSaveCreateOverWrite);
 }
 CoUninitialize();
}

 
 

Q如何获得对网页上按钮之类控制的消息?(在VC里)
T如在里使用IE控件作浏览网站的东东时,如何得到对网页按钮的点击消息呢?
A
Receiving Element Events
Each element in the DHTML Object Model supports an outgoing HTMLElementEvents2 interface. This interface defines the events that an HTML element can fire. You implement this interface to provide an event sink, which is a Component Object Model (COM) object that implements an outgoing interface and is used as the mechanism for firing events.

Note  Interfaces implemented by a server usually have their methods called by the client, but to fire an event, the server calls the respective method on the client event sink. These interface are called outgoing interfaces. A COM object that implements an outgoing interface is also known as a connectable object.
The following steps are required to receive events from an outgoing interface:

Implement the event sink.

The event sink implements the appropriate outgoing interface and methods. Internet Explorer event interfaces are dispinterfaces, so calls to event methods are made through IDispatch::Invoke . This means that you only need to implement the IDispatch interface to handle events.

Determine if the server is a connectable object.

Call QueryInterface  to retrieve a pointer to the IConnectionPointContainer  interface.

Find the appropriate connection point.

Call the IConnectionPointContainer::FindConnectionPoint  method to find the connection point you need. For Internet Explorer WebBrowser Control events, such as DWebBrowserEvents2::DocumentComplete, this is DWebBrowserEvents2. For element events, this is HTMLElementEvents2. You can also call the IConnectionPointContainer::EnumConnectionPoints  to enumerate through all the connection points a server supports.

Advise the connection point that you want to receive events.

Using the IConnectionPoint  interface pointer returned in the previous step, call IConnectionPoint::Advise , passing the IUnknown  interface pointer of your event sink.

 
Note  The connectable object will use the IUnknown interface pointer to query the client for the event sink interface. If the event sink does not support the outgoing interface, Internet Explorer will query the client for the IDispatch interface.
When you no longer want to receive events, you can call the IConnectionPoint::Unadvise  method, passing the cookie you received from the call to IConnectionPoint::Advise

The following sample code demonstrates how to begin receiving HTML element events for an element on an HTML page.
void CMyClass::ConnectEvents(IHTMLElement* pElem)
{
    HRESULT hr;
    IConnectionPointContainer* pCPC = NULL;
    IConnectionPoint* pCP = NULL;
    DWORD dwCookie;

    // Check that this is a connectable object.
    hr = pElem->QueryInterface(IID_IConnectionPointContainer, (void**)&pCPC);

    if (SUCCEEDED(hr))
    {
        // Find the connection point.
        hr = pCPC->FindConnectionPoint(DIID_HTMLElementEvents2, &pCP);

        if (SUCCEEDED(hr))
        {
            // Advise the connection point.
            // pUnk is the IUnknown interface pointer for your event sink
            hr = pCP->Advise(pUnk, &dwCookie);

            if (SUCCEEDED(hr))
            {
                // Successfully advised
            }

            pCP->Release();
        }

        pCPC->Release();
    }
}
The following sample code demonstrates how you would detect the firing of an HTMLElementEvents2::onclick event in your implementation of IDispatch::Invoke.

Hide Example

STDMETHODIMP CEventSink::Invoke(DISPID dispidMember,
                                REFIID riid,
                                LCID lcid,
                                WORD wFlags,
                                DISPPARAMS* pdispparams,
                                VARIANT* pvarResult,
                                EXCEPINFO* pexcepinfo,
                                UINT* puArgErr)
{
    switch (dispidMember)
    {
        case DISPID_HTMLELEMENTEVENTS2_ONCLICK:
        OnClick();
        break;

        default:
        break;
    }

    return S_OK;
}

Qmasterz,111222过来看看,BHO中判断网页下载完成的问题
T
我要处理网页中多Frame的情况。在ATL中:
STDMETHODIMP CSpyIE::Invoke(DISPID dispidMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pvarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
{
    case DISPID_NAVIGATECOMPLETE2:
   {
      ...
   } 
}
调试发现括号中的内容会执行多次。
参考了MSDN:
HOWTO: Determine When a Page Is Done Loading in WebBrowser Control (Q180366)
在ATL中该怎样判断??
A
Figure 9    Invoke


STDMETHODIMP CIEHlprObj::Invoke(DISPID dispidMember, REFIID riid,
                                LCID lcid, WORD wFlags,
                                DISPPARAMS* pDispParams,
                                VARIANT* pvarResult,
                                EXCEPINFO*  pExcepInfo, UINT* puArgErr)
{
   USES_CONVERSION;
   strstream strEventInfo;

   if (!pDispParams)
      return E_INVALIDARG;

   // Get the current URL
   // 
   LPOLESTR lpURL = NULL;
   m_spWebBrowser2->get_LocationURL(&lpURL);

   switch (dispidMember)
   {
      // The parameters for this DISPID are as follows:
      // [0]: Cancel flag  - VT_BYREF|VT_BOOL
      // [1]: HTTP headers - VT_BYREF|VT_VARIANT
      // [2]: Address of HTTP POST data  - VT_BYREF|VT_VARIANT
      // [3]: Target frame name - VT_BYREF|VT_VARIANT
      // [4]: Option flags - VT_BYREF|VT_VARIANT
      // [5]: URL to navigate to - VT_BYREF|VT_VARIANT
      // [6]: An object that evaluates to the top-level or frame
      //      WebBrowser object corresponding to the event.
      //
      case DISPID_BEFORENAVIGATE2:
         strEventInfo << "BeforeNavigate2: ";

         if (pDispParams->cArgs >= 5 &&
             pDispParams->rgvarg[5].vt == (VT_BYREF|VT_VARIANT))
         {
            CComVariant varURL(*pDispParams->rgvarg[5].pvarVal);
            varURL.ChangeType(VT_BSTR);

            strEventInfo << OLE2T(varURL.bstrVal);
         }
         else
            strEventInfo << "NULL";

         strEventInfo << ends;
         break;

      // The parameters for this DISPID:
      // [0]: URL navigated to - VT_BYREF|VT_VARIANT
      // [1]: An object that evaluates to the top-level or frame
      //      WebBrowser object corresponding to the event.
      //
      case DISPID_NAVIGATECOMPLETE2:
         if (pDispParams->rgvarg[0].vt == (VT_BYREF|VT_VARIANT))
         {
            CComVariant varURL(*pDispParams->rgvarg[0].pvarVal);
            varURL.ChangeType(VT_BSTR);
 
            strEventInfo << "NavigateComplete2: "
                         << OLE2T(varURL.bstrVal)
                         << ends;
         }
         break;

      // The parameters for this DISPID:
      // [0]: New status bar text - VT_BSTR
      //
      case DISPID_STATUSTEXTCHANGE:
         LPOLESTR lpStatusText;

         m_spWebBrowser2->get_StatusText(&lpStatusText);
         strEventInfo << "StatusTextChange: ";

         if (!strcmp(OLE2T(lpStatusText), ""))
            strEventInfo << "NULL";
         else
            strEventInfo << OLE2T(lpStatusText);

         strEventInfo << ends;
         break;

      // The parameters for this DISPID:
      // [0]: Maximum progress - VT_I4
      // [1]: Amount of total progress - VT_I4
      //
      case DISPID_PROGRESSCHANGE:
         strEventInfo << "ProgressChange: ";

         if (pDispParams->cArgs == 0)
            strEventInfo << "NULL";
         else
         {
            if (pDispParams->rgvarg[0].vt == VT_I4)
               strEventInfo << pDispParams->rgvarg[0].lVal;

            if (pDispParams->cArgs > 1 && pDispParams->rgvarg[1].vt == VT_I4)
               strEventInfo << ", " << pDispParams->rgvarg[1].lVal;
         }

         strEventInfo << ends;
         break;

      case DISPID_DOCUMENTCOMPLETE:
         strEventInfo << "DocumentComplete" << ends;
         break;

      case DISPID_DOWNLOADBEGIN:
         strEventInfo << "DownloadBegin" << ends;
         break;

      case DISPID_DOWNLOADCOMPLETE:
         strEventInfo << "DownloadComplete" << ends;
         break;

      // The parameters for this DISPID:
      // [0]: Enabled state - VT_BOOL
      // [1]: Command identifier - VT_I4

      //
      case DISPID_COMMANDSTATECHANGE:
         strEventInfo << "CommandStateChange: ";

         if (pDispParams->cArgs == 0)
            strEventInfo << "NULL";
         else
         {
            if (pDispParams->rgvarg[0].vt == VT_BOOL)
               strEventInfo << ((pDispParams->rgvarg[0].boolVal ==
                                 VARIANT_TRUE) ? "True" : "False");

            if (pDispParams->cArgs > 1 && pDispParams->rgvarg[1].vt == VT_I4)
               strEventInfo << ", " << pDispParams->rgvarg[1].lVal;
         }

         strEventInfo << ends;
         break;

      case DISPID_NEWWINDOW2:
         strEventInfo << "NewWindow2" << ends;
         break;

      // The parameters for this DISPID:
      // [0]: Document title - VT_BSTR
      //
      case DISPID_TITLECHANGE:
         strEventInfo << "TitleChange: ";

         if (pDispParams->cArgs > 0 && pDispParams->rgvarg[0].vt == VT_BSTR)
            strEventInfo << OLE2T(pDispParams->rgvarg[0].bstrVal);
         else
            strEventInfo << "NULL";

         strEventInfo << ends;
         break;

      // The parameters for this DISPID:
      // [0]: Name of property that changed - VT_BSTR
      //
      case DISPID_PROPERTYCHANGE:
         strEventInfo << "PropertyChange: ";

         if (pDispParams->cArgs > 0 && pDispParams->rgvarg[0].vt == VT_BSTR)
            strEventInfo << OLE2T(pDispParams->rgvarg[0].bstrVal);
         else
            strEventInfo << "NULL";

         strEventInfo << ends;
         break;

      // The parameters for this DISPID:
      // [0]: Address of cancel flag - VT_BYREF|VT_BOOL
      //
      case DISPID_QUIT:
         strEventInfo << "Quit" << ends;

         ManageConnection(Unadvise);
         m_dlgEvents.DestroyWindow();
         break;

      default:
         strEventInfo << "Unknown Event" << dispidMember << ends;
         break;
   }

   m_dlgEvents.AddEventToList(strEventInfo.str());

   return S_OK;
}


Q如何获得iframe的句柄?
T 
A
是接口吧
这个依赖于IE的版本的
http://www.csdn.net/Expert/TopicView.asp?id=704159
Q★☆怎样用vc编程来保存XML的网页?★☆
T 
A
BOOL DOMDocSaveLocation()
{
   BOOL bResult = FALSE;
   IXMLDOMDocument *pIXMLDOMDocument = NULL;
   HRESULT hr;

   try
   {
      _variant_t varString = _T("D://sample.xml");
      // Initialize pIXMLDOMDocument (create a DOMDocument).
      // Load document.
      hr = pIXMLDOMDocument->save(varString);
      if(SUCCEEDED(hr))
         bResult = TRUE;
   }
   catch(...)
   {
      DisplayErrorToUser();
   // Release the IXMLDOMDocument interface.
   }
   // Release the IXMLDOMDocument interface when finished with it.
   return bResult;
}

http://www.csdn.net/expert/topic/783/783799.xml
 想IE窗口发消息的问题(在线等)
 
我想向一个IE窗口发送一个字符串。

用spy++观察,窗口结构如下:
CabinetWClass
  Shell DocObject View
    Internet Explorer_Server
      Shell Embedding
      Shell Embedding
      Shell Embedding
      Shell Embedding
      Shell DocObject View
        Internet Explorer_Server

在最后的窗口上有一个编辑框,但是看不到这个edit。

用FindWindow(),FindWindowEx(),GetNextWindow(),最后可以得到有edit的窗口的hwnd。

往这个hwnd发送WM_KEYDOWN时,edit中有字符出现。
可是我不能一个一个字符的发啊,我想一次发送一个字符串,不知道该怎样去做?
 HRESULT IHTMLInputButtonElement::put_value(BSTR v);

HOWTO: Get IHTMLDocument2 from a HWND
Q249232
然后枚举文档元素,获得IHTMLInputButtonElement接口。


http://www.csdn.net/expert/topic/351/351580.xml
http://www.csdn.net/Expert/topicview.asp?id=653919
T怎样在程序中往历史记录里添加新的记录
Q我想在程序中往历史记录中添加新的记录,然后在IE的历史中能看到象:星期一,下面是网站,再往下是网页…
A开一个隐藏的IE,然后浏览……

VARIANT vDummy = {0};
// Instantiate a browser
   if (FAILED(hr = CoCreateInstance(CLSID_InternetExplorer,
      NULL, CLSCTX_SERVER, IID_IWebBrowser2,
                    (LPVOID*)&pWebBrowser)))
   {
      goto Error;
   }

   // Show the browser, and navigate to the special location
   // represented by the pidl
   hr = pWebBrowser->put_Visible(VARIANT_FALSE);
   hr = pWebBrowser->Navigate2(&vPIDL, &vDummy, &vDummy,
           &vDummy, &vDummy);



  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
译者序 作者简介 前言 第1章 XML简介 1 1.1 标记语言 1 1.2 XML的起源和目的 2 1.3 Web体系结构:过去与未来 4 1.3.1 传统Web体系结构 4 1.3.2 XML下的Web体系结构 5 1.4 XML基本特征 6 1.5 词汇表 8 1.5.1 科学词汇表 8 1.5.2 商业词汇表 9 1.5.3 法律词汇表 10 1.5.4 医学词汇表 11 1.5.5 计算机词汇表 11 1.6 XML技术的主要特性 12 1.6.1 格式正规的XML 12 1.6.2 文档类型定义 13 1.6.3 数据建模 14 1.6.4 文档对象模型 14 1.6.5 XML 简单API 14 1.6.6 命名空间和模式 14 1.6.7 链接和查询 15 1.6.8 转换XML 15 1.6.9 XML和数据库 16 1.6.10 服务器到服务器 16 1.6.11 电子商务与XML 17 1.6.12 使用样式 18 1.6.13 无线应用协议和WML 18 1.7 XML的应用程序举例 19 1.8 小结 19 第2章 XML语法 20 2.1 标记语法 20 2.1.1 字符 20 2.1.2 命名 21 2.2 文档部分 22 2.3 元素 23 2.3.1 起始标记 24 2.3.2 结束标记 24 2.3.3 空元素标记 24 2.3.4 标记:一个简单的例子 25 2.3.5 文档元素 25 2.3.6 子元素 26 2.3.7 元素嵌套 27 2.3.8 字符串 29 2.4 字符数据 29 2.5 属性 30 2.5.1 特殊属性 31 2.5.2 空白 33 2.5.3 行尾的处理 34 2.6 字符引用和实体引用 34 2.6.1 字符引用 34 2.6.2 实体引用 34 2.7 处理指令 35 2.8 注释 36 2.9 CDATA部分 37 2.10 文档结构 38 2.10.1 序言 38 2.10.2 尾声 43 2.11 XML语法小结 43 2.12 格式正规的文档 44 2.13 解析器 45 2.13.1 事件驱动的解析器 45 2.13.2 基于树的解析器 46 2.13.3 解析器基准测试 46 2.14 书籍目录应用程序 47 2.15 小结 49 第3章 文档类型定义 51 3.1 为何需要正式的结构 51 3.1.1 文档域 52 3.1.2 验证文档的有效性 52 3.2 编写DTD:通用原则 52 3.2.1 将DTD与XML文档相关联 53 3.2.2 基本标记声明 55 3.3 正式的DTD结构 55 3.3.1 实体 56 3.3.2 元素 58 3.3.3 属性 61 3.3.4 条件部分 67 3.4 DTD的缺点 69 3.5 用于图书目录问题的DTD 70 3.5.1 图书目录问题的正式定义 70 3.5.2 对象关系问题 77 3.5.3 进一步讨论 78 3.6 小结 79 第4章 数据建模与XML 80 4.1 信息建模 80 4.1.1 静态模型和动态模型 81 4.1.2 文档和数据 82 4.1.3 从何处开始 82 4.1.4 静态信息模型 83 4.1.5 动态建模:对数据进行哪些处理 87 4.2 设计XML文档 90 4.2.1 XML的两种角色 90 4.2.2 将信息模型映射到XML 93 4.3 模式语言和表示法 101 4.3.1 模式的作用 101 4.3.2 将DTD作为模式 103 4.3.3 XML模式建议 109 4.4 小结 110 第5章 文档对象模型 111 5.1 什么是文档对象模型 111 5.1.1 XML文档结构 111 5.1.2 为何使用DOM 113 5.1.3 DOM规范 115 5.1.4 现实世界中的DOM 116 5.1.5 特殊的XML DOM实例— HTML DOM 117 5.2 使用DOM 120 5.2.1 DOM API 120 5.2.2 客户端和服务器端 121 5.2.3 DOM在出版过程中的应用 122 5.3 使用DOM和XML的应用实例 125 5.3.1 简单的客户端实例 125 5.3.2 更复杂的编程实例 133 5.4 DOM和XML的未来 143 5.4.1 W3C的工作 143 5.4.2 应用 144 5.4.3 数据库、模式和DOM 144 5.5 小结 144 第6章 SAX 1.0: XML简易API 145 6.1 事件驱动接口 145 6.2 SAX的由来 148 6.3 SAX的高级特性 165 6.3.1 可选择的源输入 166 6.3.2 处理外部实体 168 6.3.3 选择解析器 169 6.4 一些SAX设计模式 171 6.5 SAX 2.0 187 6.5.1 可配置的接口 187 6.5.2 核心的特性和属性 188 6.6 小结 189 第7章 命名空间和模式 191 7.1 混合词汇表 192 7.1.1 分解问题 193 7.1.2 重用 193 7.1.3 多义性名称冲突 193 7.2 命名空间 195 7.3 定义和声明命名空间 196 7.3.1 声明一个命名空间 196 7.3.2 限定名 196 7.3.3 范围 197 7.4 在格式正规的书籍里使用命名空间 实例 199 7.5 模式 201 7.5.1 与DTD有关的问题 201 7.5.2 一个对创建模式的帮助 203 7.6 W3C在XML 模式方面的工作 209 7.6.1 DTD与XML 模式的比较 210 7.6.2 结构 211 7.6.3 数据类型 219 7.7 简化了的XML Data 222 7.7.1 MSXML对命名空间和模式的支持 228 7.7.2 数据类型 229 7.8 图书目录中的变化 230 7.8.1 为什么烦恼 230 7.8.2 重铸DTD 231 7.8.3 模式协调 236 7.9 小结 240 第8章 链接和查询 241 8.1 XML 信息集合 241 8.1.1 信息类型 241 8.1.2 信息集合的重要性 248 8.1.3 小结 250 8.2 链接 250 8.2.1 什么是链接 250 8.2.2 W3C规范:XLink 252 8.3 Xpointer 266 8.3.1 HTML指针 266 8.3.2 Xpointer 规范 267 8.4 W3C Xpath推荐标准 269 8.4.1 Location Step 269 8.4.2 XPointer对XPath的扩展 276 8.4.3 Xpointer错误 277 8.4.4 小结 277 8.5 XML程序段交换 278 8.5.1 什么是文档程序段 278 8.5.2 文档程序段的一些用途 279 8.5.3 问题:Bare文档程序段并不总 是充分的 281 8.5.4 解决办法:环境信息 283 8.5.5 回顾实例 285 8.5.6 如何传输程序段 287 8.5.7 小结 289 8.6 查询 289 8.6.1 什么是查询语言 289 8.6.2 关系型数据库和XML文档之间 的区别 291 8.6.3 XML查询语言的发展历史 295 8.6.4 使用Xpath和XSLT查询XML文档 298 8.6.5 查询语言展望 309 8.7 小结 309 第9章 转换 XML 310 9.1 为什么转换 XML 311 9.1.1 在不同词汇表之间转换 311 9.1.2 动态转换 312 9.1.3 不同的浏览器 312 9.2 XSL 313 9.3 XSLT 样式表命令 325 9.3.1 创建模板 325 9.3.2 处理空白 326 9.3.3 输出格式 326 9.3.4 合并样式表 327 9.3.5 嵌入样式表 328 9.4 使用XSLT的例子 328 9.4.1 命令的转换 329 9.4.2 循环 335 9.4.3 排序 336 9.4.4 条件处理 338 9.4.5 名称模板 341 9.4.6 编号方式 342 9.4.7 拷贝 344 9.5 使用DOM进行XML文档的转换 345 9.5.1 用DOM进行命令的转换 346 9.5.2 在运行时修改一个XSLT文档 349 9.6 XSL转换与DOM转换的比较 353 9.7 小结 354 第10章 XML和数据库 355 10.1 存储XML 355 10.1.1 持续性问题 355 10.1.2 文档管理 360 10.1.3 XML存储和数据库 362 10.1.4 结论 376 10.2 XML的交换 377 10.2.1 数据标准 377 10.2.2 查询标准 380 10.2.3 结论 388 10.2.4 你可能需要的标准 388 10.3 图书目录的例子 389 10.3.1 处理存在的数据和应用 389 10.3.2 图书目录模式 395 10.4 结论 420 第11章 服务器到服务器 421 11.1 XML的传送 421 11.1.1 基于FTP的XML传送 422 11.1.2 XML和消息队列 422 11.1.3 基于HTTP的XML 423 11.1.4 基于SMTP的XML 423 11.2 作为一种分布式组件模式的XML 424 11.2.1 消息传送和串行化 424 11.2.2 紧耦合系统和松耦合系统 428 11.2.3 通信方式 430 11.3 XML-RPC 431 11.3.1 为什么使用XML-RPC 432 11.3.2 XML-RPC适用于何处 433 11.3.3 XML-RPC规范—技术全瞻 434 11.3.4 XML-RPC的实现 440 11.3.5 书籍应用例子 444 11.3.6 到哪里去 464 11.4 SOAP 465 11.4.1 XML-RPC++ 465 11.4.2 实现 478 11.4.3 结论 493 11.5 WebDAV 493 11.6 小结 494 第12章 电子商务和XML 495 12.1 什么是电子商务 496 12.1.1 对客户直接销售 496 12.1.2 企业对企业交易 497 12.1.3 信息共享和内容联合 497 12.1.4 EDI—电子数据交换 498 12.2 在电子商务中应用XML 503 12.2.1 通常的错误概念 509 12.2.2 在电子商务中使用XML的感受 512 12.3 展望未来 513 12.3.1 发现和调解 514 12.3.2 容器 517 12.3.3 代理 519 12.3.4 模板 520 12.4 理论转化为实现 521 12.5 电子商务解决方案 521 12.6 行业方案 521 12.6.1 纵向行业解决方案的关键 522 12.6.2 旅游 523 12.7 人力资源 524 12.7.1 HR-XML 524 12.7.2 健康 532 12.8 cXML—纵向行业的一个详细 例子 535 12.8.1 为什么有cXML 535 12.8.2 cXML协议规范 536 12.8.3 消息传输 540 12.9 第1步—横向行业 546 12.9.1 ASC X12 546 12.9.2 XML-EDIFACT 547 12.9.3 电子商务XML工作组 549 12.10 第一个横向步骤 549 12.10.1 BizTalk标记规范 550 12.10.2 规范的目标和当前的限制 550 12.10.3 文档结构 551 12.10.4 一个用于Wrox书店的BizTalk 文档 557 12.10.5 BizTalk Jumpstart工具包简介 561 12.10.6 BizTalk服务器 562 12.11 小结 565 第13章 样式XML 567 13.1 解释的位置 567 13.2 客户端的XML转换 568 13.3 解释模型 568 13.3.1 视觉解释 569 13.3.2 语音解释 570 13.3.3 如何将样式表链接到XML文档上 571 13.3.4 规则语言 571 13.3.5 CSS 572 13.3.6 XSL 592 13.3.7 用XSL解释XML 594 13.3.8 DSSSL 611 13.3.9 Omnimark 614 13.4 小结 616 第14章 无线应用协议 617 14.1 新客户介绍 617 14.2 了解无线环境 621 14.2.1 服务 621 14.2.2 无线网络 622 14.2.3 WAP如何解决无线网络应用遇到 的问题 624 14.3 介绍WML 626 14.3.1 怎样将第一份文档传送到电话上 626 14.3.2 WML文档的结构 627 14.3.3 通用属性 629 14.3.4 WML包括什么 630 14.3.5 Meta信息 630 14.3.6 基本字符、表格和演示 631 14.3.7 使用计时器 633 14.3.8 事件处理器 634 14.3.9 使用变量 635 14.3.10 任务和菜单 637 14.3.11 客户端模板 641 14.3.12 表单数据 643 14.3.13 图像 646 14.4 在服务器上生成WML 646 14.5 WROX的WML应用 648 14.6 WML脚本 651 14.6.1 基本概念 652 14.6.2 字节码 652 14.6.3 如何从WML上调用脚本函数 652 14.7 脚本库 653 14.7.1 决定浏览器的状态—WMLBrowser 脚本库 653 14.7.2 Dialogs库 654 14.7.3 特定的语言函数 655 14.7.4 浮点数 655 14.7.5 字符串 656 14.7.6 URL 657 14.8 如何得到更多的信息 660 14.9 小结 660 第15章 实例研究1─数据双重性 662 15.1 商业需求 662 15.2 系统要求 662 15.3 设计时间:让我们开始吧 662 15.4 实现方法概述 663 15.5 建立数据库 665 15.6 提供XML功能的ASP 665 15.7 客户端页面 668 15.8 “以编号浏览”XSL样式表 676 15.9 “以名字浏览”XSL样式表 678 15.10 激活XSL样式表 679 15.11 问题:保持树的同步 680 15.12 小结 683 第16章 实例研究2—XML和分布式 应用程序 684 16.1 目前的弱点 684 16.2 构建网络应用程序的五条原则 685 16.2.1 从粗粒度服务构建应用程序 686 16.2.2 通过查询目录发现服务 687 16.2.3 将服务提供为自描述数据 688 16.2.4 服务是短暂的 689 16.2.5 服务必须可扩展,且能够降低对 外部的要求 690 16.3 商业实例 691 16.4 应用程序设计 692 16.4.1 应用程序的组织 694 16.4.2 程序员服务客户 694 16.4.3 服务 695 16.4.4 交换词汇表 696 16.5 实现 697 16.5.1 定位服务 698 16.5.2 管理数据绑定 699 16.6 输入和编辑程序员信息 700 16.6.1 客户端 700 16.6.2 服务器端 701 16.6.3 用于插入程序员信息的完整客户 端代码 704 16.6.4 用于插入程序员信息的完整服务器 端代码 705 16.7 搜索程序员信息 707 16.7.1 客户端 707 16.7.2 服务器端 709 16.8 清除程序员表单 710 16.9 输入程序员成果报告 711 16.9.1 客户端 711 16.9.2 服务器端 712 16.10 清除成果报告历史表单 714 16.11 获取程序员的成果历史 714 16.11.1 客户端 714 16.11.2 服务器端 716 16.12 经验教训 718 16.12.1 违反的开发原则 718 16.12.2 组件 718 16.12.3 重用的可能性 718 16.13 小结 719 第17章 实例研究3—图书目录信息 服务 720 17.1 图书目录信息服务 721 17.1.1 系统概述 721 17.1.2 创建BCIS 732 17.2 小结 764 第18章 实例研究4—SOAP 765 18.1 追根溯源 765 18.2 SOAP Opera 770 18.2.1 OPERA客户端 771 18.2.2 OPERA服务器 780 18.2.3 订单输入应用程序 793 18.2.4 对象 796 18.3 小结 809 附录A XML 1.0规范 810 附录B IE 5 XML文档对象模型 847 附录C SAX 1.0:XML简单API 887 附录D IE 5 XML模式和数据类型 906 附录E IE 5 XSL引用 915 附录F CSS属性 927 附录G 安装XT 939 附录H 支持与勘误 940
网络编程,当然要用到Windows Socket(套接字)技术。Socket相关的操作由一系列API函数来完成,比如socket、bind、listen、connect、accept、send、sendto、recv、recvfrom等。调用这些API函数有一定的先后次序,有些函数的参数还比较复杂,对于开发者来说,不是很好用。于是,微软的MFC提供了两个类:CAsyncSocket和CSocket,极大地方便了Socket功能的使用。   CAsyncSocket类在较低层次上封装了Windows Socket API,并且通过内建一个(隐藏的)窗口,实现了适合Windows应用的异步机制(Windows Socket API默认情况下工作在阻塞模式,不方便直接在消息驱动的Windows程序上使用)。CSocket类从CAsyncSocket类派生,进一步简化了Socket功能的应用。不过很遗憾,正因为这两个类都内建了一个窗口,它们并不是线程安全的(thread-safe);如果要在多线程环境下应用Socket功能,建议自行封装Socket API函数。 基于TCP的socket编程的服务器端程序流程如下: 1、创建套接字 2、将套接字绑定到一个本地地址和端口号上(bind) 3、将套接字设为监听模式,准备接受客户请求(listen) 4、等待客户请求,请求到来时接受请求,建立链接,并返回 一个新的基于此次通信的套接字(accept) 5、用返回的套接字和客户端进行通信(send、recv) 6、返回,等待另一客户请求 7、关闭套接字 基于TCP的socket编程的客户端程序流程如下: 1、创建套接字 2、向服务器端发送请求(connect) 3、和服务器端进行通信(send、recv) 4、关闭套接字 基于UDP的socket编程的服务器端程序流程如下: 1、创建套接字 2、将套接字绑定到本地地址和端口号上(bind) 3、等待接收数据(recvfrom) 4、关闭套接字 基于UDP的socket编程的客户端程序流程如下: 1、创建套接字 2、和服务器端进行通信(sendto) 3、关闭套接字 异步方式指的是发送方不等接收方响应,便接着发下个数据包的通信方式;而同步指发送方发出数据后,等收到接收方发回的响应,才发下一个数据包的通信方式。   阻塞套接字是指执行此套接字的网络调用时,直到成功才返回,否则一直阻塞在此网络调用上,比如调用recv()函数读取网络缓冲区中的数据,如果没有数据到达,将一直挂在recv()这个函数调用上,直到读到一些数据,此函数调用才返回;而非阻塞套接字是指执行此套接字的网络调用时,不管是否执行成功,都立即返回。比如调用recv()函数读取网络缓冲区中数据,不管是否读到数据都立即返回,而不会一直挂在此函数调用上。在实际Windows网络通信软件开发中,异步非阻塞套接字是用的最多的。平常所说的C/S(客户端/服务器)结构的软件就是异步非阻塞模式的。   对于这些概念,初学者的理解也许只能似是而非,我将用一个最简单的例子说明异步非阻塞Socket的基本原理和工作机制。目的是让初学者不仅对Socket异步非阻塞的概念有个非常透彻的理解,而且也给他们提供一个用Socket开发网络通信应用程序的快速入门方法。操作系统是Windows 98(或NT4.0),开发工具是Visual C++6.0。   MFC提供了一个异步类CAsyncSocket,它封装了异步、非阻塞Socket的基本功能,用它做常用的网络通信软件很方便。但它屏蔽了Socket的异步、非阻塞等概念,开发人员无需了解异步、非阻塞Socket的原理和工作机制。因此,建议初学者学习编网络通信程序时,暂且不要用MFC提供的类,而先用Winsock2 API,这样有助于对异步、非阻塞Socket编程机制的理解。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值