dfm:

object CopyDeskService: TCopyDeskService
  OldCreateOrder = False
  OnCreate = ServiceCreate
  OnDestroy = ServiceDestroy
  AllowPause = False
  DisplayName = 'Copy Desk Service'
  Interactive = True
  Left = 192
  Top = 107
  Height = 150
  Width = 215
end

pas:

unit Main;

interface

uses
  Windows, SysUtils, Classes, Graphics, SvcMgr;

type
  TCopyThread = class(TThread)
  private
    FIndex: DWORD;
    FScrBmp: TBitmap;
  protected
    procedure Execute; override;
  public
    constructor Create; reintroduce;
    destructor Destroy; override;
  end;

TCopyDeskService = class(TService)
    procedure ServiceCreate(Sender: TObject);
    procedure ServiceDestroy(Sender: TObject);
  private
    FCopyThread: TCopyThread;
  public
    function GetServiceController: TServiceController; override;
  end;

var
  CopyDeskService: TCopyDeskService;

implementation

{$R *.DFM}

procedure ServiceController(CtrlCode: DWord); stdcall;
begin
  CopyDeskService.Controller(CtrlCode);
end;

function TCopyDeskService.GetServiceController: TServiceController;
begin
  Result := ServiceController;
end;

procedure TCopyDeskService.ServiceCreate(Sender: TObject);
begin
  FCopyThread := TCopyThread.Create;
end;

procedure TCopyDeskService.ServiceDestroy(Sender: TObject);
begin
  FCopyThread.Terminate;
end;

function SelectHDESK(HNewDesk: HDESK): Boolean; stdcall;
var
  HOldDesk: HDESK;
  dwDummy:  DWORD;
  sName:    array[0..255] of Char;
begin
 Result := False;
  HOldDesk := GetThreadDesktop(GetCurrentThreadId);
  if (not GetUserObjectInformation(HNewDesk, UOI_NAME, @sName[0], 256, dwDummy)) then
  begin
    OutputDebugString('GetUserObjectInformation Failed.');
    Exit;
  end;
  if (not SetThreadDesktop(HNewDesk)) then
  begin
    OutputDebugString('SetThreadDesktop Failed.');
    Exit;
  end;
  if (not CloseDesktop(HOldDesk)) then
  begin
    OutputDebugString('CloseDesktop Failed.');
    Exit;
  end;
  Result := True;
end;

function SelectDesktop(pName: PChar): Boolean; stdcall;
var
  HDesktop: HDESK;
begin
  Result := False;
  if Assigned(pName) then
    HDesktop := OpenDesktop(pName, 0, False,
                          DESKTOP_CREATEMENU or DESKTOP_CREATEWINDOW or
                          DESKTOP_ENUMERATE or DESKTOP_HOOKCONTROL or
                          DESKTOP_WRITEOBJECTS or DESKTOP_READOBJECTS or
                          DESKTOP_SWITCHDESKTOP or GENERIC_WRITE)
  else
    HDesktop := OpenInputDesktop(0, False,
                          DESKTOP_CREATEMENU or DESKTOP_CREATEWINDOW or
                          DESKTOP_ENUMERATE or DESKTOP_HOOKCONTROL or
                          DESKTOP_WRITEOBJECTS or DESKTOP_READOBJECTS or
                          DESKTOP_SWITCHDESKTOP or GENERIC_WRITE);
  if (HDesktop = 0) then
  begin
    OutputDebugString(PChar('Get Desktop Failed: ' + IntToStr(GetLastError)));
    Exit;
  end;
  Result := SelectHDESK(HDesktop);
end;

function InputDesktopSelected: Boolean; stdcall;
var
  HThdDesk: HDESK;
  HInpDesk: HDESK;
  dwError:  DWORD;
  dwDummy:  DWORD;
  sThdName: array[0..255] of Char;
  sInpName: array[0..255] of Char;
