DirectX11での画像表示(思い出し)とWindowCapture

以下のリンクを見て私もウィンドウキャプチャのアプリを作ってみたくなりました。車輪の再発明ｗ

https://qiita.com/i_saint/items/ad5b0545873d0cff4604

https://github.com/microsoft/Windows.UI.Composition-Win32-Samples/tree/master/cpp/ScreenCaptureforHWND

https://tips.hecomi.com/entry/2021/03/23/230947

なので、詳細は上記リンクを参照してくださいね。
以下、自分用ののメモというか雑記。

###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;
}
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/167175/635c9e56-89c3-cf89-bc8a-830e5f3aaf8f.png)

まぁこんな感じ。たった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```は効かないとか色々と地雷はあるんで、このサンプルでいじって勉強します。。。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/167175/e2a4994e-fbb3-0ce5-c835-b2725bbcf7bf.png)


追記:) 2021.06.17
よくよくMSのマニュアルを見てみると、枠を消すプロパティがありました＾＾；
GraphicsCaptureSession.IsBorderRequiredってやつですね。手動での設定経由？？？
でも動かない＞＜

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/167175/c38e27ee-2dd7-346b-3343-bb84bae66c81.png)

あー、SDKのバージョンが低かったのね、とSDKのバージョンを上げてみたり、保留してたWin10のバージョンを21H1にしてみたりしたんですが、うまく動いてくれない。

ぐぐってみると、OBSのgitソースがヒットしました。同じように処理してる！！！

https://github.com/obsproject/obs-studio/blob/master/libobs-winrt/winrt-capture.cpp

そこから、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の消去には対応してないんですよね。どういう挙動か見たかったのに。。。
まぁ、時間が解決してくれるか。