虚拟桌面原理及实现
blog: http://blog.csdn.net/A00553344/archive/2009/02/02/3858216.aspx文章作者:不赖猴 2009-02-02一、为什么要使用虚拟桌面。场景一、上班的时候,我们经常会趁老板不注意,去一些工作时间不应该去的网站,或是运行一些不应该运行的程序,比如一些聊天工具,小游戏,股票软件等等。而且,经常会打开一大堆。当老板或其他同事来到你的桌前的时候,你正在手忙脚乱的关着这些程序,而且,还来不及保存想要保存的东西。场景二、在你给别人做讲演的时候,需要在电脑桌面上展示很多资料。当然一个桌面经常是远远不够展示的,而且,需要经常的切换画面,由于打开的资料太多,每次还的任务栏里找上一阵。很影响讲演的流畅性。虚拟桌面程序就是用来解决以上的问题。场景一、你可以用虚拟桌面程序同时生成多个桌面。一个桌面打开着你工作的资料,程序等等。一个桌面打开着你的聊天工具及一些你不想别人看到的东西。当然你还可以用一个桌面放一些你想访问的网站啊,股票信息啊等等。剩下的只是简单的按一下快捷键来切换不同的桌面。场景二、同场景一,你可以用虚拟桌面程序生成多个桌面,把要讲演的资料提前分配到多个桌面。剩下的只是简单的按一下快捷键来切换不同的桌面。二、虚拟桌面实现原理1. 原理概况每次开机的时候,我就创建多个桌面,然后定时监控快捷键(Ctrl+数字键),如果有快捷键被按下,就切换到数字键对应编号的桌面。2.什么是桌面?每一个运行着Window NT 的系统中都有一个Window 工作站对象,这个对象是安全对象的第一层,是所有用户安全对象的继承之源,每一个Window 工作站对象可以拥有一些桌面对象,每一个桌面都拥有一个窗口链。窗口链里存放着显示在所属桌面的各种窗口。Window NT 用了两个桌面窗口对象,一个是用来处理登陆界面、屏蔽、锁住工作站等,一个是我们登陆之后进来操作的窗口了。Window NT通过"explorer.exe"进程来管理这个桌面对象。这就是为什么我们在任务管理器里杀掉"explorer.exe",我们的桌面就会消失的原因。3.创建一个桌面。function CreateANewDesktop(DesktopName: string): Boolean;var sin   : TStartupInfo; pin   : TProcessInformation; hDesk : HDESK;begin result := false; hDesk := CreateDesktop(PChar(DesktopName),nil,nil,0,MAXIMUM_ALLOWED,nil); try   FillChar(sin,SizeOf(sin),0);   sin.cb := SizeOf(sin);   sin.lpDesktop := PChar(DesktopName);     CreateProcess(PChar(WindowDirectory+'explorer.exe'),nil,nil,nil,False,0,nil,nil,sin,pin);     Sleep(2000);     result := true;  finally     CloseDesktop(Desk);  end;end;4.查询当前已经存在的桌面。枚举桌面的API是EnumDesktops.BOOL EnumDesktops(
  HWINSTA hwinsta,                            // 当前的WindowsStation句柄
  DESKTOPENUMPROC lpEnumFunc,       // 回调函数,由系统调用。
  LPARAM lParam                                //传递给回调函数的参数指针
);
通常我们定义个一回调函数,定义一个全局TStringList类对象,在回调函数里将枚举到的桌面的名称增加到TStringList里。var   sttopList : TStringList;function EnumDesktopProc(Desktop: LPTSTR; Param: LParam): Boolean; stdcall;
begin
  if (Desktop<>'Winlogon') and (Desktop<>'Disconnect') then       DesktpList.Add(DeskTop);  result := True;
end;procedure EnumerateDesktops;
begin
   EnumDesktops(GetProcessWindowStation, @EnumDesktopProc, nil);
end;5.切换桌面。procedure DesktopSwitch(DesktopName: String);
var hDesk: HDESK;
begin
  hDesk:=OpenDesktop(PChar(DesktopName), DF_ALLOWOTHERACCOUNTHOOK, False, MXIMUM_ALLOWED);
  Sleep(100);
  SwitchDesktop(hDesk);
  CloseDesktop(hDesk);
end;三、结束语你可以把这个虚拟桌面程序做成一个服务,每次开机就自动加载。这样,你就可以每次都拥有多个桌面了。附件release.rar是运行程序,无须安装。
http://d.download.csdn.net/down/985557/A00553344

