Share via

Windows.Graphics.Capture - delay on source window movement

Alex Chashka 20 Reputation points
2025-11-20T07:27:21.9+00:00

Hi.

I'm using Windows.Graphics.Capture to duplicate a list of top level windows in source application.
I expanded the example given in https://github.com/microsoft/Windows.UI.Composition-Win32-Samples/tree/master/cpp/ScreenCaptureforHWND to handle multiple handles and position them according to source window offset and size.
Captures are positioned via separate SpriteVisual instances in a single root window. Their size and location is updated on an EVENT_OBJECT_LOCATIONCHANGE event of a source window handle.

As long as there is no dragging the source windows the capture works beautifully, but when source window is moved around there is a huge delay in repositioning the corresponding capture. The delay is several seconds long and is proportional to the length of the dragging.

It seems like an inherent property of a Composition framework, but I can't find documentation that would explain/help to overcome this.

Thanks in advance for any clarification.

Windows development | WinUI
0 comments No comments

Answer accepted by question author
  1. Tom Tran (WICLOUD CORPORATION) 4,765 Reputation points Microsoft External Staff Moderator
    2025-11-20T10:35:34.0033333+00:00

    Hi @Alex Chashka ,

    Thanks for sharing your details!

    You're right, I couldn't find a single official Microsoft document that explains why Composition visuals lag during live window dragging or how to fix it. The existing docs cover the individual pieces (Graphics Capture APIs, Composition basics, window messages), but they don’t combine them into a guide for real-time mirroring.

    As far as I can tell, the delay probably happens because EVENT_OBJECT_LOCATIONCHANGE fires slowly and sometimes in batches. It’s great for accessibility, but not for per-frame updates. Also, if your update logic runs on the UI thread, Windows pauses that thread during a drag, which adds more lag.

    I would suggest these workarounds first:


    Use live move messages instead of LOCATIONCHANGE.

    Update your visuals on WM_MOVING (fires repeatedly while dragging), and use WM_ENTERSIZEMOVE / WM_EXITSIZEMOVE to know when drag starts and ends.

    Reference: WM_MOVING


    Make capture independent of the UI thread.

    Create your frame pool with CreateFreeThreaded so frame updates don’t wait for the dispatcher.

    Reference: CreateFreeThreaded


    Get accurate bounds during drag.

    Use DwmGetWindowAttribute with DWMWA_EXTENDED_FRAME_BOUNDS instead of GetWindowRect to avoid invisible borders and “snap” corrections.

    Reference: DWM bounds


    The GitHub sample you linked shows how to capture and display a window, but it doesn’t include live movement logic.

    I also managed to find some related post regarding this issue, please do check it out when you have the time:

    If you are in a hurry, you could report an issue straight to the creator of the example you are referring to at: https://github.com/robmikh/Win32CaptureSample/issues

    Disclaimer: This is a non-Microsoft website. The page appears to be providing accurate, safe information. Watch out for ads on the site that may advertise products frequently classifies as a PUP (Potentially Unwanted Products). Thoroughly research any product advertised on the site before you decide to download and install it.


    I hope my suggestions help! If you have any question, please feel free to comment below. I'll be happy to help!

    1 person found this answer helpful.
    0 comments No comments

2 additional answers

Sort by: Most helpful
  1. Deleted

    This answer has been deleted due to a violation of our Code of Conduct. The answer was manually reported or identified through automated detection before action was taken. Please refer to our Code of Conduct for more information.


    Comments have been turned off. Learn more

  2. Alex Chashka 20 Reputation points
    2025-11-23T14:30:51.5766667+00:00

    @Tom Tran (WICLOUD CORPORATION) thank you so much for the response. CreateFreeThreaded seems to improve this drastically. To the point of fact, I have an alternative implementation based on DwmAPI.DwmRegisterThumbnail

    The movement updates are implemented there through the same EVENT_OBJECT_LOCATIONCHANGE hook and it captures the same source application. The movements are smooth there, virtually without any visible delay at all. It obviously handles the same amount of events and uses the same GetWindowRect internally. It had other issues so I decided to try something more modern.

    For some reason, DwmAPI.DwmUpdateThumbnailProperties is so much lighter than the

    SpriteVisual v.Offset() = newOffsetValue;
    SpriteVisual v.Size() = newSizeValue;

    that when using the latter, over the same amount of the events the whole thing becomes shaky even when doing this not on the queue.


Your answer

Answers can be marked as 'Accepted' by the question author and 'Recommended' by moderators, which helps users know the answer solved the author's problem.