Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1676039
  • 博文数量: 585
  • 博客积分: 14610
  • 博客等级: 上将
  • 技术积分: 7402
  • 用 户 组: 普通用户
  • 注册时间: 2008-05-15 10:52
文章存档

2013年(5)

2012年(214)

2011年(56)

2010年(66)

2009年(44)

2008年(200)

分类: C/C++

2012-01-27 03:25:53

实用!超强VC/MFC 常见问答收集(上)
分类: 2.3 VC技巧收集 284人阅读 评论(0) 收藏 举报


  自编浏览器进入一个网页后,点一个链接后系统自动调用用IE打开网页而不是用自身浏览器打开网页。如何让窗口用我自己的浏览器打开?

  http://www.csdn.net/develop/read_article.asp?id=21702
  控制新的窗口
  默认情况下,浏览器收到创建新窗口请求时,会在IE中打开新的窗口。你可以处理NewWindow2事件来在自己指定的窗口中打开请求的页面。

问:
  如何枚举系统中视频捕获设备(摄像头)的设备名称
答:
  以下代码来 自DirectX9 SDK中的AMCAP示例

// put all installed video and audio devices in the menus 
// 
void AddDevicesToMenu() 

…… 
    // enumerate all video capture devices 
    ICreateDevEnum *pCreateDevEnum=0; 
    hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER, 
                          IID_ICreateDevEnum, (void **)&pCreateDevEnum); 
    if (hr != NOERROR) 
    { 
        ErrMsg(TEXT("Error Creating Device Enumerator" )); 
        return ; 
    } 

    IEnumMoniker *pEm=0; 
    hr = pCreateDevEnum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory, &pEm, 0); 
    if (hr != NOERROR) 
    { 
        ErrMsg(TEXT("Sorry, you have no video capture hardware./r/n/r/n" ) 
               TEXT("Video capture will not function properly." )); 
        goto EnumAudio; 
    } 

    pEm->Reset(); 
    ULONG cFetched; 
    IMoniker *pM; 

    while (hr = pEm->Next(1, &pM, &cFetched), hr==S_OK) 
    { 
        IPropertyBag *pBag=0; 

        hr = pM->BindToStorage(0, 0, IID_IPropertyBag, (void **)&pBag); 
        if (SUCCEEDED(hr)) 
        { 
            VARIANT var; 
            var.vt = VT_BSTR; 
            hr = pBag->Read(L"FriendlyName" , &var, NULL); 
            if (hr == NOERROR) 
            { 
                AppendMenu(hMenuSub, MF_STRING, MENU_VDEVICE0 + uIndex, 
                    W2T(var.bstrVal)); 

                if (gcap.pmVideo != 0 && (S_OK == gcap.pmVideo->IsEqual(pM))) 
                    bCheck = TRUE; 

                CheckMenuItem(hMenuSub,  MENU_VDEVICE0 + uIndex, 
                    (bCheck ? MF_CHECKED : MF_UNCHECKED)); 
                EnableMenuItem(hMenuSub, MENU_VDEVICE0 + uIndex, 
                    (gcap.fCapturing ? MF_DISABLED : MF_ENABLED)); 
                bCheck = FALSE; 

                SysFreeString(var.bstrVal); 

                ASSERT(gcap.rgpmVideoMenu[uIndex] == 0); 
                gcap.rgpmVideoMenu[uIndex] = pM; 
                pM->AddRef(); 
            } 
            pBag->Release(); 
        } 

        pM->Release(); 
        uIndex++; 
    } 
    pEm->Release();

问:
  我目前使用 BCG 中的 CBCGPPropList 来实现某一个东西的属性,可是有一项数据特别大,大约500个字符,我希望能把这一项的高度调整可是不知道如何处理,不知道能单独调整其中一项吗

  答:从CBCGPProp派生一个函数,重载OnEdit并在其中创建一个需要的大小的编辑框。最后Add自定义的prop类对象。具体实现可以参照CBCGPColorProp和CBCGPFontProp类的实现

  问:我想实现一个功能,就是检测一个目录或文件,看它是否存在,如果不存在就创建这个目录或文件。
  答:
  可以用Win32文件查找来查找文件或者文件夹是否存在,也可以用PathFileExists来判断。GetFileAttributes和 PathIsDirectory可以用于判断文件是否是目录。创建文件可以用CreateDirectory或者 MakeSureDirectoryPathExists。