begin
  Result := False;
  HThdDesk := GetThreadDesktop(GetCurrentThreadId);
  HInpDesk := OpenInputDesktop(0, False,
                          DESKTOP_CREATEMENU or DESKTOP_CREATEWINDOW or
                          DESKTOP_ENUMERATE or DESKTOP_HOOKCONTROL or
                          DESKTOP_WRITEOBJECTS or DESKTOP_READOBJECTS or
                          DESKTOP_SWITCHDESKTOP);
  if (HInpDesk = 0) then
  begin
    OutputDebugString('OpenInputDesktop Failed.');
    dwError := GetLastError;
    Result := (dwError = 170);
    Exit;
  end;
  if (not GetUserObjectInformation(HThdDesk, UOI_NAME, @sThdName[0], 256, dwDummy)) then
  begin
    OutputDebugString('GetUserObjectInformation HThdDesk Failed.');
    CloseDesktop(HInpDesk);
    Exit;
  end;
  if (not GetUserObjectInformation(HInpDesk, UOI_NAME, @sInpName[0], 256, dwDummy)) then
  begin
    OutputDebugString('GetUserObjectInformation HInpDesk Failed.');
    CloseDesktop(HInpDesk);
    Exit;
  end;
  CloseDesktop(HInpDesk);
  Result := (lstrcmp(sThdName, sInpName) = 0);
end;

procedure CopyScreen(Bmp: TBitmap; out Index: DWORD);
var
  DC: HDC;
begin
  DC := GetDC(0);
  Bmp.Width  := GetSystemMetrics(SM_CXSCREEN);
  Bmp.Height := GetSystemMetrics(SM_CYSCREEN);
  Bmp.Canvas.Lock;
  try
    BitBlt(Bmp.Canvas.Handle, 0, 0, Bmp.Width, Bmp.Height, DC, 0, 0, SRCCOPY);
    Bmp.SaveToFile('j:/p' + IntToStr(Index) + '.bmp');
    Inc(Index);
  finally
    Bmp.Canvas.Unlock;
    ReleaseDC(0, DC);
  end;
end;

constructor TCopyThread.Create;
begin
  FreeOnTerminate := True;
  FScrBmp := TBitmap.Create;
  FScrBmp.PixelFormat := pf8bit;
  FIndex := 0;
  inherited Create(False);
end;

destructor TCopyThread.Destroy;
begin
  FScrBmp.Free;
  FScrBmp := nil;
  inherited;
end;

procedure TCopyThread.Execute;
begin
  while (not Terminated) do
  begin
    if InputDesktopSelected then CopyScreen(FScrBmp, FIndex)
    else if SelectDesktop(nil) then CopyScreen(FScrBmp, FIndex);
    Sleep(3000);
  end;
end;

end.

http://blog.csdn.net/cdlff/article/details/3489941

因为锁定界面后Windows切换到Session0去了,而你的程序运行在当前用户Session.

WTS系API可以帮你,去Sesson0重新运行一个进程截好图后通过IPC返回当前进程就好了.

对了,Session0隔离从Windows Vista开始引入. 另外 2ccc 应该有一个 WSDT 的 单元,可惜 2ccc 不支持内容搜索

http://bbs.2ccc.com/topic.asp?topicid=506628

