以FoxPro的界面为例。设主程序为Winform.exe,FoxPro编译的程序为vfpTest.exe。
1 在Winform中新建一个窗口VFPSHOW作为所有vfp打开后的父窗口,提供一个单例模式实现窗口唯一打开
VFPSHOW实例
private static VFPSHOW mInstance = null;
/// <summary>
/// 单例模式
/// </summary>
public static VFPSHOW Instance
{
get
{
if (mInstance == null || mInstance.IsDisposed)
{
mInstance = new VFPSHOW();
}
return mInstance;
}
}
private static VFPSHOW mInstance = null;
/// <summary>
/// 单例模式
/// </summary>
public static VFPSHOW Instance
{
get
{
if (mInstance == null || mInstance.IsDisposed)
{
mInstance = new VFPSHOW();
}
return mInstance;
}
}
2 引入系统API,用于把VFP程序打开的表单窗口整合到VFPSHOW页面中,先添加如下引用:
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Threading;
using System.Reflection;
using System.Management;
WIN API
private const int SWP_NOOWNERZORDER = 0x200;
private const int SWP_NOREDRAW = 0x8;
private const int SWP_NOZORDER = 0x4;
private const int SWP_SHOWWINDOW = 0x0040;
private const int WS_EX_MDICHILD = 0x40;
private const int SWP_FRAMECHANGED = 0x20;
private const int SWP_NOACTIVATE = 0x10;
private const int SWP_ASYNCWINDOWPOS = 0x4000;
private const int SWP_NOMOVE = 0x2;
private const int SWP_NOSIZE = 0x1;
private const int GWL_STYLE = (-16);
private const int WS_VISIBLE = 0x10000000;
private const int WM_CLOSE = 0x10;
private const int WS_CHILD = 0x40000000;
[DllImport("user32.dll", EntryPoint = "GetWindowThreadProcessId", SetLastError = true,
CharSet = CharSet.Unicode, ExactSpelling = true,
CallingConvention = CallingConvention.StdCall)]
private static extern long GetWindowThreadProcessId(long hWnd, long lpdwProcessId);
[DllImport("user32.dll", SetLastError = true)]
private static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
[DllImport("user32.dll", SetLastError = true)]
private static extern long SetParent(IntPtr hWndChild, IntPtr hWndNewParent);
[DllImport("user32.dll", EntryPoint = "GetWindowLongA", SetLastError = true)]
private static extern long GetWindowLong(IntPtr hwnd, int nIndex);
[DllImport("user32.dll", EntryPoint = "SetWindowLongA", SetLastError = true)]
private static extern long SetWindowLong(IntPtr hwnd, int nIndex, long dwNewLong);
//private static extern int SetWindowLong(IntPtr hWnd, int nIndex, IntPtr dwNewLong);
[DllImport("user32.dll", SetLastError = true)]
private static extern long SetWindowPos(IntPtr hwnd, long hWndInsertAfter, long x, long y, long cx, long cy, long wFlags);
[DllImport("user32.dll", SetLastError = true)]
private static extern bool MoveWindow(IntPtr hwnd, int x, int y, int cx, int cy, bool repaint);
[DllImport("user32.dll", EntryPoint = "PostMessageA", SetLastError = true)]
private static extern bool PostMessage(IntPtr hwnd, uint Msg, long wParam, long lParam);
[DllImport("user32.dll")]
public static extern void SetForegroundWindow(IntPtr hwnd);
private const int SWP_NOOWNERZORDER = 0x200;
private const int SWP_NOREDRAW = 0x8;
private const int SWP_NOZORDER = 0x4;
private const int SWP_SHOWWINDOW = 0x0040;
private const int WS_EX_MDICHILD = 0x40;
private const int SWP_FRAMECHANGED = 0x20;
private const int SWP_NOACTIVATE = 0x10;
private const int SWP_ASYNCWINDOWPOS = 0x4000;
private const int SWP_NOMOVE = 0x2;
private const int SWP_NOSIZE = 0x1;
private const int GWL_STYLE = (-16);
private const int WS_VISIBLE = 0x10000000;
private const int WM_CLOSE = 0x10;
private const int WS_CHILD = 0x40000000;
[DllImport("user32.dll", EntryPoint = "GetWindowThreadProcessId", SetLastError = true,
CharSet = CharSet.Unicode, ExactSpelling = true,
CallingConvention = CallingConvention.StdCall)]
private static extern long GetWindowThreadProcessId(long hWnd, long lpdwProcessId);
[DllImport("user32.dll", SetLastError = true)]
private static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
[DllImport("user32.dll", SetLastError = true)]
private static extern long SetParent(IntPtr hWndChild, IntPtr hWndNewParent);
[DllImport("user32.dll", EntryPoint = "GetWindowLongA", SetLastError = true)]
private static extern long GetWindowLong(IntPtr hwnd, int nIndex);
[DllImport("user32.dll", EntryPoint = "SetWindowLongA", SetLastError = true)]
private static extern long SetWindowLong(IntPtr hwnd, int nIndex, long dwNewLong);
//private static extern int SetWindowLong(IntPtr hWnd, int nIndex, IntPtr dwNewLong);
[DllImport("user32.dll", SetLastError = true)]
private static extern long SetWindowPos(IntPtr hwnd, long hWndInsertAfter, long x, long y, long cx, long cy, long wFlags);
[DllImport("user32.dll", SetLastError = true)]
private static extern bool MoveWindow(IntPtr hwnd, int x, int y, int cx, int cy, bool repaint);
[DllImport("user32.dll", EntryPoint = "PostMessageA", SetLastError = true)]
private static extern bool PostMessage(IntPtr hwnd, uint Msg, long wParam, long lParam);
[DllImport("user32.dll")]
public static extern void SetForegroundWindow(IntPtr hwnd);
3 用Process执行其它程序,vfpTest.exe,传入打开窗口命令,如 Do From myForm
运行进程
#region 运行进程
IntPtr appWin;
ProcessStartInfo psi = new ProcessStartInfo(strVFPPath);
psi.RedirectStandardInput = true;
psi.RedirectStandardOutput = true;
psi.UseShellExecute = false;
psi.Arguments = strArugments;
Process _process = new Process();
_process.StartInfo = psi;
_process.EnableRaisingEvents = true;
_process.Exited += new EventHandler(_process_Exited);
_process.Start();
#endregion
#region 运行进程
IntPtr appWin;
ProcessStartInfo psi = new ProcessStartInfo(strVFPPath);
psi.RedirectStandardInput = true;
psi.RedirectStandardOutput = true;
psi.UseShellExecute = false;
psi.Arguments = strArugments;
Process _process = new Process();
_process.StartInfo = psi;
_process.EnableRaisingEvents = true;
_process.Exited += new EventHandler(_process_Exited);
_process.Start();
#endregion
4 把创建的表单移动到VFPSHOW中
VFP进程放入C#窗口中
#region VFP进程放入C#窗口中
if (_process.WaitForInputIdle())
{
while (_process.MainWindowHandle.ToInt32() == 0)
{
Thread.Sleep(intMilliSecod);
_process.Refresh();//必须刷新状态才能重新获得TITLE
}
_process.StartInfo = psi;
// Get the main handle
appWin = _process.MainWindowHandle;
// Put it into this form
SetParent(appWin, mInstance.Handle);
// Move the window to overlay it on this window
//MoveWindow(appWin, 0, 0, _mainParent.dockPanel1.Width, _mainParent.dockPanel1.Height, true);
MoveWindow(appWin, intX, intY, intWidth, intHeight, true);
if (intX > mInstance.Width)
{
intX = 10;
}
else
{
intX = intX + intWidth;
}
}
#endregion
#region VFP进程放入C#窗口中
if (_process.WaitForInputIdle())
{
while (_process.MainWindowHandle.ToInt32() == 0)
{
Thread.Sleep(intMilliSecod);
_process.Refresh();//必须刷新状态才能重新获得TITLE
}
_process.StartInfo = psi;
// Get the main handle
appWin = _process.MainWindowHandle;
// Put it into this form
SetParent(appWin, mInstance.Handle);
// Move the window to overlay it on this window
//MoveWindow(appWin, 0, 0, _mainParent.dockPanel1.Width, _mainParent.dockPanel1.Height, true);
MoveWindow(appWin, intX, intY, intWidth, intHeight, true);
if (intX > mInstance.Width)
{
intX = 10;
}
else
{
intX = intX + intWidth;
}
}
#endregion
5 通过上面4步就完成了VFP嵌入到VFPSHOW界面的效果,MDI窗口需要再加入一些判断:
(1)如果指定的VFP界面已经打开,只激活VFPSHOW界面,不再次打开
已经打开激活窗口
///因直接用process取不到进程的startinfo信息,所以采用以下方法
SelectQuery selectQuery = new SelectQuery("select * from Win32_Process Where Name = 'vfpTest.exe'");
string strCmdLine = "";
using (ManagementObjectSearcher searcher = new ManagementObjectSearcher(selectQuery))
{
foreach (ManagementObject process in searcher.Get())
{
strCmdLine = process.Properties["CommandLine"].Value.ToString();
if (strCmdLine.Substring(strCmdLine.IndexOf(' ') + 1) == strArugments)
{
mInstance.Show();//另一个进程执行时显示当前窗口
mInstance.Activate();
return;
}
}
}
///因直接用process取不到进程的startinfo信息,所以采用以下方法
SelectQuery selectQuery = new SelectQuery("select * from Win32_Process Where Name = 'vfpTest.exe'");
string strCmdLine = "";
using (ManagementObjectSearcher searcher = new ManagementObjectSearcher(selectQuery))
{
foreach (ManagementObject process in searcher.Get())
{
strCmdLine = process.Properties["CommandLine"].Value.ToString();
if (strCmdLine.Substring(strCmdLine.IndexOf(' ') + 1) == strArugments)
{
mInstance.Show();//另一个进程执行时显示当前窗口
mInstance.Activate();
return;
}
}
}
(2)最多允许5个VFP程序
最多允许5个VFP程序
Process[] allProcess = Process.GetProcessesByName("vfpTest");
if (allProcess != null && allProcess.Length >= 5)
{
InfoProcess.MessageShow("该控制台最多允许5个VFP程序同时运行!");
return;
}
Process[] allProcess = Process.GetProcessesByName("vfpTest");
if (allProcess != null && allProcess.Length >= 5)
{
InfoProcess.MessageShow("该控制台最多允许5个VFP程序同时运行!");
return;
}
6 完整文件:上传时报错,有需要的再说
非有希望才坚持,坚持才会有希望