bool FileExists(CString FileName) 

    WIN32_FIND_DATA FindFileData; 
    HANDLE hFind; 
    bool FindFlag = false ; 

    hFind = FindFirstFile(FileName , &FindFileData); 

    if (hFind == INVALID_HANDLE_VALUE) 
    { 
        FindFlag = false ; 
    } 
    else 
    { 
        FindFlag = true ; 
    } 
    FindClose(hFind); 
    return FindFlag; 

DWORD   dwFlag = GetFileAttributes(pathname); 
if ( 0xFFFFFFFF == dwFlag ) 不存在; 
if (  FILE_ATTRIBUTE_DIRECTORY & dwFlag ) 是文件夹 
else 是文件

  问:
  请教一下,html中如果已知Activex的classid,有什么办法可以直接找到它? 通过id来查找比较慢,所以问一下可否通过这种方式?取得IOleObject之后,我需要如何做才可以调用Activex控件中的函数呢?
  答:
  由于控件所在容器是HTMLDocument对象,你可以用IOleContainer::EnumObjects枚举里面的OLE对象,包括控件和框架

IOleContainer* pContainer; 

  // Get the container 
  HRESULT hr = pHtmlDoc2->QueryInterface(IID_IOleContainer, 
                                      (void **)&pContainer); 
  lpDisp->Release(); 

  if (FAILED(hr)) 
     return hr; 

  IEnumUnknown* pEnumerator; 

  // Get an enumerator for the frames 
  hr = pContainer->EnumObjects(OLECONTF_EMBEDDINGS, &pEnumerator); 
  pContainer->Release(); 

  if (FAILED(hr)) 
     return hr; 

  IUnknown* pUnk; 



  ULONG uFetched; 

  // Enumerate and refresh all the frames 
  for (UINT i = 0; S_OK == pEnumerator->Next(1, &pUnk, &uFetched); i++) 
  { 
     // QI for IOleObject here to see if we have an embedded browser 
     IOleObject* pOleObject; 

     hr = pUnk->QueryInterface(IID_IOleObject, (void **)&pOleObject); 
     pUnk->Release(); 

     if (SUCCEEDED(hr)) 
     { 
         CLSID clsID; 
         pOleObject->GetUserClassID(&clsID); 
     } 
  } 

  pEnumerator->Release();

控件的IOleObject接口是用来查询控件的CLSID的。你应该查询控件的IDispatch接口,然后按照http://www.csdn.net/develop/read_article.asp?id=14752 里面的方法调用其属性和方法。

  问:
  已知PIDL怎么得到他对应的IShellFolder指针呢 
  答:用SHBindtoParent就可以了

IShellFolder *psfParent; //A pointer to the parent folder object's IShellFolder interface 
LPITEMIDLIST pidlItem = NULL; //the item's PIDL 
LPITEMIDLIST pidlRelative = NULL; //the item's PIDL relative to the parent folder 
STRRET str; //the display name's STRRET structure 
TCHAR szDisplayName[MAX_PATH]; //the display name's string 

HRESULT hres = SHBindToParent(pidlItem, IID_IShellFolder, &psfParent, &pidlRelative); 
if (SUCCEEDED(hres)) 

    psfParent->GetDisplayNameOf(pidlRelative, SHGDN_NORMAL, &str); 
    psfParent->Release(); 
    StrRetToBuf(&str, pidlItem, szDisplayName, ARRAYSIZE(szDisplayName)); 
}

问:如何handle IE的textsize changed event? 我想在用户改变text size 时做些处理,请问该如何handle,在哪个事件中做?谢谢指教。
  答:sink HtmlDocument对象的IOleCommandTaget接口。

  问:  IStream *pStream; CString mString; 怎么样才能把pStream的内容赋给mString呢? 
  答:下面的代码把一个内存流读到字节数组。你可以根据字符串的类型把字节数组转化成字符串。

COleStreamFile osfRead; 
osfRead.Attach(pStream); 
long lLength=osfRead.GetLength(); 
CByteArray baBuf; 
baBuf.SetSize(lLength); 
osfRead.Read(baBuf.GetData(),lLength);

