以下のリンクを見て私もウィンドウキャプチャのアプリを作ってみたくなりました。車輪の再発明w
なので、詳細は上記リンクを参照してくださいね。
以下、自分用ののメモというか雑記。
DirectX11の書き方の思い出し
普段の画像表示には自前のライブラリを利用しているので、書き方をすっかり忘れてました。
こんな感じ?
スタティックの子ウィンドウとボタンを貼り付けて、右側のスタティックにビットマップを描画するようにしました。
// DisableWarnings
# pragma warning(disable: 4996) // disable warning "may be unsafe"
// CRT
# define _CRT_SECURE_NO_WARNINGS
# include <stdio.h>
# include <math.h>
// STL
# include <tuple>
# include <vector>
# include <functional>
using std::placeholders::_1;
using std::placeholders::_2;
// Win32
# define _WINSOCK_DEPRECATED_NO_WARNINGS
# define WIN32_LEAN_AND_MEAN
# define OEMRESOURCE
# include <windows.h>
# include <shlwapi.h>
# pragma comment(lib, "shlwapi.lib")
# include <commctrl.h>
# pragma comment(lib, "comctl32.lib")
# pragma comment(linker, "\"/manifestdependency:type='Win32' "\
"name='Microsoft.Windows.Common-Controls' version='6.0.0.0' "\
"processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")
// DirectX
# include <d3d11_4.h>
# pragma comment(lib, "d3d11.lib")
# include <dxgi1_3.h>
# pragma comment(lib, "dxgi.lib")
# include <d2d1_2.h>
# include <d2d1helper.h>
# pragma comment(lib, "d2d1.lib")
# include <dcomp.h>
# pragma comment(lib, "dcomp.lib")
# include <wincodec.h>
# pragma comment(lib, "windowscodecs.lib")
/////////////////////////////////////////////////////////////////////////////////////////////
# define ID_IMGL 100
# define ID_IMGR 101
# define ID_BTN1 102
# define ID_BTN2 103
HINSTANCE hInstance;
char HomeFolderName[MAX_PATH]{};
// DirectX
ID2D1Factory1 *pD2D_Factory=NULL;
IDXGIFactory2 *pDXGI_Factory=NULL;
IWICImagingFactory *pWIC_Factory=NULL;
ID3D11Device *pD3D_Device=NULL;
ID3D11DeviceContext *pD3D_DC=NULL;
IDXGIDevice *pDXGI_Device=NULL;
ID2D1Device *pD2D_Device=NULL;
// ImageResource
ID2D1Bitmap1 *Image_Bitmap=NULL;
今回はエフェクトを使用しないのでコンポジションは使用しません。
struct MyWin
{
void CreateSwapChain(HWND _hwnd, int _width, int _height);
void ReleaseSwapChain();
HWND hwnd=NULL;
int width, height;
IDXGISwapChain1 *pDXGI_SwapChain=NULL;
ID2D1DeviceContext *pDXGI_DC=NULL;
IDCompositionDevice *pDComp_Device=NULL;
IDCompositionTarget *pDComp_Target=NULL;
IDCompositionVisual *pDComp_Visual=NULL;
ID2D1Bitmap1 *Surface_Bitmap=NULL;
};
void MyWin::CreateSwapChain(HWND _hwnd, int _width, int _height)
{
hwnd=_hwnd;
width=_width;
height=_height;
// Create SwapChain
DXGI_SWAP_CHAIN_DESC1 sc_desc{};
sc_desc.Width =width;
sc_desc.Height =height;
sc_desc.Format =DXGI_FORMAT_B8G8R8A8_UNORM;
sc_desc.BufferUsage =DXGI_USAGE_RENDER_TARGET_OUTPUT;
sc_desc.SwapEffect =DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL; //DXGI_SWAP_EFFECT_FLIP_DISCARD;
sc_desc.BufferCount =2;
sc_desc.SampleDesc.Count =1;
sc_desc.AlphaMode =DXGI_ALPHA_MODE_UNSPECIFIED; //DXGI_ALPHA_MODE_PREMULTIPLIED;
sc_desc.Scaling =DXGI_SCALING_NONE; //DXGI_SCALING_STRETCH;
// pDXGI_Factory->CreateSwapChainForComposition(pDXGI_Device, &sc_desc, NULL, &pDXGI_SwapChain);
pDXGI_Factory->CreateSwapChainForHwnd(pDXGI_Device, _hwnd, &sc_desc, NULL, NULL, &pDXGI_SwapChain);
// Create DC_Target
pD2D_Device->CreateDeviceContext(D2D1_DEVICE_CONTEXT_OPTIONS_NONE, reinterpret_cast<ID2D1DeviceContext **>(&pDXGI_DC));
IDXGISurface2 *sc_surface;
pDXGI_SwapChain->GetBuffer(0, __uuidof(IDXGISurface2), reinterpret_cast<void **>(&sc_surface));
D2D1_BITMAP_PROPERTIES1 prop{};
prop.pixelFormat.alphaMode =D2D1_ALPHA_MODE_PREMULTIPLIED;
prop.pixelFormat.format =DXGI_FORMAT_B8G8R8A8_UNORM;
prop.bitmapOptions =D2D1_BITMAP_OPTIONS_TARGET| D2D1_BITMAP_OPTIONS_CANNOT_DRAW;
pDXGI_DC->CreateBitmapFromDxgiSurface(sc_surface, &prop, &Surface_Bitmap);
sc_surface->Release();
pDXGI_DC->SetTarget(Surface_Bitmap);
// Create DComp
/*
DCompositionCreateDevice(pDXGI_Device, __uuidof(IDCompositionDevice), reinterpret_cast<void **>(&pDComp_Device));
pDComp_Device->CreateTargetForHwnd(hwnd, TRUE, &pDComp_Target);
pDComp_Device->CreateVisual(&pDComp_Visual);
pDComp_Visual->SetContent(pDXGI_SwapChain);
pDComp_Target->SetRoot(pDComp_Visual);
pDComp_Device->Commit();
*/
}
void MyWin::ReleaseSwapChain()
{
if(pDXGI_SwapChain!=NULL) pDXGI_SwapChain->Release();
if(pDXGI_DC!=NULL) pDXGI_DC->Release();
if(pDComp_Device!=NULL) pDComp_Device->Release();
if(pDComp_Target!=NULL) pDComp_Target->Release();
if(pDComp_Visual!=NULL) pDComp_Visual->Release();
if(Surface_Bitmap!=NULL) Surface_Bitmap->Release();
}
WICによるpngの画像ファイル読み込み用
IWICBitmapSource *CreateWICBITMAPfromFile(char *filename)
{
IWICBitmapSource *pWIC_BS=NULL;
IStream *pIStream;
HRESULT hr=SHCreateStreamOnFile(filename, STGM_READ, &pIStream);
if(hr==S_OK){
IWICBitmapDecoder *pDecoder=NULL;
IWICBitmapFrameDecode *pDecodedFrame=NULL;
pWIC_Factory->CreateDecoderFromStream(pIStream, NULL, WICDecodeMetadataCacheOnLoad, &pDecoder);
pDecoder->GetFrame(0, &pDecodedFrame);
WICConvertBitmapSource(GUID_WICPixelFormat32bppPBGRA, pDecodedFrame, &pWIC_BS);
pDecodedFrame->Release();
pDecoder->Release();
pIStream->Release();
}
return pWIC_BS;
}
// MainWindow/ChildWindows
HWND hwndMain;
HWND hwndImgL, hwndImgR, hwndBtn1, hwndBtn2;
# define IMAGE_WIDTH 128
# define IMAGE_HEIGHT 128
MyWin mywinL, mywinR;
LONG_PTR __stdcall WndProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
{
switch(msg){
case WM_COMMAND:
switch(LOWORD(wparam)){
case ID_BTN1:
{
}
break;
case ID_BTN2:
{
}
break;
}
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hwnd, msg, wparam, lparam);
}
return 0;
}
# pragma comment(linker, "/subsystem:\"WINDOWS\"")
int __stdcall WinMain(HINSTANCE, HINSTANCE, LPSTR, INT)
{
bool UseConsole=true;
// ShowConsole
if(UseConsole==true){ AllocConsole(); freopen("CONIN$", "r", stdin); freopen("CONOUT$", "w", stdout); }
// Initialize App
hInstance =GetModuleHandle(NULL);
GetModuleFileName(NULL, HomeFolderName, MAX_PATH); PathRemoveFileSpec(HomeFolderName);
CoInitialize(NULL);
// create DirectX factories
CreateDXGIFactory2(0, __uuidof(IDXGIFactory2), reinterpret_cast<void **>(&pDXGI_Factory));
D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &pD2D_Factory);
CoCreateInstance(CLSID_WICImagingFactory, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pWIC_Factory));
// create DirectX Devices
D3D11CreateDevice(NULL, D3D_DRIVER_TYPE_HARDWARE, 0, D3D11_CREATE_DEVICE_BGRA_SUPPORT,
NULL, 0, D3D11_SDK_VERSION, &pD3D_Device, NULL, &pD3D_DC);
pD3D_Device->QueryInterface(IID_PPV_ARGS(&pDXGI_Device));
pD2D_Factory->CreateDevice(pDXGI_Device, &pD2D_Device);
D3D_DeviceRT=CreateDirect3DDevice(pDXGI_Device);
// load Resources with temporary D2D_DC
char filename[MAX_PATH]={};
sprintf(filename, "%s\\test.png", HomeFolderName);
if(PathFileExists(filename)==TRUE){
printf("load image %s\n", filename);
IWICBitmapSource *pWIC_BitmapSource=CreateWICBITMAPfromFile(filename);
if(pWIC_BitmapSource!=NULL){
ID2D1DeviceContext *pD2D_DCtemp;
pD2D_Device->CreateDeviceContext(D2D1_DEVICE_CONTEXT_OPTIONS_NONE, reinterpret_cast<ID2D1DeviceContext **>(&pD2D_DCtemp));
pD2D_DCtemp->CreateBitmapFromWicBitmap(pWIC_BitmapSource, &Image_Bitmap);
pD2D_DCtemp->Release();
pWIC_BitmapSource->Release();
}
}else{
printf("image(%s) not found\n", filename);
ID2D1DeviceContext *pD2D_DCtemp;
pD2D_Device->CreateDeviceContext(D2D1_DEVICE_CONTEXT_OPTIONS_NONE, reinterpret_cast<ID2D1DeviceContext **>(&pD2D_DCtemp));
unsigned char *imbuf=(unsigned char *)malloc(IMAGE_WIDTH*IMAGE_HEIGHT*4);
for(int i=0; i<IMAGE_WIDTH*IMAGE_HEIGHT; i++){
*(imbuf+i*4+0)=0x00; // B
*(imbuf+i*4+1)=0xff; // G
*(imbuf+i*4+2)=0x00; // R
*(imbuf+i*4+3)=0xff; // A
}
pD2D_DCtemp->CreateBitmap(D2D1::SizeU(IMAGE_WIDTH, IMAGE_HEIGHT),
imbuf, IMAGE_WIDTH*4,
D2D1::BitmapProperties1(D2D1_BITMAP_OPTIONS_TARGET,
D2D1::PixelFormat(DXGI_FORMAT_B8G8R8A8_UNORM, D2D1_ALPHA_MODE_PREMULTIPLIED)),
&Image_Bitmap);
free(imbuf);
pD2D_DCtemp->Release();
}
// CreateWindow
WNDCLASS wc{};
wc.lpfnWndProc =WndProc;
wc.hInstance =hInstance;
wc.lpszClassName ="MyTest_Class";
ATOM atom=RegisterClass(&wc);
hwndMain=CreateWindow(MAKEINTATOM(atom), "", WS_OVERLAPPEDWINDOW,
0, 0, 400, 180, NULL, NULL, hInstance, NULL);
hwndBtn1=CreateWindow("BUTTON", "test1", WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON,
280, 6, 80, 22, hwndMain, (HMENU)ID_BTN1, hInstance, NULL);
hwndBtn2=CreateWindow("BUTTON", "test2", WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON,
280, 30, 80, 22, hwndMain, (HMENU)ID_BTN2, hInstance, NULL);
hwndImgL=CreateWindow("STATIC", "", WS_CHILD| WS_VISIBLE| SS_BLACKFRAME,
10, 6, IMAGE_WIDTH, IMAGE_HEIGHT, hwndMain, (HMENU)ID_IMGL, hInstance, NULL);
hwndImgR=CreateWindow("STATIC", "", WS_CHILD| WS_VISIBLE| SS_BLACKFRAME,
140, 6, IMAGE_WIDTH, IMAGE_HEIGHT, hwndMain, (HMENU)ID_IMGR, hInstance, NULL);
mywinL.CreateSwapChain(hwndImgL, IMAGE_WIDTH, IMAGE_HEIGHT);
mywinR.CreateSwapChain(hwndImgR, IMAGE_WIDTH, IMAGE_HEIGHT);
ShowWindow(hwndMain, SW_SHOW);
UpdateWindow(hwndMain);
// MessageLoop
MSG msg;
for(;;){
if(PeekMessage(&msg, nullptr, 0, 0, PM_REMOVE)!=0){ // ==0: no message !=0: has message
if(msg.message==WM_QUIT) break;
if((msg.message==WM_KEYDOWN)&&(msg.wParam == VK_ESCAPE)){ PostQuitMessage(0); continue; }
DispatchMessage(&msg);
}
if(mywinL.pDXGI_DC!=NULL){
if(Image_Bitmap!=NULL){
mywinL.pDXGI_DC->BeginDraw();
mywinL.pDXGI_DC->SetTransform(D2D1::Matrix3x2F::Identity());
mywinL.pDXGI_DC->Clear(D2D1::ColorF(D2D1::ColorF::Black));
mywinL.pDXGI_DC->DrawImage(Image_Bitmap, D2D1::Point2F(0, 0), D2D1::RectF(0.f, 0.f, (float)IMAGE_WIDTH, (float)IMAGE_HEIGHT),
D2D1_INTERPOLATION_MODE_LINEAR, D2D1_COMPOSITE_MODE_SOURCE_OVER);
mywinL.pDXGI_DC->EndDraw();
mywinL.pDXGI_SwapChain->Present(1, 0);
}
}
}
// UnInitialize
mywinL.ReleaseSwapChain();
mywinR.ReleaseSwapChain();
if(Image_Bitmap!=NULL) Image_Bitmap->Release();
if(pD3D_DC!=NULL) pD3D_DC->Release();
if(pD3D_Device!=NULL) pD3D_Device->Release();
if(pDXGI_Device!=NULL) pDXGI_Device->Release();
if(pD2D_Device!=NULL) pD2D_Device->Release();
if(pDXGI_Factory!=NULL) pDXGI_Factory->Release();
if(pD2D_Factory!=NULL) pD2D_Factory->Release();
if(pWIC_Factory!=NULL) pWIC_Factory->Release();
UnregisterClass(MAKEINTATOM(atom), hInstance);
CoUninitialize();
if(UseConsole==true){ system("pause"); FreeConsole(); }
return 0;
}
まぁこんな感じ。たった1枚の画像を表示するにも長ったらしくてめんどくさいですね><
WinRTのウィンドウキャプチャ
以下を追記していきます。下のインライン関数はScreenCaptureforHWNDのヘッダーファイルからのコピペです。
// WinRT
# include <unknwn.h>
# include <winrt/base.h>
# include <winrt/Windows.Foundation.h>
# include <winrt/Windows.System.h>
# include <winrt/Windows.Graphics.DirectX.Direct3d11.h>
# include <winrt/Windows.Graphics.Capture.h>
# include <Windows.Graphics.Directx.Direct3d11.interop.h>
# include <Windows.Graphics.Capture.Interop.h>
# pragma comment(lib, "windowsapp.lib")
namespace winrt
{
using namespace Windows;
using namespace Windows::Foundation;
using namespace Windows::System;
using namespace Windows::Graphics;
using namespace Windows::Graphics::Capture;
using namespace Windows::Graphics::DirectX;
using namespace Windows::Graphics::DirectX::Direct3D11;
}
// copy from ScreenCaptureforHWND/*.interop.h ///////////////////////////////////////////////////////////////
extern "C"
{
HRESULT __stdcall CreateDirect3D11DeviceFromDXGIDevice(::IDXGIDevice* dxgiDevice, ::IInspectable** graphicsDevice);
HRESULT __stdcall CreateDirect3D11SurfaceFromDXGISurface(::IDXGISurface* dgxiSurface, ::IInspectable** graphicsSurface);
}
struct __declspec(uuid("A9B3D012-3DF2-4EE3-B8D1-8695F457D3C1"))
IDirect3DDxgiInterfaceAccess : ::IUnknown
{
virtual HRESULT __stdcall GetInterface(GUID const& id, void** object) = 0;
};
inline auto CreateDirect3DDevice(IDXGIDevice* dxgi_device)
{
winrt::com_ptr<::IInspectable> d3d_device;
winrt::check_hresult(CreateDirect3D11DeviceFromDXGIDevice(dxgi_device, d3d_device.put()));
return d3d_device.as<winrt::Windows::Graphics::DirectX::Direct3D11::IDirect3DDevice>();
}
inline auto CreateDirect3DSurface(IDXGISurface* dxgi_surface)
{
winrt::com_ptr<::IInspectable> d3d_surface;
winrt::check_hresult(CreateDirect3D11SurfaceFromDXGISurface(dxgi_surface, d3d_surface.put()));
return d3d_surface.as<winrt::Windows::Graphics::DirectX::Direct3D11::IDirect3DSurface>();
}
template <typename T>
auto GetDXGIInterfaceFromObject(winrt::Windows::Foundation::IInspectable const& object)
{
auto access = object.as<IDirect3DDxgiInterfaceAccess>();
winrt::com_ptr<T> result;
winrt::check_hresult(access->GetInterface(winrt::guid_of<T>(), result.put_void()));
return result;
}
inline auto CreateCaptureItemForWindow(HWND hwnd)
{
auto activation_factory = winrt::get_activation_factory<winrt::Windows::Graphics::Capture::GraphicsCaptureItem>();
auto interop_factory = activation_factory.as<IGraphicsCaptureItemInterop>();
winrt::Windows::Graphics::Capture::GraphicsCaptureItem item = { nullptr };
interop_factory->CreateForWindow(hwnd, winrt::guid_of<ABI::Windows::Graphics::Capture::IGraphicsCaptureItem>(), reinterpret_cast<void**>(winrt::put_abi(item)));
return item;
}
でキャプチャーの本体。オートでキャプチャーするか、手動で1枚づつキャプチャーするか選べるようにしてます。
// WinRT_Capture
winrt::Direct3D11CaptureFramePool capt_framepool { nullptr };
winrt::GraphicsCaptureItem capt_item { nullptr };
winrt::GraphicsCaptureSession capt_session { nullptr };
winrt::Direct3D11CaptureFramePool::FrameArrived_revoker capt_frame_arrived;
bool capt_automode=false;
bool CaptWinRT_onFrameArrived(IDXGISwapChain1 *swapchain,
winrt::Direct3D11CaptureFramePool const& sender, winrt::IInspectable const& args =nullptr)
{
winrt::Direct3D11CaptureFrame capt_frame =sender.TryGetNextFrame();
if(capt_frame==nullptr) return false;
DXGI_SWAP_CHAIN_DESC1 sc_desc{};
swapchain->GetDesc1(&sc_desc);
D3D11_BOX src_region{};
src_region.left =0;
src_region.right =sc_desc.Width;
src_region.top =0;
src_region.bottom =sc_desc.Height;
src_region.front =0;
src_region.back =1;
winrt::SizeInt32 c_size =capt_frame.ContentSize();
auto access =capt_frame.Surface().as<IDirect3DDxgiInterfaceAccess>();
ID3D11Texture2D *texture_src;
access->GetInterface(winrt::guid_of<ID3D11Texture2D>(), reinterpret_cast<void **>(&texture_src));
ID3D11Texture2D *texture_dst;
swapchain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&texture_dst);
pD3D_DC->CopySubresourceRegion(texture_dst, 0, 0, 0, 0, texture_src, 0, &src_region);
texture_dst->Release();
texture_src->Release();
capt_frame.Close();
if(capt_automode==true) swapchain->Present(1, 0);
return true;
}
bool CaptWinRT_Start(MyWin wDst, HWND hwndSrc, bool useOnFrameArrived, bool free_threaded=true)
{
// create capture item for window
capt_item=CreateCaptureItemForWindow(hwndSrc);
if(capt_item==nullptr) return false;
// create frame pool
winrt::SizeInt32 c_size =capt_item.Size(); // c_size.Width, c_size.Height
if(free_threaded){
capt_framepool=winrt::Direct3D11CaptureFramePool::CreateFreeThreaded(D3D_DeviceRT,
winrt::DirectXPixelFormat::B8G8R8A8UIntNormalized, 1, c_size);
}else{
capt_framepool=winrt::Direct3D11CaptureFramePool::Create(D3D_DeviceRT,
winrt::DirectXPixelFormat::B8G8R8A8UIntNormalized, 1, c_size);
}
if(useOnFrameArrived==true){
capt_frame_arrived=capt_framepool.FrameArrived(winrt::auto_revoke, std::bind(CaptWinRT_onFrameArrived, wDst.pDXGI_SwapChain, _1, _2));
capt_automode=true;
printf("capture auto\n");
}else{
capt_automode=false;
printf("capture manual\n");
}
// start capture
capt_session=capt_framepool.CreateCaptureSession(capt_item);
capt_session.IsCursorCaptureEnabled(true);
capt_session.StartCapture();
return true;
}
void CaptWinRT_Stop()
{
printf("capture stop\n");
if(capt_session!=nullptr) { if(capt_automode==true) capt_frame_arrived.revoke(); capt_session=nullptr; }
if(capt_framepool!=nullptr) { capt_framepool.Close(); capt_framepool=nullptr; }
if(capt_item!=nullptr) { capt_item=nullptr; }
}
そして呼び出し側に組み込み。
case WM_COMMAND:
switch(LOWORD(wparam)){
case ID_BTN1:
{
HWND hwndTarget=hwndMain;
if(capt_session==nullptr) CaptWinRT_Start(mywinR, hwndTarget, false); // capture-manual
else CaptWinRT_Stop();
}
break;
case ID_BTN2:
{
HWND hwndTarget=hwndMain;
if(capt_session==nullptr) CaptWinRT_Start(mywinR, hwndTarget, true); // capture-auto
else CaptWinRT_Stop();
}
break;
}
break;
// MessageLoop
MSG msg;
for(;;){
if(PeekMessage(&msg, nullptr, 0, 0, PM_REMOVE)!=0){ // ==0: no message !=0: has message
if(msg.message==WM_QUIT) break;
if((msg.message==WM_KEYDOWN)&&(msg.wParam == VK_ESCAPE)){ PostQuitMessage(0); continue; }
DispatchMessage(&msg);
}
if(mywinL.pDXGI_DC!=NULL){
if(Image_Bitmap!=NULL){
mywinL.pDXGI_DC->BeginDraw();
mywinL.pDXGI_DC->SetTransform(D2D1::Matrix3x2F::Identity());
mywinL.pDXGI_DC->Clear(D2D1::ColorF(D2D1::ColorF::Black));
mywinL.pDXGI_DC->DrawImage(Image_Bitmap, D2D1::Point2F(0, 0), D2D1::RectF(0.f, 0.f, (float)IMAGE_WIDTH, (float)IMAGE_HEIGHT),
D2D1_INTERPOLATION_MODE_LINEAR, D2D1_COMPOSITE_MODE_SOURCE_OVER);
mywinL.pDXGI_DC->EndDraw();
mywinL.pDXGI_SwapChain->Present(1, 0);
}
}
if(mywinR.pDXGI_DC!=NULL){
if((capt_automode==false)&&(capt_session!=nullptr)&&(capt_framepool!=nullptr)){
if(CaptWinRT_onFrameArrived(mywinR.pDXGI_SwapChain, capt_framepool)==true){
mywinR.pDXGI_SwapChain->Present(1, 0);
}
}
}
}
この、「あなた、キャプチャー(盗撮)されちゃってますよ~」をしめす黄色い枠、なんとかならんかね?
あと、子ウィンドウ同士の転送は無理っすか???転送先が子ウィンドウってのは問題ないけど(GPUテクスチャ間のコピーになるから当たり前か)。
テクスチャの幅って16の倍数だったっけとか、コンポジション通さないで表示する場合、DXGI_ALPHA_MODE_PREMULTIPLIED
は効かないとか色々と地雷はあるんで、このサンプルでいじって勉強します。。。
追記:) 2021.06.17
よくよくMSのマニュアルを見てみると、枠を消すプロパティがありました^^;
GraphicsCaptureSession.IsBorderRequiredってやつですね。手動での設定経由???
でも動かない><
あー、SDKのバージョンが低かったのね、とSDKのバージョンを上げてみたり、保留してたWin10のバージョンを21H1にしてみたりしたんですが、うまく動いてくれない。
ぐぐってみると、OBSのgitソースがヒットしました。同じように処理してる!!!
そこから、UniversalAPIContractのバージョンチェック関数と、IsBorderRequiredのサポートチェック関数をコピペして確認することにしてみました。
BOOL winrt_capture_supported()
try{
return winrt::ApiInformation::IsApiContractPresent(L"Windows.Foundation.UniversalApiContract", 12);
}catch (const winrt::hresult_error &err){
printf("winrt_capture_supported (0x%08X): %ls", (unsigned int)err.to_abi(), err.message().c_str());
return false;
}catch (...){
printf("winrt_capture_supported (0x%08X)", (unsigned int)winrt::to_hresult());
return false;
}
bool winrt_capture_border_toggle_supported()
try{
return winrt::ApiInformation::IsPropertyPresent(L"Windows.Graphics.Capture.GraphicsCaptureSession", L"IsBorderRequired");
}catch (const winrt::hresult_error &err){
printf("winrt_capture_border_toggle_supported (0x%08X): %ls", (unsigned int)err.to_abi(), err.message().c_str());
return false;
}catch (...){
printf("winrt_capture_border_toggle_supported (0x%08X)", (unsigned int)winrt::to_hresult());
return false;
}
結果、UniversalApiContract 12
は否 (引数10までは通った)、当然IsBorderRequired
もなし。。。
うーん、SDKのバージョンは20348
UniversalApiContractもC:\Program Files (x86)\Windows Kits\10\References\10.0.20348.0\Windows.Foundation.UniversalApiContract\12.0.0.0
があるんだけどなぁ。。。
で前述のOBS、ソースからビルドしてはいないんだけど、リリース版はまだYellowBorderの消去には対応してないんですよね。どういう挙動か見たかったのに。。。
まぁ、時間が解決してくれるか。