UWSCで仮想デスクトップ切替
Enum系APIをたたいてみたくなって、やってみた。
ついでに、仮想デスクトップ切替スクリプトに仕上げてみた。
スクリプト
Desktops.uws
OPTION EXPLICIT CALL Asm IFB GET_UWSC_NAME = "Desktops.uws" THEN DIM ds = Desktops.Enum(), hDesk, i HASHTBL dl FOR i = 0 TO LENGTH(ds) - 1 hDesk = Desktops.Open(ds[i]) IF hDesk THEN dl[hDesk] = ds[i] NEXT DIM createD = "(新規作成)", createP = "(プロセス起動)", name name = SLCTBOX(SLCT_BTN OR SLCT_STR, 0, "切替先 (現在:" + Desktops.GetName() + ")", dl, createD, createP) SELECT name CASE createD name = INPUT("作成するデスクトップ名を入力してください") CASE createP name = SLCTBOX(SLCT_BTN OR SLCT_STR, 0, "作成先 (現在:" + Desktops.GetName() + ")", dl) i = EMPTY IFB name <> -1 THEN i = INPUT("プロセスを入力してください", GET_SYS_DIR + "\calc.exe") ENDIF IFB LENGTH(i) THEN IF !Desktops.Create(name, i) THEN MSGBOX("起動失敗:" + name + "<#CR>" + i) ENDIF name = EMPTY CASE -1 name = EMPTY SELEND hDesk = 0 IFB dl[name, HASH_EXISTS] THEN hDesk = dl[name] ELSE hDesk = Desktops.Open(name) ENDIF IFB hDesk THEN IF !Desktops.Switch(hDesk) THEN MSGBOX("切替失敗:" + name) ENDIF FOR i = 0 TO LENGTH(dl) - 1 Desktops.Close(dl[i, HASH_KEY]) NEXT Desktops.Dispose() ENDIF MODULE Desktops DEF_DLL GetProcessWindowStation(): DWORD: user32 DEF_DLL EnumDesktopsA(DWORD,DWORD,DWORD): BOOL: user32 DIM _addr = 0 FUNCTION Enum(hwinsta=ERR_VALUE) RESULT = SPLIT(EMPTY) IFB _addr = 0 THEN DIM code = "VYvsg+wQx0X0AQAAAItFDIlF/MdF+AAAAADrCYtN+IPBAYlN+ItVCANV+A++AoXA" code = code + "fgLr6ItN+IPBAYlN+ItV/IsCA0X4i038O0EEdzPHRfAAAAAA6wmLVfCDwgGJVfCL" code = code + "RfA7RfhzGYtN/IsRA1Xwi0UIA0Xwi038igCIRBEI69aLTfyLEQNV+ItF/IkQi0X0" code = code + "i+VdwggA" _addr = Asm.Set(code) ENDIF DIM paraSize = 9, para = Asm.Alloc(paraSize) IFB _addr > 0 AND para > 0 THEN IF hwinsta = ERR_VALUE THEN hwinsta = GetProcessWindowStation() IFB EnumDesktopsA(hwinsta, _addr, para) THEN paraSize = Asm.GetDword(para) Asm.Free(para) para = Asm.Alloc(paraSize + 8) IFB para > 0 THEN Asm.SetDword(para + 4, paraSize) IFB !EnumDesktopsA(hwinsta, _addr, para) THEN Asm.Free(para) para = 0 ENDIF ENDIF ELSE Asm.Free(para) para = 0 ENDIF ELSE IF para > 0 THEN Asm.Free(para) para = 0 ENDIF IFB para > 0 THEN //Asm.Dump(para, paraSize + 8) DEF_DLL RtlMoveMemory(var BYTE[], DWORD, DWORD): kernel32 DIM data[paraSize], i, j = 0, buf RtlMoveMemory(data, para + 8, paraSize) DEF_DLL RtlMoveMemory(var string, DWORD, DWORD): kernel32 HASHTBL ds FOR i = 0 TO paraSize - 1 IFB data[i] = 0 THEN buf = FORMAT(CHR(0), i - j) RtlMoveMemory(buf, para + 8 + j, i - j) ds[LENGTH(ds)] = buf j = i + 1 ENDIF NEXT j = LENGTH(ds) - 1 RESULT = SPLIT(" ") RESIZE(RESULT, j) FOR i = 0 TO j RESULT[i] = ds[i, HASH_VAL] NEXT ENDIF FEND PROCEDURE Dispose() IF _addr THEN Asm.Free(_addr) _addr = 0 FEND FUNCTION Open(name, bFirstExplorer=TRUE) DEF_DLL OpenDesktopW(wstring, DWORD, BOOL, DWORD): DWORD: user32 RESULT = OpenDesktopW(name, 0, FALSE, $1FF) IFB RESULT THEN bFirstExplorer = FALSE ELSE DEF_DLL CreateDesktopW(wstring,wstring,dword,DWORD,DWORD,dword): DWORD: user32 RESULT = CreateDesktopW(name, NULL, 0, 0, $1FF, 0) ENDIF IFB RESULT > 0 AND bFirstExplorer THEN IF !Create(name, GET_WIN_DIR + "\explorer.exe") THEN RESULT = 0 ENDIF FEND FUNCTION Switch(hDesk) //DEF_DLL SetThreadDesktop(DWORD): BOOL: user32 DEF_DLL SwitchDesktop(DWORD): BOOL: user32 RESULT = SwitchDesktop(hDesk) FEND FUNCTION Close(hDesk) DEF_DLL CloseDesktop(DWORD): BOOL: user32 RESULT = CloseDesktop(hDesk) FEND FUNCTION GetCurrent() DEF_DLL GetThreadDesktop(DWORD): DWORD: user32 DEF_DLL GetCurrentThreadId(): DWORD: kernel32 RESULT = GetThreadDesktop(GetCurrentThreadId()) FEND FUNCTION GetName(hDesk=0) RESULT = EMPTY IF hDesk = 0 THEN hDesk = GetCurrent() DEF_DLL GetUserObjectInformationW(DWORD,int,var wstring,DWORD,var DWORD): BOOL: user32 DIM dwLen = 0, buf GetUserObjectInformationW(hDesk, 2, NULL, dwLen, dwLen) IFB dwLen > 0 THEN buf = FORMAT(CHR(0), dwLen) IF GetUserObjectInformationW(hDesk, 2, buf, dwLen, dwLen) THEN RESULT = buf ENDIF FEND FUNCTION Create(name, path, cmdline="") RESULT = FALSE DEF_DLL CreateProcessW(wstring,wstring,dword,dword,BOOL,dword,string,wstring, _ {DWORD,var wstring,var wstring,var wstring,DWORD,DWORD,DWORD,DWORD,DWORD,DWORD,DWORD,DWORD,WORD,WORD,dword,DWORD,DWORD,DWORD}, _ {DWORD,DWORD,DWORD,DWORD}): BOOL: kernel32 DIM hProcess, hThread, dwProcessId, dwThreadId RESULT = CreateProcessW(path, cmdline, 0, 0, FALSE, 0, NULL, NULL, _ 68,NULL,name,NULL,0,0,0,0,0,0,0,0,0,0,0,0,0,0, _ hProcess, hThread, dwProcessId, dwThreadId) IFB RESULT THEN IF hProcess THEN Asm.CloseHandle(hProcess) IF hThread THEN Asm.CloseHandle(hThread) ENDIF FEND ENDMODULE
Asmモジュールは、以下からどうぞ。
UWSCにできないことはない? - じゅんじゅんのきまぐれ
最初は「Default」くらいしかないと思いますが、新規作成すれば作れます。
また、プロセス起動で、他のデスクトップにプロセスを作れます。
なお、デスクトップを削除する手段はないので、消したくなったらログオフ or シャットダウンしてください。