关于VC6使用最新的MSDN(续)

    两个星期近乎狂热地查资料、调试,接着又是近两个星期的编写毕业论文,到现在已将近一个月时间了,

对我做的经历给个总结:
    三天时间浏览了一些网上的com入门级教程、看了com技术内幕,然后开始写第一个com,从创建动态链接库

,到实现自己的IFactory,到编写组建的DllGetClassObject、DllCanUnloadNow、DllRegisterServer、

DllUnregisterServer,到组建加载成功用了将近一个星期,然后开始加原作者的核心代码到组建中,编译调

试......。然而,遗憾的是我发现我走到了尽头,按我对作者原文的理解,我的程序怎么也达不到作者提到的

结果,一按f1我的vc就报错。郁闷。。。。
    最后找到了原作者的源码,发现我的代码比较幼稚可笑。
    首先将KeywordSearch重定向到MyKeywordSearch的那段代码虽然写的正确,但是放错了地方,我将他放在

了DLLMain中(这就是我一直纳闷"Tools"->"Customize"->"Add-ins and Macro Files"->"加载我的dll时为什么

我的代码被反复执行的原因),原码中这段实现在CDSAddIn::OnConnection中实现,这样保证了这段代码只在第

一次加载插件时执行。
    其次对MyKeywordSearch的实现想得过于简单,我的实现方式如下:
HRESULT __stdcall MyKeywordSearch(LPWSTR pszKeyword,  long dwFlags, long dwReserved ){
 
 Help* pHelp;
 
 HRESULT _hr = theHelp.QueryInterface(__uuidof(VsHelp::Help), (void**)&pHelp);
     if (FAILED(_hr)) AfxMessageBox("failed,return");
 
  _hr = pHelp->DisplayTopicFromF1Keyword(pszKeyword);

 if (FAILED(_hr)) AfxMessageBox("failed2,return");
   
    return _hr;

}

其中theHelp的定义为:HelpPtr theHelp;

