用C语言实现IBindStatusCallback接口

标签: , , , ,

昨天在Google关键字“URLDownloadToFile IBindStatusCallback”的时候,看到了看雪论坛上一个名为《在C中怎么使用IBindStatusCallback接口里的方法》的帖子。有人给出了C++的实现,有人留了一句“这样比较麻烦,但是可以实现”,却没有代码。

如果说Linux是C的天下,那么Windows就是C++的天下了。曾经有人问我,在Windows下C++比C方便得多,你为什么偏要用C?我回答,不为什么,因为我喜欢。

和COM开发有关的C语言资料真的很少,但并不是没有,Jeff Glatt的神作《COM in plain C》是最好的资料。把《COM in plain C》看完,实现IBindStatusCallback接口只是小菜一碟。

简单起见,只实现了最常用的OnProgress方法,并且是黑乎乎的控制台程序。只要把原理弄清楚,写一个简单的带进度条的GUI下载器也不是难事。

/***********************************
Author  : Demon
Website : https://demon.tw
E-mail  : 380401911@qq.com
***********************************/
#include <stdio.h>
#include <urlmon.h>
#pragma comment (lib, "urlmon.lib")

HRESULT ( STDMETHODCALLTYPE QueryInterface )( 
    IBindStatusCallback * This,
    /* [in] */ REFIID riid,
    /* [iid_is][out] */ void **ppvObject)
{
    return E_NOTIMPL;
}

ULONG ( STDMETHODCALLTYPE AddRef )( 
    IBindStatusCallback * This)
{
    return E_NOTIMPL;
}

ULONG ( STDMETHODCALLTYPE Release )( 
    IBindStatusCallback * This)
{
    return E_NOTIMPL;
}

HRESULT ( STDMETHODCALLTYPE OnStartBinding )( 
    IBindStatusCallback * This,
    /* [in] */ DWORD dwReserved,
    /* [in] */ IBinding *pib)
{
    return E_NOTIMPL;
}

HRESULT ( STDMETHODCALLTYPE GetPriority )( 
    IBindStatusCallback * This,
    /* [out] */ LONG *pnPriority)
{
    return E_NOTIMPL;
}

HRESULT ( STDMETHODCALLTYPE OnLowResource )( 
    IBindStatusCallback * This,
    /* [in] */ DWORD reserved)
{
    return E_NOTIMPL;
}

HRESULT ( STDMETHODCALLTYPE OnProgress )( 
    IBindStatusCallback * This,
    /* [in] */ ULONG ulProgress,
    /* [in] */ ULONG ulProgressMax,
    /* [in] */ ULONG ulStatusCode,
    /* [in] */ LPCWSTR szStatusText)
{
    if (ulProgress > 0)
    {   
        printf("Downloaded %d of %d bytes\n",
            ulProgress, ulProgressMax); 
        fflush(stdout);
    }
    return S_OK;
}

HRESULT ( STDMETHODCALLTYPE OnStopBinding )( 
    IBindStatusCallback * This,
    /* [in] */ HRESULT hresult,
    /* [unique][in] */ LPCWSTR szError)
{
    return E_NOTIMPL;
}

HRESULT ( STDMETHODCALLTYPE GetBindInfo )( 
    IBindStatusCallback * This,
    /* [out] */ DWORD *grfBINDF,
    /* [unique][out][in] */ BINDINFO *pbindinfo)
{
    return E_NOTIMPL;
}

HRESULT ( STDMETHODCALLTYPE OnDataAvailable )( 
    IBindStatusCallback * This,
    /* [in] */ DWORD grfBSCF,
    /* [in] */ DWORD dwSize,
    /* [in] */ FORMATETC *pformatetc,
    /* [in] */ STGMEDIUM *pstgmed)
{
    return E_NOTIMPL;
}

HRESULT ( STDMETHODCALLTYPE OnObjectAvailable )( 
    IBindStatusCallback * This,
    /* [in] */ REFIID riid,
    /* [iid_is][in] */ IUnknown *punk)
{
    return E_NOTIMPL;
}

static const IBindStatusCallbackVtbl IBindStatusCallback_Vtbl =
{
    QueryInterface,
    AddRef,
    Release,
    OnStartBinding,
    GetPriority,
    OnLowResource,
    OnProgress,
    OnStopBinding,
    GetBindInfo,
    OnDataAvailable,
    OnObjectAvailable
};

int main(int argc, char *argv[])
{
    HRESULT hr;
    IBindStatusCallback MyCallback;
    MyCallback.lpVtbl = (IBindStatusCallbackVtbl *)&IBindStatusCallback_Vtbl;
    hr = URLDownloadToFile(NULL, 
        "https://demon.tw/download/VbsEdit.zip", "VbsEdit.zip", 0, &MyCallback);
    if (FAILED(hr))
    {
        printf("Error: %X\n", hr);
    }
    return 0;
}

两年前的帖子了,不知道发帖那位朋友看不看得到。也许,他现在已经不写代码了吧。两年后的我呢?

赞赏

微信赞赏支付宝赞赏

随机文章:

  1. VBS字符串的内部实现
  2. Ubuntu下安装Lighttpd+PHP+MySQL
  3. 远程桌面连接用户名密码错误的解决方法
  4. VB使用WebBrowser读取网页中iframe的内容
  5. Unicode中的方框绘制字符

留下回复