问:我Create了一个ListControl用来显示文件列表?怎么实现有图标的文件显示阿?
  答:SHGetFileInfo可以返回系统图像列表,里面包含每一种文件类型的图标。参见http://www.csdn.net/develop/read_article.asp?id=22243 
  问题:如何编写无界面的HTML解析器?
  答:walkall示例就是一个无界面的HTML解析器。
 
  问:用AfxBeginThread创建的线程除了调用AfxEndThread还可以用什么函数关闭? 
  答:
  可以从外部用事件通知来优雅地结束线程
  启动线程m_pThreadWrite=AfxBeginThread(ThreadProc,(LPVOID)this);
线程体。为了避免在静态函数中引用对象指针的麻烦,调用对象参数的线程体成员函数。

UINT CMyClass::ThreadProc(LPVOID lp) 

    CMicrophoneInput* pInput = (CMicrophoneInput*)lp; 
    return pInput->Run(); 

简单的循环检测退出标志 
UINT CMyClass::Run() 

    HRESULT hr; 
    if (!InitInstance()) 
    { 
        TRACE("InitInstance failed/r/n" ; 
              return ExitInstance(); 
          } 
          while (!IsKilling()) 
    { 
//do something 
    } 
    return ExitInstance(); 

重设退出标志 
BOOL CMyClass::InitInstance() 

    m_eventKill.ResetEvent(); 
    m_eventDead.ResetEvent(); 
//do something 
    return TRUE 
       } 
       设已退出标志 
       UINT CMyClass::ExitInstance() 

//do something 
    m_eventDead.SetEvent(); 
    return 0; 
}

检查退出标志

BOOL CMyClass::IsDead() 

    return WaitForSingleObject(m_eventDead, 0) == WAIT_OBJECT_0; 

BOOL CMyClass::IsKilling() 

    return WaitForSingleObject(m_eventKill, 0) == WAIT_OBJECT_0; 
}

在外部可以这样终止线程

//check if dead 
if (!IsDead()&&m_pThreadWrite!=NULL){ 
m_eventKill.SetEvent(); 
WaitForSingleObject(m_eventDead,INFINITE); 
m_pThreadWrite=NULL; 
}

问:怎么实现IEnumString接口?
  答:http://www.codeproject.com/wtl/customautocomplete_wtl.asp 
IAutoComplete and custom IEnumString implementation for WTL dialogs
  下面是我的基于数据库的IEnumString实现

if !defined(AFX_ENUMSTRING_H__4D5D61AD_CD0D_477C_880F_8E5EEB5B1E8F__INCLUDED_) 
#define AFX_ENUMSTRING_H__4D5D61AD_CD0D_477C_880F_8E5EEB5B1E8F__INCLUDED_ 

#if _MSC_VER > 1000 
#pragma once 
#endif // _MSC_VER > 1000 
// EnumString.h : header file 
// 

////////////////////////////////////////////////////////// 
// CEnumString command target 
#include  
#include "esuihelper.h" 
class _ES_UI_EXPORT CEnumString : public IEnumString 

    public : 
        CEnumString();           // protected constructor used by dynamic creation 
// Attributes 
    public : 
        ULONG m_nRefCount; 
// Operations 
    public : 
        STDMETHODIMP_(ULONG ) AddRef(); 
        STDMETHODIMP_(ULONG ) Release(); 
        STDMETHODIMP QueryInterface(REFIID riid, void ** ppvObject); 
        STDMETHODIMP Next(ULONG celt, LPOLESTR* rgelt, ULONG * pceltFetched); 
        STDMETHODIMP Skip(ULONG celt); 
        STDMETHODIMP Reset(void ); 
        STDMETHODIMP Clone(IEnumString** ppenum); 
        BOOL Bind(HWND p_hWndEdit, DWORD p_dwOptions = 0, LPCTSTR p_lpszFormatString = NULL); 
        VOID Unbind(); 
// Overrides 
// ClassWizard generated virtual function overrides 
//{{AFX_VIRTUAL(CEnumString) 
//}}AFX_VIRTUAL 

// Implementation 
    protected : 
        virtual ~CEnumString(); 
        CComPtr m_pac; 
        BOOL m_fBound; 
// Generated message map functions 
//{{AFX_MSG(CEnumString) 
        // NOTE - the ClassWizard will add and remove member functions here. 
//}}AFX_MSG 

    }; 

///////////////////////////////////////////////////////////// 

