Skip to content

Commit

Permalink
Add optional captureCursor flag
Browse files Browse the repository at this point in the history
Remove the yellow capture border (thanks to https://github.com/eamon-cai for the tip)
  • Loading branch information
lovettchris committed Jul 20, 2024
1 parent 2f50f1d commit abe940a
Show file tree
Hide file tree
Showing 9 changed files with 44 additions and 22 deletions.
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ build-backend = "setuptools.build_meta"
# project metadata
[project]
name = "wincam"
version = "0.0.4"
version = "0.0.5"
authors = [
{name = "lovettchris"}
]
Expand Down
4 changes: 2 additions & 2 deletions src/ScreenCapture/ScreenCapture.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ extern "C" {
return 0;
}

int __declspec(dllexport) __stdcall StartCapture(int x, int y, int width, int height)
int __declspec(dllexport) __stdcall StartCapture(int x, int y, int width, int height, bool captureCursor)
{
auto mon = FindMonitor(x, y, width, height, false);
if (mon.hmon == nullptr)
Expand All @@ -126,7 +126,7 @@ extern "C" {

RECT bounds = { mon.x, mon.y, mon.x + width, mon.y + height };
m_capture = std::make_unique<SimpleCapture>();
return m_capture->StartCapture(device, item, winrt::Windows::Graphics::DirectX::DirectXPixelFormat::B8G8R8A8UIntNormalized, bounds);
return m_capture->StartCapture(device, item, winrt::Windows::Graphics::DirectX::DirectXPixelFormat::B8G8R8A8UIntNormalized, bounds, captureCursor);

}
catch (winrt::hresult_error const& ex) {
Expand Down
2 changes: 1 addition & 1 deletion src/ScreenCapture/ScreenCapture.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,6 @@

#include <Windows.h>

int WINAPI StartCapture(int x, int y, int width, int height);
int WINAPI StartCapture(int x, int y, int width, int height, bool captureCursor);
void WINAPI StopCapture();
unsigned long long WINAPI ReadNextFrame(char* buffer, unsigned int size);
2 changes: 1 addition & 1 deletion src/ScreenCapture/ScreenCapture.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
<Keyword>Win32Proj</Keyword>
<ProjectGuid>{006df20e-a899-42f1-ad3c-3b29295b7718}</ProjectGuid>
<RootNamespace>ScreenCapture</RootNamespace>
<WindowsTargetPlatformVersion>10.0.19041.0</WindowsTargetPlatformVersion>
<WindowsTargetPlatformVersion>10.0.26100.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
Expand Down
3 changes: 3 additions & 0 deletions src/ScreenCapture/ScreenCapture.vcxproj.filters
Original file line number Diff line number Diff line change
Expand Up @@ -42,4 +42,7 @@
<ItemGroup>
<None Include="packages.config" />
</ItemGroup>
<ItemGroup>
<Natvis Include="$(MSBuildThisFileDirectory)..\..\natvis\wil.natvis" />
</ItemGroup>
</Project>
41 changes: 29 additions & 12 deletions src/ScreenCapture/SimpleCapture.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ namespace util {
winrt::check_hresult(surfaceInterop->QueryInterface(winrt::guid_of<winrt::Windows::UI::Composition::ICompositionSurface>(), winrt::put_abi(surface)));
return surface;
}

}

// since we are requesting B8G8R8A8UIntNormalized
Expand All @@ -99,11 +100,12 @@ SimpleCapture::SimpleCapture()
InitializeCriticalSection(&m_mutex);
}

unsigned int SimpleCapture::StartCapture(
int SimpleCapture::StartCapture(
winrt::IDirect3DDevice const& device,
winrt::GraphicsCaptureItem const& item,
winrt::DirectXPixelFormat pixelFormat,
RECT bounds)
RECT bounds,
bool captureCursor)
{
m_frameId = 0;
m_buffer = nullptr;
Expand Down Expand Up @@ -132,6 +134,21 @@ unsigned int SimpleCapture::StartCapture(
// it on the UI thread.
m_framePool = winrt::Direct3D11CaptureFramePool::CreateFreeThreaded(m_device, m_pixelFormat, 2, m_item.Size());
m_session = m_framePool.CreateCaptureSession(m_item);
if (!m_session.IsSupported())
{
printf("CreateCaptureSession is not supported on this version of Windows.\n");
return -1;
}
m_session.IsCursorCaptureEnabled(captureCursor);

auto session3 = m_session.as<winrt::Windows::Graphics::Capture::IGraphicsCaptureSession3>();
if (session3 != nullptr) {
session3.IsBorderRequired(false);
}
else {
printf("Cannot disable the capture border on this version of windows\n");
}

m_lastSize = m_item.Size();
m_frameArrivedToken = m_framePool.FrameArrived({ this, &SimpleCapture::OnFrameArrived });

Expand Down Expand Up @@ -232,7 +249,7 @@ void SaveBitmap(UCHAR* pixels, D3D11_TEXTURE2D_DESC& desc, int stride) {
__uuidof(wicFactory),
wicFactory.put_void());
if (FAILED(hr)) {
printf("Failed to create instance of WICImagingFactory");
printf("Failed to create instance of WICImagingFactory\n");
return;
}

Expand All @@ -242,7 +259,7 @@ void SaveBitmap(UCHAR* pixels, D3D11_TEXTURE2D_DESC& desc, int stride) {
nullptr,
wicEncoder.put());
if (FAILED(hr)) {
printf("Failed to create BMP encoder");
printf("Failed to create BMP encoder\n");
return;
}

Expand All @@ -255,7 +272,7 @@ void SaveBitmap(UCHAR* pixels, D3D11_TEXTURE2D_DESC& desc, int stride) {

hr = wicStream->InitializeFromFilename(L"d:\\temp\\test.bmp", GENERIC_WRITE);
if (FAILED(hr)) {
printf("Failed to initialize stream from file name");
printf("Failed to initialize stream from file name\n");
return;
}

Expand All @@ -270,27 +287,27 @@ void SaveBitmap(UCHAR* pixels, D3D11_TEXTURE2D_DESC& desc, int stride) {
winrt::com_ptr<IWICBitmapFrameEncode> frameEncode;
wicEncoder->CreateNewFrame(frameEncode.put(), nullptr);
if (FAILED(hr)) {
printf("Failed to create IWICBitmapFrameEncode");
printf("Failed to create IWICBitmapFrameEncode\n");
return;
}

hr = frameEncode->Initialize(nullptr);
if (FAILED(hr)) {
printf("Failed to initialize IWICBitmapFrameEncode");
printf("Failed to initialize IWICBitmapFrameEncode\n");
return;
}

GUID wicFormatGuid = GUID_WICPixelFormat32bppBGRA;

hr = frameEncode->SetPixelFormat(&wicFormatGuid);
if (FAILED(hr)) {
printf("SetPixelFormat failed.");
printf("SetPixelFormat failed.\n");
return;
}

hr = frameEncode->SetSize(desc.Width, desc.Height);
if (FAILED(hr)) {
printf("SetSize(...) failed.");
printf("SetSize(...) failed.\n");
return;
}

Expand All @@ -300,19 +317,19 @@ void SaveBitmap(UCHAR* pixels, D3D11_TEXTURE2D_DESC& desc, int stride) {
desc.Height * stride,
reinterpret_cast<BYTE*>(pixels));
if (FAILED(hr)) {
printf("frameEncode->WritePixels(...) failed.");
printf("frameEncode->WritePixels(...) failed.\n");
}

hr = frameEncode->Commit();
if (FAILED(hr)) {
printf("Failed to commit frameEncode");
printf("Failed to commit frameEncode\n");
return;
}
}

hr = wicEncoder->Commit();
if (FAILED(hr)) {
printf("Failed to commit encoder");
printf("Failed to commit encoder\n");
return;
}
}
Expand Down
5 changes: 3 additions & 2 deletions src/ScreenCapture/SimpleCapture.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,12 @@ class SimpleCapture
SimpleCapture();
~SimpleCapture() { Close(); }

unsigned int StartCapture(
int StartCapture(
winrt::Windows::Graphics::DirectX::Direct3D11::IDirect3DDevice const& device,
winrt::Windows::Graphics::Capture::GraphicsCaptureItem const& item,
winrt::Windows::Graphics::DirectX::DirectXPixelFormat pixelFormat,
RECT bounds);
RECT bounds,
bool captureCursor);

void Close();

Expand Down
2 changes: 1 addition & 1 deletion wincam.egg-info/PKG-INFO
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Metadata-Version: 2.1
Name: wincam
Version: 0.0.4
Version: 0.0.5
Summary: A Python high-performance screenshot library for Windows 10+ using Direct3D11CaptureFramePool.
Author: lovettchris
Project-URL: Homepage, https://github.com/lovettchris/wincam
Expand Down
5 changes: 3 additions & 2 deletions wincam/dxcam.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ class DXCamera(Camera):
which is based on Direct3D11CaptureFramePool. Only one DXCamera can be activate at a time.
See https://learn.microsoft.com/en-us/uwp/api/windows.graphics.capture.direct3d11captureframepool"""

def __init__(self, left: int, top: int, width: int, height: int, fps: int = 30):
def __init__(self, left: int, top: int, width: int, height: int, fps: int = 30, capture_cursor: bool = True):
super().__init__()
if os.name != "nt":
raise Exception("This class only works on Windows")
Expand All @@ -27,6 +27,7 @@ def __init__(self, left: int, top: int, width: int, height: int, fps: int = 30):
self._height = height
self._left = left
self._top = top
self._capture_cursor = capture_cursor
self._throttle = FpsThrottle(fps)
full_path = os.path.realpath(os.path.join(script_dir, "native", "runtimes", "x64", "ScreenCapture.dll"))
if not os.path.exists(full_path):
Expand All @@ -52,7 +53,7 @@ def reset_throttle(self):

def get_bgr_frame(self) -> Tuple[np.ndarray, float]:
if not self._started:
hr = self.lib.StartCapture(self._left, self._top, self._width, self._height)
hr = self.lib.StartCapture(self._left, self._top, self._width, self._height, self._capture_cursor)
if hr <= 0:
raise Exception(f"Failed to start capture, error code {f'{-hr:02x}'}")
self._size = hr
Expand Down

0 comments on commit abe940a

Please sign in to comment.