我有一个标准的GDI win32应用程序。我有一个组件可以通过利用IOleInPlaceSiteWindowless / IOleInPlaceObjectWindowless接口来托管无窗口ActiveX控件(我们通常用于Flash),因此每当托管控件回调到InvalidateRect时调用IViewObject :: Draw。此组件通常在本文之后建模:http://www.codeguru.com/cpp/com-tech/activex/controls/article.php/c12229/Transparent-Flash-Control-in-Plain-C.htm
现在我的应用程序针对一些较旧的硬件,我发现这种方法存在一些性能问题,我在Internet Explorer中运行相同的ActiveX控件时看不到这些问题。事实上,使用进程监视器,我能够看到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);
与我的初始实现类似,只要控件调用InvalidateRect,我就会调用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);
不确定我做错了什么,而且基本上卡住了。任何帮助将不胜感激。