//{{AFX_INSERT_LOCATION}} 
// Microsoft Visual C++ will insert additional declarations immediately before the previous line. 

#endif // !defined(AFX_ENUMSTRING_H__4D5D61AD_CD0D_477C_880F_8E5EEB5B1E8F__INCLUDED_) 
// EnumString.cpp : implementation file 
// 

#include "stdafx.h" 
#include "EnumString.h" 

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

///////////////////////////////////////////////////////////// 
// CEnumString 


CEnumString::CEnumString() 

    m_fBound = FALSE; 
    m_nRefCount = 0; 





CEnumString::~CEnumString() 



///////////////////////////////////////////////////////////// 
// CEnumString message handlers 
ULONG FAR EXPORT CEnumString::AddRef() 

    TRACE_LINE("CEnumString::AddRef/n" ); 
    return ::InterlockedIncrement(reinterpret_cast <LONG *>(&m_nRefCount)); 


ULONG FAR EXPORT CEnumString::Release() 

    TRACE_LINE("CEnumString::Release/n" ); 
    ULONG nCount = 0; 
    nCount = (ULONG ) ::InterlockedDecrement(reinterpret_cast <LONG *>(&m_nRefCount)); 

    if (nCount == 0) 
        delete this ; 

    return nCount; 



HRESULT FAR EXPORT CEnumString::QueryInterface( 
    REFIID riid, void FAR* FAR* ppvObject ) 

    HRESULT hr = E_NOINTERFACE; 

    if (ppvObject != NULL) 
    { 
        *ppvObject = NULL; 

        if (IID_IUnknown == riid) 
            *ppvObject = static_cast (this ); 

        if (IID_IEnumString == riid) 
            *ppvObject = static_cast (this ); 

        if (*ppvObject != NULL) 
        { 
            hr = S_OK; 
            ((LPUNKNOWN)*ppvObject)->AddRef(); 
        } 



    } 
    else 
    { 
        hr = E_POINTER; 
    } 

    return hr; 


STDMETHODIMP CEnumString::Next(ULONG celt, LPOLESTR* rgelt, ULONG * pceltFetched) 

    return E_NOTIMPL; 


STDMETHODIMP CEnumString::Skip(ULONG celt) 

    return E_NOTIMPL; 


STDMETHODIMP CEnumString::Reset(void ) 

    return E_NOTIMPL; 

STDMETHODIMP CEnumString::Clone(IEnumString** ppenum) 

    if (!ppenum) 
        return E_POINTER; 

    CEnumString* pnew = new CEnumString; 
    pnew->AddRef(); 
    *ppenum = pnew; 
    return S_OK; 

BOOL CEnumString::Bind(HWND p_hWndEdit, DWORD p_dwOptions /*= 0-*/ , LPCTSTR p_lpszFormatString /*= NULL*/ ) 

    if ((m_fBound) || (m_pac)) 
        return FALSE; 
    HRESULT hr = S_OK; 

    hr = m_pac.CoCreateInstance(CLSID_AutoComplete); 
    if (SUCCEEDED(hr)) 
    { 

        if (p_dwOptions) 
        { 
            CComQIPtr pAC2(m_pac); 

            ATLASSERT(pAC2); 
            hr = pAC2->SetOptions(p_dwOptions);   // This never fails? 
            pAC2.Release(); 

        } 

        hr = m_pac->Init(p_hWndEdit, this , NULL, (LPOLESTR)p_lpszFormatString); 
        if (SUCCEEDED(hr)) 
        { 
            m_fBound = TRUE; 
            return TRUE; 
        } 
    } 
    return FALSE; 

VOID CEnumString::Unbind() 


    if (!m_fBound) 
        return ; 

    ATLASSERT(m_pac); 

    if (m_pac) 
    { 
        m_pac.Release(); 
        m_fBound = FALSE; 

    } 

#include "../esuihelper/EnumString.h" 
#include "DataType.h" 
class CDataType; 
class _ES_DATATYPE_EXPORT CEnumDataType : public CEnumString 

public : 
    CEnumDataType(LPCTSTR lpszDataType); 
    virtual ~CEnumDataType(); 
    CDataType* m_pDataType; 
