Visual c++ 如何利用DirectX/DirectDraw加速托管的无窗口ActiveX控件的动画

Visual c++ 如何利用DirectX/DirectDraw加速托管的无窗口ActiveX控件的动画,visual-c++,directx,activex,gdi,ole,Visual C++,Directx,Activex,Gdi,Ole,我有一个标准的GDI win32应用程序。我有一个组件,它可以通过利用IOleInPlaceSiteWindowless/IOleInPlaceObjectWindowless接口对来承载无窗口ActiveX控件(我们通常在Flash中使用它),从而在宿主控件调用InvalidateObject时调用IViewObject::Draw。此组件通常按照本文建模: 现在,我的应用程序针对一些较旧的硬件,我发现这种方法存在一些性能问题,而在Internet Explorer中运行相同的ActiveX控

我有一个标准的GDI win32应用程序。我有一个组件,它可以通过利用IOleInPlaceSiteWindowless/IOleInPlaceObjectWindowless接口对来承载无窗口ActiveX控件(我们通常在Flash中使用它),从而在宿主控件调用InvalidateObject时调用IViewObject::Draw。此组件通常按照本文建模:

现在,我的应用程序针对一些较旧的硬件,我发现这种方法存在一些性能问题,而在Internet Explorer中运行相同的ActiveX控件时,我没有看到这些问题。事实上,使用process monitor,我可以看到IE在某种程度上使用GPU进行渲染,而我的应用程序没有。这让我发现IE很可能在幕后使用DirectDraw来实现更好的性能

所以我尝试在我的应用程序中这样做,但是我没有看到屏幕上画出任何东西。我的DirectX/DirectDraw知识几乎为零,因此可能与此有关,但以下是我正在尝试的。也许有人能看到我做错了什么,并把我带到我需要的地方(请注意,我只是在玩,这就是为什么没有错误处理):

  • 我创建我的分层窗口

    ivhWnd = CreateWindowEx(WS_EX_LAYERED,
    L"MyWndClass",
    NULL,
    WS_POPUP | WS_VISIBLE | WS_CLIPSIBLINGS, 
    CW_USEDEFAULT,
    CW_USEDEFAULT,
    CW_USEDEFAULT,
    CW_USEDEFAULT,
    ivhParentWindow,
    ( HMENU )NULL,
    ivhAppInstance,
    ( LPVOID )NULL );
    
  • 我初始化DirectDraw并创建屏幕外表面:

    DirectDrawCreateEx(NULL, (LPVOID*)&pivDD, IID_IDirectDraw7, NULL);
    pivDD->SetCooperativeLevel(NULL, DDSCL_NORMAL);
    
    DDSURFACEDESC2 tvSurfDesc;
    ZeroMemory(&tvSurfDesc, sizeof(DDSURFACEDESC2));
    
    tvSurfDesc.dwSize = sizeof(DDSURFACEDESC2);
    tvSurfDesc.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH;
    tvSurfDesc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY;
    tvSurfDesc.dwWidth = 320;
    tvSurfDesc.dwHeight = 340;
    
    HRESULT tvHR = pivDD->CreateSurface((LPDDSURFACEDESC)&tvSurfDesc, (LPDIRECTDRAWSURFACE*)&pivPrimarySurface, NULL);
    
    LPDIRECTDRAWCLIPPER ptvClipper;
    pivDD->CreateClipper(0, &ptvClipper, NULL);
    
    ptvClipper->SetHWnd(0, ivhInternalMsgWindow);
    
    pivPrimarySurface->SetClipper(ptvClipper);
    
  • 类似于我最初的实现,每当控件调用InvalidateObject::Draw时,我调用了IViewObject::Draw;我现在基本上也这样做了,但将DC用于我的DDraw曲面,而不是兼容的位图:

    RECT rTotal;
    ::GetClientRect(ivhWnd, &rTotal);
    
    HDC tvhDC;
    pivPrimarySurface->GetDC(&tvhDC);
    
    HRESULT tvHR = OleDraw(ivViewObject, DVASPECT_TRANSPARENT, tvhDC, &rTotal);
    
    BLENDFUNCTION bf;
    bf.BlendOp = AC_SRC_OVER;
    bf.AlphaFormat = AC_SRC_ALPHA;
    bf.BlendFlags = 0;
    bf.SourceConstantAlpha = 255;
    
    UpdateLayeredWindow(ivhWnd, NULL, NULL, NULL, tvhDC, NULL, 0, &bf, ULW_ALPHA);
    

  • 不确定我做错了什么,我基本上被卡住了。如果有任何帮助,我们将不胜感激。

    对于代码格式问题,我们深表歉意-不确定创建DirectDraw曲面时会发生什么,您不希望通过其DC进行绘制。整个想法是,DC是一种很少来回传输数据的工具,例如,当您需要初始化曲面并加载初始数据时。为了实现高性能指标,您希望在每次绘制时不创建兼容DC的情况下对曲面进行blit。感谢您的回复。我想我不明白的是如何实现Internet Explorer的功能。我知道,在我们第一次调用OleDraw时,IShockwaveFlash对象查询IDirectDraw3(没有文档记录),但仅仅返回一个新对象似乎还不够——我认为这样做没有任何好处。很明显,这里有一个缺失的部分,我无法理解。