解决方案 »

  1.   

    猴哥,咋才有20分  分太少,hoha
      

  2.   

    呵呵。以前见过。也是delphi的。
      

  3.   

    招聘启示
    本公司是一家大型的信息专业网站,公司09年为了开拓全国业务需要,现急需招聘具备良好的团队合作精神,责任感强,善于沟通,能够承受压力的程序员3-5名,职位要求如下:(一)Delphi程序员
    1、三年以上Delphi开发经验,精通Delphi+SQL Server编程, 熟悉SQ LServer数据库;
    2、从事过行业管理信息系统开发全过程,具有一定的软件工程思想;
    3、有电子商务、国际货运代理、仓储、物流EDICRM软件开发经验优。
    (二)C#程序员
    1.二年以上C#软件研发工作经验;
    2.有软件体系结构设计经验,有很强的C#编码技能;
    3.精通XML、MSDTC、COM+/COM、Web Services和.net framework;
    4.熟练掌握Oracle、SQL Server等大型数据库系统,熟悉数据库设计、调优及SQL存储过程的编写。
    (三)网站设计程序员
    1. 美术、计算机二年以上工作经验;
    2. 熟悉SQL数据,精通ASP.NET编程进行后台的开发,有一定的编辑经验,能够独立完成项目方案的设计;
    3. 精通网页设计和平面设计的相关软件,如Dreamweaver、Photoshop、Flash、Coredraw等 ;
    4.文字功底好,有丰富的想象策划能力,能独立完成大型网站的建设需求/策划方案。 工作地点:河南       工作方式:全职         福利待遇:面议(不会低于你的期望值)联系方式:冯先生 13603728111
      

  4.   

    注册成系统服务不难,建一个服务工程就可以了。楼主,请教一点:建立多个虚拟桌面后,如果返回最原始的那个桌面上?这点在你的EXE上有这个功能,但你的源码中并没有给出。
      

  5.   


    因为你是在当前桌面建的,只要你不切换,是不会到其他桌面去的.而且当前的桌面的名字叫'Default',你还可以通过SwitchToDesktop('Default')返回到原始桌面.
      

  6.   

    用EnumDesktops就能枚举出各个桌面的名称了,用Desktop读取,第1个就是default
      

  7.   

    N年前就有人发过了.我发个汇编的.;该程序功能为创建一个虚拟桌面,可以按CTRL + 1 和 CTRL + 2 在原先的桌面和  ;
    ;新建桌面之间切换,按CTRL + 3关闭程序;你可以在不同的桌面做不同的事情。   ;
    ;本代码根据网络上流传的C++代码改编(作者无从考证),非我独创。              ;
    ;你可以任意修改,使用此代码。此代码由http://www.aogosoft.com/提供下载     ;
    ;Author: xiep                                                             ;
    ;Email : [email protected]                                                 ;
    ;Wwb   : http://hi.baidu.com/xiep_                                        ;            .386
                .model flat,stdcall 
                option casemap:none 
    include     windows.inc 
    include     kernel32.inc 
    include     user32.inc
    includelib  kernel32.lib 
    includelib  user32.lib             .data 
    hInstance dd 0
    hWinMain dd 0
    hNewDesktop   dd 0
    hCurrentDesktop dd 0
    szNewDesktop    db  "NewDeskTop",0
    szExplorer db "explorer",0
    szClassName  db  "MyClass",0
    CTRL1 EQU 0 ;0 - 0BFFFh
    CTRL2 EQU 1
    CTRL3 EQU 2            .code 
    StartExplore proc  
        LOCAL   @stStartInfo :STARTUPINFO
        LOCAL   @stProcessInfo :PROCESS_INFORMATION    mov     @stStartInfo.cb, SIZEOF STARTUPINFO
        mov     @stStartInfo.lpDesktop, offset szNewDesktop
        invoke  CreateProcess,NULL, addr szExplorer, NULL, NULL, \
         TRUE, NULL, NULL, NULL, addr @stStartInfo, addr @stProcessInfo
        ret
    StartExplore endpSetDesktop proc         
        invoke  GetCurrentThreadId
        invoke  GetThreadDesktop, eax   
        mov     hCurrentDesktop, eax
        mov     hNewDesktop, 0
        invoke  OpenDesktop, addr szNewDesktop, 0, FALSE, 0   ;检查桌面是否已经存在
        .if     !eax
                invoke CloseDesktop, eax ;存在则先关闭
        .endif
        invoke  CreateDesktop, addr szNewDesktop, NULL, NULL, 0, MAXIMUM_ALLOWED, NULL 
        mov     hNewDesktop, eax   
        .if     eax
            invoke SetThreadDesktop, hNewDesktop
            invoke  SwitchDesktop, hNewDesktop
            invoke  StartExplore
        .endif    
        ret
    SetDesktop endp _ProcWinMain proc hWnd, uMsg, wParam, lParam
    mov eax, uMsg
        .if         eax == WM_CLOSE         
            invoke  SwitchDesktop, hCurrentDesktop
            invoke  CloseDesktop, hNewDesktop
            invoke UnregisterHotKey, hWnd, CTRL1      
            invoke  UnregisterHotKey, hWnd, CTRL2
            invoke  UnregisterHotKey, hWnd, CTRL3
    invoke DestroyWindow, hWinMain
    invoke PostQuitMessage, NULL
        .elseif     eax == WM_CREATE
            invoke SetWindowPos, hWnd, HWND_TOPMOST, \
             0, 0, 0, 0, SWP_NOMOVE or SWP_NOSIZE ;窗口置顶
            invoke  RegisterHotKey, hWnd, CTRL1, MOD_CONTROL, 31h ;CTRL + 1
            invoke  RegisterHotKey, hWnd, CTRL2, MOD_CONTROL, 32h ;CTRL + 2
            invoke  RegisterHotKey, hWnd, CTRL3, MOD_CONTROL, 33h ;CTRL + 3
            invoke  SetDesktop
        .elseif     eax == WM_HOTKEY
            .if         wParam == CTRL1
                invoke  SwitchDesktop, hCurrentDesktop    
            .elseif     wParam == CTRL2  
                invoke  SwitchDesktop, hNewDesktop
            .elseif     wParam == CTRL3  
                invoke  SwitchDesktop, hCurrentDesktop
                invoke  PostQuitMessage, NULL         
            .endif
        .else 
            invoke DefWindowProc, hWnd, uMsg, wParam, lParam
    ret
        .endif  
        xor eax, eax
        ret
    _ProcWinMain endp _WinMain  proc
        local  @stWndClass:WNDCLASSEX
        local @stMsg:MSG
        
        invoke GetModuleHandle, NULL
        mov hInstance, eax
        invoke RtlZeroMemory, addr @stWndClass, sizeof @stWndClass
        
        invoke LoadCursor, 0, IDC_ARROW
        mov @stWndClass.hCursor, eax
        mov eax, hInstance
        mov @stWndClass.hInstance, eax
        mov @stWndClass.cbSize, sizeof WNDCLASSEX
        mov @stWndClass.lpfnWndProc, offset _ProcWinMain
        mov @stWndClass.hbrBackground, COLOR_WINDOW + 1
        mov @stWndClass.lpszClassName, offset szClassName
        invoke RegisterClassEx, addr @stWndClass
        invoke CreateWindowEx, WS_EX_TOOLWINDOW, addr szClassName,\
         NULL, WS_POPUP or WS_SYSMENU, 0, 0, 0, 0,\
         NULL, NULL, hInstance, NULL ;创建无标题栏的窗口,这样就不会在任务栏显示了
        mov hWinMain, eax
        invoke ShowWindow, hWinMain, SW_SHOWNORMAL
        invoke UpdateWindow, hWinMain
        .while TRUE
         invoke GetMessage, addr @stMsg, NULL, 0, 0
         .break .if eax == 0
         invoke TranslateMessage, addr @stMsg
         invoke DispatchMessage, addr @stMsg
        .endw    
        ret    
    _WinMain  endpstart:
        call _WinMain
        invoke  ExitProcess, NULL
    end        start
      

  8.   

    好像在crtl+3时,有桌面背景会报错
      

  9.   

    [code=BatchFile]
    sc delete 服务名
    [/code]
      

  10.   

    容我不客气的说句,这些代码深究下来不过
    CreateDesktop
    SwitchDesktop
    CloseDesktop
    EnumDesktops
    这么几个API函数,串联一下,加个全局热键就搞定了。
    这并不困难,实际上虚拟桌面最大的难题是如何将一个窗口或者进程从一个桌面切换到另一个,
    以及如何原原本本的讲桌面关闭楼主能把自己的东西共享出来,精神可嘉,但希望可以看到更深层次的研究!
      

  11.   

    如何将一个窗口或者进程从一个桌面切换到另一个
    也不是什么难题,几行代码的事,只不过是不能在GUI线程中处理罢了.关闭桌面,只要将这个桌面里所有的东西关闭完,再去关闭句柄就是了