しつこいですかw
の続続編です。こういうのは一気に片付けないと。。。
と
をみて、DWMSharedSurfaceを使ったキャプチャを実装してみました。
前々回のソースに追加していきます。
DWMをつかったウィンドウ指定の隠れ関数があるらしい(なぜかdwmapi.dll
じゃなくてuser32.dll
に)
ってことなので抜き出します。
// DWM Capture
BOOL (__stdcall *DwmGetDxSharedSurface)(HWND, HANDLE *, uint64_t *, DWORD *, DWORD *, uint64_t *)=NULL;
uint64_t adapterLuid=0;
HANDLE pDXGI_SharedHandle=NULL;
ID3D11Texture2D *texture_shared=NULL;
関数の第1、第2引数だけあれば動作するらしいんですが、参考にさせてもらったサイトの情報に習い、アダプターのLUIDも生成しておきます。
// load DWM-function
HMODULE hdll=LoadLibrary("user32.dll");
if(hdll){
DwmGetDxSharedSurface=(BOOL(__stdcall *)(HWND, HANDLE *, uint64_t *, DWORD *, DWORD *, uint64_t *))
GetProcAddress(hdll, "DwmGetDxSharedSurface");
}
if(DwmGetDxSharedSurface==NULL) printf("not found function: DwmGetDxSharedSurface\n");
IDXGIAdapter1 *adapter;
DXGI_ADAPTER_DESC1 dxgi_desc{};
pDXGI_Factory->EnumAdapters1(0, &adapter); // index=0;
adapter->GetDesc1(&dxgi_desc);
adapterLuid=(((uint64_t)dxgi_desc.AdapterLuid.HighPart)<<32)|(dxgi_desc.AdapterLuid.LowPart);
adapter->Release();
printf("adapter's LUID=%llu\n", adapterLuid);
キャプチャ開始すると共有リソースに対象ウィンドウのテクスチャが更新され続けるようです。
bool CaptDWM_FrameCopy(IDXGISwapChain1 *swapchain)
{
DXGI_SWAP_CHAIN_DESC1 sc_desc{};
swapchain->GetDesc1(&sc_desc);
int offset_x=1;
int offset_y=GetSystemMetrics(SM_CYCAPTION)+8;
D3D11_BOX src_region{};
src_region.left =offset_x;
src_region.right =offset_x+sc_desc.Width;
src_region.top =offset_y;
src_region.bottom =offset_y+sc_desc.Height;
src_region.front =0;
src_region.back =1;
ID3D11Texture2D *texture_dst;
swapchain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&texture_dst);
pD3D_DC->CopySubresourceRegion(texture_dst, 0, 0, 0, 0, texture_shared, 0, &src_region);
texture_dst->Release();
return true;
}
bool CaptDWM_Start(MyWin wDst, HWND hwndSrc)
{
if(pDXGI_SharedHandle!=NULL) return false;
if(DwmGetDxSharedSurface==NULL) return false;
DwmGetDxSharedSurface(hwndSrc, &pDXGI_SharedHandle, &adapterLuid, NULL, NULL, NULL);
if((pDXGI_SharedHandle==NULL)||(pDXGI_SharedHandle==INVALID_HANDLE_VALUE)) return false;
pD3D_Device->OpenSharedResource(pDXGI_SharedHandle, __uuidof(ID3D11Texture2D), reinterpret_cast<void **>(&texture_shared));
if(texture_shared==NULL) return false;
D3D11_TEXTURE2D_DESC texture_desc{};
texture_shared->GetDesc(&texture_desc);
printf("start capture(%d,%d) with DWM\n", texture_desc.Width, texture_desc.Height);
return true;
}
void CaptDWM_Stop()
{
if(texture_shared!=NULL) { texture_shared->Release(); texture_shared=NULL; }
if(pDXGI_SharedHandle!=NULL){ CloseHandle(pDXGI_SharedHandle); pDXGI_SharedHandle=NULL; }
}
ってことで、排他も考えずにガンガンコピーします。(DirectX11だとどうなんじゃろ?)
if(mywinO.pDXGI_DC!=NULL){
if(texture_shared!=NULL){
CaptDWM_FrameCopy(mywinO.pDXGI_SwapChain);
mywinO.pDXGI_DC->BeginDraw();
mywinO.pDXGI_DC->SetTransform(D2D1::Matrix3x2F::Identity());
mywinO.pDXGI_DC->DrawBitmap(Overlay_Image_Bitmap,
D2D1::RectF(220.f, 0.f, 220.f+(float)overlay_image_width, 0.f+(float)overlay_image_height),
1.f, D2D1_BITMAP_INTERPOLATION_MODE_LINEAR);
mywinO.pDXGI_DC->EndDraw();
mywinO.pDXGI_SwapChain->Present(1, 0);
}
あの忌々しい黄色い枠はこの方法だと付きませんね^^(その分だけズレが発生しました)
しかーし、DierctXの描画はキャプチャされませんでした><