protected : 
    CString m_strDataType; 
    STDMETHODIMP Next(ULONG celt, LPOLESTR* rgelt, ULONG * pceltFetched); 
    STDMETHODIMP Skip(ULONG celt); 
    STDMETHODIMP Reset(void ); 
    STDMETHODIMP Clone(IEnumString** ppenum); 
    ado20::_RecordsetPtr m_pRecordset; 
}; 
CEnumDataType::CEnumDataType(LPCTSTR lpszDataType) 
        : m_strDataType(lpszDataType) 




    m_pDataType = g_pDataTypeManager->GetDataType(m_strDataType); 
    ASSERT(m_pDataType); 
    m_pRecordset.CreateInstance("ADODB.Recordset" ); 
    try 
    { 
        if (m_pRecordset != NULL) 
        { 
            if ( m_pRecordset->State&adStateOpen) 
            { 
                return ; 
            } 
        } 
        ESRecordsetOpen((LPCTSTR )m_pDataType->m_strSQLAutoComplete, _variant_t((IDispatch *)g_connection, true ), 
                        m_pRecordset, adOpenDynamic, adLockOptimistic, adCmdUnspecified); 

        m_pRecordset->Requery(adCmdUnknown); 
        if (m_pRecordset->BOF == VARIANT_FALSE) 
            m_pRecordset->MoveFirst(); 
    } 
    catch (_com_error &e) 
    { 
        ESErrPrintProviderError(g_connection); 
        ESErrPrintComError(e); 
    } 


CEnumDataType::~CEnumDataType() 

    try 
    { 
        if (m_pRecordset != NULL) 
        { 
            if ( m_pRecordset->State&adStateOpen) 
            { 
                m_pRecordset->Close(); 
            } 
        } 
    } 
    catch (_com_error &e) 
    { 
        ESErrPrintProviderError(g_connection); 
        ESErrPrintComError(e); 
    } 

STDMETHODIMP CEnumDataType::Next(ULONG celt, LPOLESTR* rgelt, ULONG * pceltFetched) 

    if (m_pRecordset == NULL) return OLE_E_BLANK; 

    HRESULT hr = S_FALSE; 
    ZeroMemory(rgelt, sizeof (OLECHAR*) * celt); 
    try 
    { 
        if (!celt) celt = 1; 
        for (ULONG i = 0; i < celt; i++) 
        { 
            if (m_pRecordset->EndOfFile == VARIANT_TRUE) 
                break ; 
            _bstr_t bstrText = 
                (LPCTSTR )g_GetValueString( 
                    m_pRecordset->Fields->Item[(LPCTSTR )m_pDataType->m_strAutoCompleteField]->Value); 
            if (bstrText.length() > 0) 
            { 
                rgelt[i] = OLESTRDUP(bstrText); 
                if (pceltFetched) 
                    *pceltFetched++; 
            } 
            m_pRecordset->MoveNext(); 
        } 
        if (i == celt) 
            hr = S_OK; 
    } 
    catch (_com_error &e) 
    { 
        ESErrPrintProviderError(g_connection); 
        ESErrPrintComError(e); 
        return e.Error(); 
    } 
    return hr; 

STDMETHODIMP CEnumDataType::Skip(ULONG celt) 

    if (m_pRecordset == NULL) return OLE_E_BLANK; 
    try 
    { 
        m_pRecordset->Move(celt, (long )adBookmarkCurrent); 
    } 
    catch (_com_error &e) 
    { 
        ESErrPrintProviderError(g_connection); 
        ESErrPrintComError(e); 
        return e.Error(); 
    } 
    return S_OK; 

STDMETHODIMP CEnumDataType::Reset(void ) 

    if (m_pRecordset == NULL) return OLE_E_BLANK; 
    try 
    { 
        m_pRecordset->Requery(adCmdUnknown); 
        if (m_pRecordset->BOF == VARIANT_FALSE) 
            m_pRecordset->MoveFirst(); 
    } 
    catch (_com_error &e) 



    { 
        ESErrPrintProviderError(g_connection); 
        ESErrPrintComError(e); 
        return e.Error(); 
    } 
    return S_OK; 

STDMETHODIMP CEnumDataType::Clone(IEnumString** ppenum) 

    if (!ppenum) 
        return E_POINTER; 

    CEnumDataType* pnew = new CEnumDataType(m_strDataType); 
    pnew->AddRef(); 
    *ppenum = pnew; 
    return S_OK; 
}
阅读(873) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~