拟桌面

突然翻到以前的一个小软件,这个软件的作用是创建一个虚拟桌面,并切换到他,这还是在Win7时代时候的了,貌似那时候很多人用这种类似的软件在上班时玩游戏,但是在Win10中加入了虚拟桌面,这类软件不知道怎么样了。

Win10中可以点击任务视图按钮,在最上面就可以创建,(虚拟桌面在Linux操作系统是一个标配,但是在Windows操作系统一直没有此功能,直到Win10才加入这项功能)。Windows编程之虚拟桌面实现_javaWindows编程之虚拟桌面实现_java_02笔记本的话四个手指左右滑动触摸板就可以切换,或者Win + Ctrl + → |←切换。

创建一个虚拟桌面需要CreateDesktop函数,创建出来还需要切换过去,则要使用SwitchDesktop,如果要在虚拟桌面中运行程序,则可以使用CreateProcess,另外创建的新桌面是光秃秃的,并没有桌面图标、桌面壁纸,所以我们要注册一个快捷键,切换过去的时候还要可以切换回来,由于学艺不精,只会点VB,VB注册全局快捷键需要改变默认的窗口过程,然后去判断消息标识是不是WM_HOTKEY,在做相应的判断。

CreateDesktop函数参数

HDESK CreateDesktopA(
 LPCSTR                lpszDesktop,
 LPCSTR                lpszDevice,
 DEVMODEA              *pDevmode,
 DWORD                 dwFlags,
 ACCESS_MASK           dwDesiredAccess,
 LPSECURITY_ATTRIBUTES lpsa
);

lpszDesktops:要创建的桌面的名称。桌面名称不区分大小写,并且不能包含反斜杠字符。

lpszDevice:保留;必须为NULL。

pDevmode:保留;必须为NULL。

dwFlags:此参数可以为零或DF_ALLOWOTHERACCOUNTHOOK,DF_ALLOWOTHERACCOUNTHOOK意思是使在桌面上其他帐户中运行的进程能够在此进程中设置挂钩。

dwDesiredAccess:桌面的权限。

lpsa:指向SECURITY_ATTRIBUTES结构的指针,该结构确定返回的句柄是否可以由子进程继承。如果lpsa为NULL,则不能继承该句柄。

实例

这部分是创建新的桌面,并将默认的窗口过程改成myWindowProc。

其中的GetThreadDesktop用来检索分配给指定线程的桌面的句柄,还有RegisterHotKey注册一个快捷键,当快捷键按下时,窗口过程中会收到WM_HOTKEY消息。


Private Sub Form_Load()
g_hDesktopThreadOld = GetThreadDesktop(App.ThreadID)
RegisterHotKey Me.hWnd, 1, MOD_CONTROL, Asc("Q")
RegisterHotKey Me.hWnd, 2, MOD_CONTROL, Asc("W")
g_hDesktopNameNew = "MyNewDesktop"

g_hDesktopNew = CreateDesktop(g_hDesktopNameNew, vbNullString, ByVal 0&, 0, GENERIC_ALL, ByVal 0&)
SetThreadDesktop g_hDesktopNew
lpOldWinProc = SetWindowLong(Me.hWnd, GWL_WNDPROC, AddressOf myWindowProc)
End Sub

模块中。

这部分主要的逻辑就是判断热键,如果是Ctrl+W,则通过SwitchDesktop 切换到新的桌面,另外通过CreateProcess在新的桌面中打开一个资源管理器(CreateProcess参数中的STARTUPINFOA结构体lpDesktop属性指定新的桌面名称即可),如果是Ctrl+Q则切换到原来桌面。

SwitchDesktop只有一个参数,桌面的句柄,这个句柄由CreateDesktop和 OpenDesktop函数返回。

