сделать снимок экрана рабочего стола, созданного с помощью createdesktop api - PullRequest
3 голосов
/ 03 января 2011

Я использую API createdesktop для создания рабочего стола, и я хотел бы сделать снимок экрана или отправить мышь / клавиатуру ввода без отображения рабочего стола пользователю.

Ответы [ 2 ]

6 голосов
/ 03 января 2011

Короткий ответ, который я нашел, это то, что вы не можете. Вы не можете сделать снимок экрана неактивного рабочего стола, потому что нет вызовов рисования, потому что нет видимых окон для перерисовки.

Вы можете выполнить вызов SwitchDesktop (), сделать снимок экрана, а затем выполнить SwitchDesktop () обратно. Пользователь не заметит этого, но вы, вероятно, не получите много на скриншоте, потому что за это короткое время окна не успели перерисовать.

Другое дело, что вы должны создать новый поток для вызова SetThreadDesktop (). Если вы используете для этого основной поток, он потерпит неудачу при использовании приложения с графическим интерфейсом. SetThreadDesktop () завершается ошибкой, когда у вас есть окно на текущем рабочем столе.

SysInternals имеет приложение для управления несколькими рабочими столами (например, переключатель рабочего стола linux). Когда вы собираетесь выбрать рабочий стол, чтобы переключиться на него, вы увидите миниатюру рабочего стола. Это миниатюра не является активной, она фиксируется последней известной полной перерисовкой, когда пользователь находится на этом рабочем столе. Короче говоря, если SysInternals не может сделать живой снимок экрана, я сомневаюсь, что кто-либо из нас будет.

Это, конечно, основано на моем собственном исследовании этой особенности. Если бы кто-то действительно заставил это работать, я хотел бы знать, таким образом, я не могу использовать это также!

3 голосов
/ 03 января 2011

Редактировать : Это не сработает для невидимых рабочих столов, я посмотрел свой старый код и понял, что мне это нужно для захвата скриншота активного рабочего стола (которыйбыло , а не 'WinSta0 \ Default'), чтобы получить дескриптор активного рабочего стола пользователя, я использовал OpenInputDesktop.

+ 1 ThivingSix вы правы .

Извините всех за мое недопонимание.


Вам необходимо использовать SetThreadDesktop (если вы создаете рабочий стол с помощью CreateDestkop, у вас есть дескриптор для него, который вы передаете SetThreadDesktop).После переключения рабочего стола на поток вы можете поймать скриншот.Хорошей идеей было бы вернуться к предыдущему рабочему столу для потока (чтобы не «нарушать» другой / будущий код).

var
  lOldDesktop: HDESK;
begin
  lOldDesktop:= GetThreadDesktop(GetCurrentThreadId);
  try
    if not SetThreadDesktop(ADesktop) then // pass handle to your desktop, or dekstop handle obtained from OpenInputDesktop
      {error handle, like RaiseLastOSError or Exit(False)};

    // your screenshot/input/mouse code here

  finally
    if lOldDesktop<> 0 then // GetThreadDesktop can fail (I don't know condition when this GetThreadDesktop(GetCurrentThreadId) could fail)
      SetThreadDesktop(lOldDesktop); // revert thread to previous desktop
  end;
end;

Этот код должен выполняться в неосновном потоке, как указывал ThivingSix, поскольку SetThreadDesktop может завершиться с этимдело.Безопасным способом является создание темы для скриншота.

PS.Я не уверен, что это будет работать с «отправить ввод мыши / клавиатуры» (это должно), но для скриншота работает.

Редактировать :

...