Delphi的TService的輸入桌面切換(服务程序)(windows登录界面如何截图)(使用了OpenDesktop和GetThreadDesktop等API)的更多相关文章

  1. jQuery - 中文輸入法與KeyDown/KeyPress事件

    最近專案中引用了Telerik ASP.NET擴充元件AutoComplete輸入欄位,測試時發現偶爾會不聽始喚,輸入文字時無法觸發資料查詢,在Javascript Source Code裡反覆追蹤測 ...

  2. Ubuntu 安裝 嘸蝦米 輸入法

    O S : 14.04.1-Ubuntu 加入fcitx開發團隊的repository: sudo add-apt-repository ppa:fcitx-team/nightly sudo apt ...

  3. JS 計算文本域還能輸入多少個字符

    //輸入計數 //count:能輸入的數據總量    function Calculation(v, count) {        var span = $(v).next();        va ...

  4. Windows 小技巧: 變更輸入法順序

    Windows XP 中還是有辦法變更輸入法順序的!!只不過,要動用到 Regedit.exe 這個程式. 執行 Regedit.exe至 HKEY_CURRENT_USER\Keyboard Lay ...

  5. html5 表單輸入類型

    輸入類型有:email,url,number,range,Date pickers(工作機制是什麼),search, 有相關類型的輸入域,會對域進行驗證. 不同的瀏覽器並不一定都支持所有的輸入類型.

  6. [Java] 資料輸入的差異性(System.in、BufferedReader、Scanner)

    一.System.in System.in提供的read方法每次只能讀取一個字節的數據,不實用 二.BufferedReader BufferedReader類位於java.io包中,使用要加上 im ...

  7. 透過手機 App 在 OpenELEC(XBMC)中輸入中文

    這裡介紹如何使用手機 App 在沒有中文輸入法的 OpenELEC(XBMC)中輸入中文字. OpenELEC(XBMC)雖然有內建中文語系,但是卻沒有中文的輸入法,沒辦法直接輸入中文字,這對於一般家 ...

  8. C# DataGridView的單元格中只能輸入數字

    控件類型:DataGridView 控件名稱:dgvGift_Condition 裏面用到的:IsNumeric.NotePastText.RestoreText 等請參見 前一日志“TextBox中 ...

  9. IE網址欄快速輸入網址,“Ctrl+Enter”補齊“.com”

    繁體中文Windows,預設 IE 在網址列輸入 abc,然後按 Ctrl+Enter ,會跳到www.abc.com.tw, 但較常用的連結是www.abc.com,如何修改这一設定呢? 可以透過修 ...

随机推荐

  1. JSpider是一个用Java实现的WebSpider

    JSpider是一个用Java实现的WebSpider,JSpider的执行格式如下: jspider [URL] [ConfigName] URL一定要加上协议名称,如:http://,否则会报错. ...

  2. 进入MFC讲坛的前言(三)

    MFC中的窗口创建及窗口消息映射 我经常碰到有人问我有关窗口创建的问题,他们经常把用HWND描述的系统窗口对象和用CWnd描述的MFC的窗口对象混淆不清.这两者之间是紧密联系在一起的,但是MFC为了自 ...

  3. 凡客副总裁被曝离职:或因IPO受阻|凡客|王春焕|离职_互联网_新浪科技_新浪网

    凡客副总裁被曝离职:或因IPO受阻|凡客|王春焕|离职_互联网_新浪科技_新浪网 凡客副总裁被曝离职:或因IPO受阻 2013年05月07日 00:56   每日经济新闻    我有话说     每经 ...

  4. HDU 4883 TIANKENG’s restaurant (贪心)

    链接:pid=4883">带我学习.带我飞 第一次BC,稳挂,WA n多次.今天又一次做了一下 略挫 #include <iostream> #include <cs ...

  5. Java 找出四位数的全部吸血鬼数字 基础代码实例

    /**  * 找出四位数的全部吸血鬼数字  * 吸血鬼数字是指位数为偶数的数字,能够由一对数字相乘而得到,而这对数字各包括乘积的一半位数的数字,当中从最初的数字中选取的数字能够随意排序.  * 以两个 ...

  6. 第一次PS练习

    嘿嘿,自己第一次的PS,虽然把在大神眼里是小KS,但是了,对我来说值得劲纪念.加油,我会努力的.

  7. PHP - 发送短信

    1.购买服务 我购买的是在百度进行推广的API服务.按照要求进行购买就好,之后获取自己的apikey. 2.将提供的代码修改后集成到项目中: <?php /** * * * 发送短信 * * * ...

  8. linux环境ubuntu: pushd: not found

    编译错误: /bin/sh: 1: pushd: not found的问题 http://www.cnblogs.com/wansui/p/4230869.html 查看原因:进入/bin目录,查看s ...

  9. [转]PostgreSQL事务处理机制

    原文链接:http://blog.chinaunix.net/uid-20726500-id-4040024.html 事务的实现原理可以解读为DBMS采取何种技术确保事务的ACID特性.Postgr ...

  10. Java网络编程:利用apache的HttpClient包进行http操作

    本文介绍如何利用apache的HttpClient包进行http操作,包括get操作和post操作. 一.下面的代码是对HttpClient包的封装,以便于更好的编写应用代码. import java ...