回复 2楼 吹水佬
代码找到了,可惜是VFP9.0的,其中BINTOC和CTOBION函数的第二个参数使用了RS,VFP8.0不支持,可俺偏偏就用VFP8.0
。
m.oDesktop = NEWOBJECT( 'NewDesktop' )
IF ( 'O' == VARTYPE( m.oDesktop )) AND !ISNULL( m.oDesktop )
m.cFile = GETFILE( 'exe', '文件名(&N):', '运行(&R)', 0, '请选择要在新桌面中运行的程序' )
m.oDesktop.Run( m.cFile )
ENDIF
m.oDesktop = NULL
DEFINE CLASS NewDesktop AS Custom
HIDDEN hOldDesktop
hOldDesktop = 0
HIDDEN hOldInput
hOldInput = 0
HIDDEN hNewDesktop
hNewDesktop = 0
HIDDEN pcNewDesktop
pcNewDesktop = 0
HIDDEN NewDesktopName
NewDesktopName = ('desktop' +SYS(2015))
HIDDEN ErrMsg
ErrMsg = ''
Name = 'NewDesktop'
HIDDEN PROCEDURE api_decl
DECLARE Long GetThreadDesktop IN WIN32API Long dwThreadId
DECLARE Long OpenInputDesktop IN WIN32API ;
Long dwFlags, Long fInherit, Long dwDesiredAccess
DECLARE Long CreateDesktop IN WIN32API ;
String lpszDesktop, Long lpszDevice, Long pDevmode, ;
Long dwFlags, Long dwDesiredAccess, Long lpsa
DECLARE Long SetThreadDesktop IN WIN32API Long hDesktop
DECLARE Long SwitchDesktop IN WIN32API Long hDesktop
DECLARE Long CloseDesktop IN WIN32API Long hDesktop
DECLARE Long CreateProcess IN WIN32API ;
String pszAppName, String pszCmdLine, ;
Long lpProcessAttr, Long lpThreadAttr, ;
Long bInheritHandles, Long dwCreationFlags, ;
Long lpEnvironment, String pszCurDir, ;
String lpStartupInfo, String @ lpProcInfo
DECLARE Long CloseHandle IN WIN32API Long hObject
DECLARE Long WaitForSingleObject IN WIN32API ;
Long hHandle, Long dwMilliseconds
DECLARE Long GetProcessHeap IN WIN32API
DECLARE Long HeapAlloc IN WIN32API ;
Long hHeap, Long dwFlags, Long dwBytes
DECLARE Long HeapFree IN WIN32API ;
Long hHeap, Long dwFlags, Long lpMem
DECLARE Long GetLastError IN WIN32API
This.pcNewDesktop = HeapAlloc( GetProcessHeap(), 8, LEN(This.NewDesktopName)+1 )
IF ( 0 == This.pcNewDesktop )
MESSAGEBOX( '内存分配失败 !', 16, '错误' )
ELSE
SYS( 2600, This.pcNewDesktop, LEN(This.NewDesktopName), This.NewDesktopName )
ENDIF
ENDPROC
PROCEDURE Run
*!*
------------------------------------------------------------------------
*!*
功能: 在新建桌面中运行指定的程序
*!*
入口: tcExeFile - 要执行的 exe 文件
*!*
tiTimeout - 等待执行时间(单位 ms, 0 代表一直等待到它终止并退出)
*!*
------------------------------------------------------------------------
LPARAMETERS tcExeFile, tiTimeout
IF ( 'C' != VARTYPE( m.tcExeFile )) OR EMPTY( m.tcExeFile )
RETURN .F.
ENDIF
IF ( PCOUNT() < 2 ) OR ( 'N' != VARTYPE( m.tiTimeout )) OR ( m.tiTimeout <= 0 )
m.tiTimeout = -1
ENDIF
This.ErrMsg = ''
IF This.SwitchToNewDesktop()
This.StartProcess( m.tcExeFile, m.tiTimeout )
ENDIF
IF !EMPTY( This.ErrMsg )
MESSAGEBOX( This.ErrMsg, 16, '错误' )
ENDIF
ENDPROC
HIDDEN PROCEDURE SwitchToNewDesktop
#define DESKTOP_SWITCHDESKTOP
0x0100
#define GENERIC_ALL
0x10000000
*!* 保存当前线程所在的桌面句柄
This.hOldDesktop = GetThreadDesktop( _vfp.ThreadId )
*!* 保存当前用户输入线程的桌面句柄
This.hOldInput = OpenInputDesktop( 0, 0, DESKTOP_SWITCHDESKTOP )
*!* 创建新桌面
This.hNewDesktop = CreateDesktop( This.NewDesktopName, 0, 0, 0, GENERIC_ALL, 0 )
IF ( 0 == This.hNewDesktop )
This.ErrMsg = '创建桌面失败!错误代码: ' + TRANSFORM( GetLastError())
RETURN .F.
ENDIF
*!* 切换当前线程到新建桌面中
SetThreadDesktop( This.hNewDesktop )
IF ( 0 == SwitchDesktop( This.hNewDesktop ))
This.ErrMsg = '切换桌面失败!错误代码: ' + TRANSFORM( GetLastError())
RETURN .F.
ENDIF
ENDPROC
HIDDEN PROCEDURE StartProcess
LPARAMETERS tcExeFile, tiTimeout
*!*
typedef struct _PROCESS_INFORMATION {
*!*
HANDLE hProcess;
*!*
HANDLE hThread;
*!*
DWORD dwProcessId;
*!*
DWORD dwThreadId;
*!*
} PROCESS_INFORMATION
*!*
typedef struct _STARTUPINFO {
*!*
DWORD cb;
*!*
LPTSTR lpReserved;
*!*
LPTSTR lpDesktop;
*!*
LPTSTR lpTitle;
*!*
DWORD dwX;
*!*
DWORD dwY;
*!*
DWORD dwXSize;
*!*
DWORD dwYSize;
*!*
DWORD dwXCountChars;
*!*
DWORD dwYCountChars;
*!*
DWORD dwFillAttribute;
*!*
DWORD dwFlags;
*!*
WORD wShowWindow;
*!*
WORD cbReserved2;
*!*
LPBYTE lpReserved2;
*!*
HANDLE hStdInput;
*!*
HANDLE hStdOutput;
*!*
HANDLE hStdError;
*!*
} STARTUPINFO
LOCAL cSI, cPI, hProcess
IF ( m.tiTimeout <= 0 )
m.tiTimeout = -1
ENDIF
m.cSI = BINTOC( 0, 'rs' ) + BINTOC( This.pcNewDesktop, 'rs' ) + REPLICATE( CHR(0), 14*4 )
m.cSI = BINTOC( LEN( m.cSI )+4, 'rs' ) + m.cSI
m.cPI = REPLICATE( CHR(0), 4*4 )
IF ( 0 == CreateProcess( ;
m.tcExeFile, '', 0, 0, 0, 0, 0, NULL, m.cSI, @ m.cPI ))
This.ErrMsg = '在新桌面中创建进程失败! 错误代码: ' + TRANSFORM( GetLastError())
ELSE
m.hProcess = CTOBIN( LEFT( m.cPI, 4 ), 'rs' )
*!* 等待此进程终止
WaitForSingleObject( m.hProcess, m.tiTimeout )
*!* CloseHandle( m.hProcess )
ENDIF
This.ClearUp()
ENDPROC
HIDDEN PROCEDURE ClearUp
IF ( 0 != This.hOldInput )
SwitchDesktop( This.hOldInput )
&& 切换回默认桌面
This.hOldInput = 0
ENDIF
IF ( 0 != This.hOldDesktop )
SetThreadDesktop( This.hOldDesktop )
&& 回复原线程桌面
This.hOldDesktop = 0
ENDIF
IF ( 0 != This.hNewDesktop )
CloseDesktop( This.hNewDesktop )
&& 关闭新建的桌面
This.hNewDesktop = 0
ENDIF
ENDPROC
PROCEDURE Init
This.api_decl()
ENDPROC
PROCEDURE Destroy
IF ( 0 != This.pcNewDesktop )
HeapFree( GetProcessHeap(), 0, This.pcNewDesktop )
This.pcNewDesktop = 0
ENDIF
ENDPROC
ENDDEFINE