Public Declare Function GetThreadDesktop Lib "user32" (ByVal dwThread As Long) As Long
Public Declare Function CreateDesktop Lib "user32" Alias "CreateDesktopA" (ByVal lpszDesktop As String, ByVal lpszDevice As String, pDevmode As Long, ByVal dwFlags As Long, ByVal dwDesiredAccess As Long, lpsa As Long) As Long
Public Declare Function SwitchDesktop Lib "user32" (ByVal hDesktop As Long) As Long
Public Declare Function SetThreadDesktop Lib "user32" (ByVal hDesktop As Long) As Long
Public Declare Function CloseDesktop Lib "user32" (ByVal hDesktop As Long) As Long
Public Declare Function OpenDesktop Lib "user32" Alias "OpenDesktopA" (ByVal lpszDesktop As String, ByVal dwFlags As Long, ByVal fInherit As Boolean, ByVal dwDesiredAccess As Long) As Long
Public Declare Function RegisterHotKey Lib "user32" (ByVal hWnd As Long, ByVal id As Long, ByVal fsModifiers As Long, ByVal vk As Long) As Long
Public Declare Function SetWindowLong Lib "user32" Alias "SetWindowLongA" (ByVal hWnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long
Public Declare Function CreateProcess Lib "kernel32" Alias "CreateProcessA" (ByVal lpApplicationName As String, ByVal lpCommandLine As String, lpProcessAttributes As Long, lpThreadAttributes As Long, ByVal bInheritHandles As Long, ByVal dwCreationFlags As Long, lpEnvironment As Any, ByVal lpCurrentDriectory As String, lpStartupInfo As STARTUPINFO, lpProcessInformation As PROCESS_INFORMATION) As Long
Public Declare Function CallWindowProc Lib "user32" Alias "CallWindowProcA" (ByVal lpPrevWndFunc As Long, ByVal hWnd As Long, ByVal Msg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long

Public Const CCHDEVICENAME = 32
Public Const CCHFORMNAME = 32

Public Const MOD_CONTROL = &H2
Public Const WM_HOTKEY = &H312
Public Const GWL_WNDPROC = -4

Public Type STARTUPINFO
        cb As Long
        lpReserved As String
        lpDesktop As String
        lpTitle As String
        dwX As Long
        dwY As Long
        dwXSize As Long
        dwYSize As Long
        dwXCountChars As Long
        dwYCountChars As Long
        dwFillAttribute As Long
        dwFlags As Long
        wShowWindow As Integer
        cbReserved2 As Integer
        lpReserved2 As Long
        hStdInput As Long
        hStdOutput As Long
        hStdError As Long
End Type

Public Type PROCESS_INFORMATION
        hProcess As Long
        hThread As Long
        dwProcessId As Long
        dwThreadId As Long
End Type


Public Type DEVMODE
        dmDeviceName As String * CCHDEVICENAME
        dmSpecVersion As Integer
        dmDriverVersion As Integer
        dmSize As Integer
        dmDriverExtra As Integer
        dmFields As Long
        dmOrientation As Integer
        dmPaperSize As Integer
        dmPaperLength As Integer
        dmPaperWidth As Integer
        dmScale As Integer
        dmCopies As Integer
        dmDefaultSource As Integer
        dmPrintQuality As Integer
        dmColor As Integer
        dmDuplex As Integer
        dmYResolution As Integer
        dmTTOption As Integer
        dmCollate As Integer
        dmFormName As String * CCHFORMNAME
        dmUnusedPadding As Integer
        dmBitsPerPel As Long
        dmPelsWidth As Long
        dmPelsHeight As Long
        dmDisplayFlags As Long
        dmDisplayFrequency As Long
End Type

Public Type SECURITY_ATTRIBUTES
        nLength As Long
        lpSecurityDescriptor As Long
        bInheritHandle As Long
End Type

Public Const GENERIC_ALL = &H10000000

Public Const DESKTOP_SWITCHDESKTOP = &H100
Public Const DESKTOP_CREATEMENU = &H4&
Public Const DESKTOP_CREATEWINDOW = &H2&
Public Const DESKTOP_ENUMERATE = &H40&
Public Const DESKTOP_HOOKCONTROL = &H8&
Public Const DESKTOP_JOURNALPLAYBACK = &H20&
Public Const DESKTOP_JOURNALRECORD = &H10&
Public Const DESKTOP_READOBJECTS = &H1&
Public Const DESKTOP_WRITEOBJECTS = &H80&
Public Const DESKTOP_ALL = 511
Public Const MAXIMUM_ALLOWED = &H2000000


Public lpOldWinProc As Long
Public g_hDesktopThreadOld As Long
Public g_hDesktopNew As Long, g_hDesktopNameNew As String


Function myWindowProc(ByVal hWnd As Long, ByVal uMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
If uMsg 
= WM_HOTKEY Then
    If wParam = 2 And g_hDesktopNew <> 0 Then
        SwitchDesktop g_hDesktopNew
        startExplorer ("explorer.exe")
    End If
    If wParam 
1 Then
        SwitchDesktop g_hDesktopThreadOld
    End If
End If
myWindowProc = CallWindowProc(lpOldWinProc, hWnd, uMsg, wParam, lParam)
End Function

Public Sub startExplorer(str As String)
Dim sui As STARTUPINFO, pi As PROCESS_INFORMATION
sui.cb 
= Len(sui)
sui.lpDesktop = g_hDesktopNameNew
CreateProcess vbNullString, str, ByVal 0&, ByVal 0&, 1, &H4000000 Or &H800, ByVal 0&, vbNullString, sui, pi
End Sub

是不是有点意思呢?