而源码的实现为:
HRESULT __stdcall MyKeywordSearch(IUnknown * This, LPWSTR pszKeyword, long dwFlags, long

dwReserved)
{
 ASSERT(theHelp != NULL);

 LONG lResult;
 HKEY hKey;
 lResult = RegOpenKeyEx(HKEY_CURRENT_USER,
  "Software//Microsoft//Dependency Walker//External Help",
  0, KEY_READ, &hKey);
 if (lResult == ERROR_SUCCESS)
 {
  CHAR szCollection[MAX_PATH];
  DWORD cbCollection = MAX_PATH;
  lResult = RegQueryValueEx(hKey, "Collection", NULL, NULL, (LPBYTE)szCollection,

&cbCollection);
  if (lResult == ERROR_SUCCESS)
  {
   TRACE1("use collection: %s/n", szCollection);

   if (stricmp(szCollection, "Online") == 0)
   {
    WCHAR szURL[1024];
    DWORD dwURL = sizeof(szURL);
    lResult = RegQueryValueExW(hKey, L"URL", NULL, NULL, (LPBYTE)

szURL, &dwURL);
    if (lResult == ERROR_SUCCESS)
    {
     WCHAR *p = wcsstr(szURL, L"%1");
     if (p)
     {
      p[1] = L's';
      WCHAR szLink[1024];
      if (_snwprintf(szLink, sizeof(szLink)/sizeof

(WCHAR), szURL, pszKeyword) > 0)
      {
       TRACE1("use collection: %S/n", szLink);
       
       ShellExecuteW(NULL, L"open", szLink,

NULL, NULL, SW_SHOWNORMAL);

       RegCloseKey(hKey);
       return S_OK;
      }
     }
    }
   } /* end Online */
   else
   {
    HKEY hHelp;
    lResult = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
     "SOFTWARE//Microsoft//MSDN//7.0//Help//0x0409",
     0, KEY_READ|KEY_ENUMERATE_SUB_KEYS, &hHelp);
    if (lResult == ERROR_SUCCESS)
    {
     DWORD dwIndex = 0;
     CHAR szGuid[MAX_PATH];
     while (RegEnumKey(hHelp, dwIndex++, szGuid, MAX_PATH) ==

ERROR_SUCCESS)
     {
      HKEY hGuid;
      if (RegOpenKeyEx(hHelp, szGuid, 0, KEY_READ,

&hGuid) != ERROR_SUCCESS)
       continue;
      
      CHAR szCollection2[MAX_PATH];
      DWORD cbCollection2 = MAX_PATH;
      lResult = RegQueryValueEx(hGuid, NULL, NULL,

NULL, (LPBYTE)szCollection2, &cbCollection2);
      if (lResult == ERROR_SUCCESS && stricmp

(szCollection, szCollection2) == 0)
      {
       cbCollection2 = MAX_PATH;
       lResult = RegQueryValueEx(hGuid,

"Filename", NULL, NULL, (LPBYTE)szCollection2, &cbCollection2);
       if (lResult == ERROR_SUCCESS &&
        strnicmp(szCollection2, "ms-

help://", sizeof("ms-help://")-1) == 0)
       {
        TRACE1("use collection: %s/n",

szCollection2);
        theHelp->SetCollection

(szCollection2, "");
        
        RegCloseKey(hGuid);
        break;
       }
      }
      
      RegCloseKey(hGuid);
     } /* end RegEnumKey(hHelp) */
     
     RegCloseKey(hHelp);
    }
   } /* end not Online */   
  }

  RegCloseKey(hKey);
 }

 theHelp->SyncIndex(pszKeyword, 1);
 theHelp->DisplayTopicFromF1Keyword(pszKeyword);

 return S_OK;
}


看过源码有茅塞顿开之感觉,真是学到了不少东西! 

先将源码中的两个主要文件内容贴出来

 

//  AddInMod.cpp : implementation file
//

#include 
" stdafx.h "
#include 
" VSNetHelp.h "
#include 
" DSAddIn.h "
#include 
" Commands.h "

#ifdef _DEBUG
#define  new DEBUG_NEW
#undef  THIS_FILE
static   char  THIS_FILE[]  =  __FILE__;
#endif

#import 
" C:Program FilesCommon FilesMicrosoft SharedMSEnvvshelp.tlb "

// #import "C:Program FilesCommon FilesMicrosoft SharedVS98vshelp.dll"
#include  " vc6help.tlh "

struct  _IVsHelpSystemVtbl
{
    HRESULT (STDMETHODCALLTYPE 
* QueryInterface)(IUnknown  *  This, REFIID riid,  void   ** ppvObject);
    ULONG (STDMETHODCALLTYPE 
* AddRef)(IUnknown  *  This);
    ULONG (STDMETHODCALLTYPE 
* Release)(IUnknown  *  This);
    HRESULT (STDMETHODCALLTYPE 
* KeywordSearch)(IUnknown  *  This, LPWSTR pszKeyword,  long  dwFlags,  long  dwReserved);
}
;

struct  _IVsHelpSystem
{
    
struct  _IVsHelpSystemVtbl  * lpVtbl;
}
;

VsHelp::HelpPtr theHelp;
VsHelpServices::IVsHelpSystemPtr vc6Help;
_IVsHelpSystem 
* iHelp  =  NULL;

HRESULT (STDMETHODCALLTYPE 
* OldKeywordSearch)(IUnknown  *  This, LPWSTR pszKeyword,  long  dwFlags,  long  dwReserved)  =  NULL;

HRESULT __stdcall MyKeywordSearch(IUnknown 
*  This, LPWSTR pszKeyword,  long  dwFlags,  long  dwReserved)
{
    ASSERT(theHelp 
!=  NULL);

    LONG lResult;
    HKEY hKey;
    lResult 
=  RegOpenKeyEx(HKEY_CURRENT_USER,
        
" Software/Microsoft/Dependency Walker/External Help " ,
        
0 , KEY_READ,  & hKey);
    
if  (lResult  ==  ERROR_SUCCESS)
    
{
        CHAR szCollection[MAX_PATH];
        DWORD cbCollection 
=  MAX_PATH;
        lResult 
=  RegQueryValueEx(hKey,  " Collection " , NULL, NULL, (LPBYTE)szCollection,  & cbCollection);
        
if  (lResult  ==  ERROR_SUCCESS)
        
{
            TRACE1(
" use collection: %s " , szCollection);

            
if  (stricmp(szCollection,  " Online " ==   0 )
            
{
                WCHAR szURL[
1024 ];
                DWORD dwURL 
=   sizeof (szURL);
                lResult 
=  RegQueryValueExW(hKey, L " URL " , NULL, NULL, (LPBYTE)szURL,  & dwURL);
                
if  (lResult  ==  ERROR_SUCCESS)
                
{
                    WCHAR 
* =  wcsstr(szURL, L " %1 " );
                    
if  (p)
                    
{
                        p[
1 =  L ' s ' ;
                        WCHAR szLink[
1024 ];
                        
if  (_snwprintf(szLink,  sizeof (szLink) / sizeof (WCHAR), szURL, pszKeyword)  >   0 )
                        
{
                            TRACE1(
" use collection: %S " , szLink);
                            
                            ShellExecuteW(NULL, L
" open " , szLink, NULL, NULL, SW_SHOWNORMAL);

                            RegCloseKey(hKey);
                            
return  S_OK;
                        }

                    }

                }

            }
  /*  end Online  */
            
else
            
{
                HKEY hHelp;
                lResult 
=  RegOpenKeyEx(HKEY_LOCAL_MACHINE,
                    
" SOFTWARE/Microsoft/MSDN/7.0/Help/0x0409 " ,
                    
0 , KEY_READ | KEY_ENUMERATE_SUB_KEYS,  & hHelp);
                
if  (lResult  ==  ERROR_SUCCESS)
                
{
                    DWORD dwIndex 
=   0 ;
                    CHAR szGuid[MAX_PATH];
                    
while  (RegEnumKey(hHelp, dwIndex ++ , szGuid, MAX_PATH)  ==  ERROR_SUCCESS)
                    
{
                        HKEY hGuid;
                        
if  (RegOpenKeyEx(hHelp, szGuid,  0 , KEY_READ,  & hGuid)  !=  ERROR_SUCCESS)
                            
continue ;
                        
                        CHAR szCollection2[MAX_PATH];
                        DWORD cbCollection2 
=  MAX_PATH;
                        lResult 
=  RegQueryValueEx(hGuid, NULL, NULL, NULL, (LPBYTE)szCollection2,  & cbCollection2);
                        
if  (lResult  ==  ERROR_SUCCESS  &&  stricmp(szCollection, szCollection2)  ==   0 )
                        
{
                            cbCollection2 
=  MAX_PATH;
                            lResult 
=  RegQueryValueEx(hGuid,  " Filename " , NULL, NULL, (LPBYTE)szCollection2,  & cbCollection2);
                            
if  (lResult  ==  ERROR_SUCCESS  &&
                                strnicmp(szCollection2, 
" ms-help:// " sizeof ( " ms-help:// " ) - 1 ==   0 )
                            
{
                                TRACE1(
" use collection: %s " , szCollection2);
                                theHelp
-> SetCollection(szCollection2,  "" );
                                
                                RegCloseKey(hGuid);
                                
break ;
                            }

                        }

                        
                        RegCloseKey(hGuid);
                    }
  /*  end RegEnumKey(hHelp)  */
                    
                    RegCloseKey(hHelp);
                }

            }
  /*  end not Online  */             
        }


        RegCloseKey(hKey);
    }


    theHelp
-> SyncIndex(pszKeyword,  1 );
    theHelp
-> DisplayTopicFromF1Keyword(pszKeyword);

    
return  S_OK;
}


//  This is called when the user first loads the add-in, and on start-up
//   of each subsequent Developer Studio session
STDMETHODIMP CDSAddIn::OnConnection(IApplication *  pApp, VARIANT_BOOL bFirstTime,
        
long  dwCookie, VARIANT_BOOL *  OnConnection)
{
    AFX_MANAGE_STATE(AfxGetStaticModuleState());

    
//  Store info passed to us
    IApplication *  pApplication  =  NULL;
    
if  (FAILED(pApp -> QueryInterface(IID_IApplication, ( void ** & pApplication))
        
||  pApplication  ==  NULL)
    
{
        
* OnConnection  =  VARIANT_FALSE;
        
return  S_OK;
    }


    
{
        HRESULT hr 
=  theHelp.CreateInstance(__uuidof(VsHelp::DExploreAppObj));
        
if  (SUCCEEDED(hr))
        
{
            HRESULT hr 
=  vc6Help.CreateInstance(__uuidof(VsHelpServices::VsHelpServices));
            
if  (SUCCEEDED(hr))
            
{
                iHelp 
=  (_IVsHelpSystem  * )vc6Help.GetInterfacePtr();
                
                TRACE1(
" iHelp = %x " , iHelp);
                TRACE1(
" lpVtbl = %x " , iHelp -> lpVtbl);
                TRACE1(
" KeywordSearch = %x " , iHelp -> lpVtbl -> KeywordSearch);
                
                OldKeywordSearch 
=  iHelp -> lpVtbl -> KeywordSearch;
                
                DWORD dwOldProtect;
                
if  (VirtualProtect(iHelp -> lpVtbl,  sizeof (_IVsHelpSystemVtbl), PAGE_READWRITE,  & dwOldProtect))
                    iHelp
-> lpVtbl -> KeywordSearch  =  MyKeywordSearch;
            }

        }

    }


    m_dwCookie 
=  dwCookie;

    
//  Create command dispatch, send info back to DevStudio
    CCommandsObj::CreateInstance( & m_pCommands);
    m_pCommands
-> AddRef();

    
//  The QueryInterface above AddRef'd the Application object.  It will
    
//   be Release'd in CCommand's destructor.
    m_pCommands -> SetApplicationObject(pApplication);

    
//  (see stdafx.h for the definition of VERIFY_OK)

    VERIFY_OK(pApplication
-> SetAddInInfo(( long ) AfxGetInstanceHandle(),
        (LPDISPATCH) m_pCommands, 
- 1 - 1 , m_dwCookie));

    
//  Inform DevStudio of the commands we implement

    
//  TODO: Replace the AddCommand call below with a series of calls,
    
//   one for each command your add-in will add.

    
//  The command name should not be localized to other languages.  The 
    
//   tooltip, command description, and other strings related to this
    
//   command are stored in the string table (IDS_CMD_STRING) and should
    
//   be localized.
    LPCTSTR szCommand  =  _T( " VSNetHelpCommand " );
    VARIANT_BOOL bRet;
    CString strCmdString;
    strCmdString.LoadString(IDS_CMD_STRING);
    strCmdString 
=  szCommand  +  strCmdString;
    CComBSTR bszCmdString(strCmdString);
    CComBSTR bszMethod(_T(
" VSNetHelpCommandMethod " ));
    VERIFY_OK(pApplication
-> AddCommand(bszCmdString, bszMethod,  - 1 , m_dwCookie,  & bRet));
    
if  (bRet  ==  VARIANT_FALSE)
    
{
        
//  AddCommand failed because a command with this name already
        
//   exists.  You may try adding your command under a different name.
        
//   Or, you can fail to load as we will do here.
         * OnConnection  =  VARIANT_FALSE;
        
return  S_OK;
    }


    
* OnConnection  =  VARIANT_TRUE;
    
return  S_OK;
}


//  This is called on shut-down, and also when the user unloads the add-in
STDMETHODIMP CDSAddIn::OnDisconnection(VARIANT_BOOL bLastTime)
{
    AFX_MANAGE_STATE(AfxGetStaticModuleState());

    m_pCommands
-> Release();
    m_pCommands 
=  NULL;

    
//  TODO: Perform any cleanup work here
     if  (iHelp  &&  iHelp -> lpVtbl -> KeywordSearch  ==  MyKeywordSearch)
    
{
        iHelp
-> lpVtbl -> KeywordSearch  =  OldKeywordSearch;
        iHelp 
=  NULL;
    }


    
if  (theHelp)
        theHelp.Release();

    
if  (vc6Help)
        vc6Help.Release();

    
return  S_OK;
}

有兴趣的话可以mail我索取原作者的源码:maomaovv@gmail.com

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值