.NET的各种优点,使我无法将之束之高阁. .NET丰富的类库,功能强大,使用方便.终于进行了把VEGA向.NET移植做了第一次尝试.下图是用C#写的程序.运行速度比想像中的要好多了.仿真强调的重要的一点就是实时性.CLR没让我失望,运行得很流畅.
很多其它平台.NET平台移植后,名前加了一N.如NUnit, NHhibernate,Ndoc等,因此我把它命名为NVega.Frameword.由于仅是第一次小小尝试,我们仅仅用了几个必备函数.
//NativeMethod.cs
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
using System.Threading;
using Microsoft.Win32;
using System.Diagnostics;
namespace NVega.Framework
... {
internal class NativeMethod
...{
[DllImport("psvgd.dll")]
public static extern void vgInitWinSys(IntPtr AppInstance, IntPtr winHandle);
[DllImport("psvgd.dll", CharSet = CharSet.Ansi)]
public static extern void vgDefineSys(string fileName);
[DllImport("psvgd.dll")]
public static extern void vgConfigSys();
[DllImport("psvgd.dll")]
public static extern void vgSyncFrame();
[DllImport("psvgd.dll")]
public static extern void vgFrame();
[DllImport("psvgd.dll")]
public static extern void vgDrawEnabled(int enable);
}
}
经过尝试,vgDefineSys(string fileName)函数的DLLIMPORT属性CharSet只能设为Ansi,这说明,VEGA的字符串处理方式是ANSI的而非UNCODE,即在UNCODE的操作系统上,进行仿真的
//VegaThread.cs
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
using System.Threading;
using Microsoft.Win32;
using System.Diagnostics;
namespace NVega.Framework
... {
public class VegaThread
...{
public delegate void VegaHandler();
private bool terminate;
private string fileName;
private Thread vgThread;
private IntPtr winContainer;
private bool vgPause;
private static bool started;
static VegaThread()
...{
started = false;
}
public VegaThread(IntPtr winContainer)
: this(winContainer,string.Empty)
...{
}
public VegaThread(IntPtr winContainer,string fileName)
: this(winContainer, fileName, true)
...{
}
public VegaThread(IntPtr winContainer, string fileName, bool suspend)
...{
this.fileName = fileName;
this.winContainer = winContainer;
this.vgPause = this.terminate = false;
this.vgThread = new Thread(new ThreadStart(new VegaHandler(this.RunVegaApp)));
if(!suspend) this.Start();
}
public void Start()
...{
if(started)
throw new RerunVegaException("Vega thread run only one time in an application instance.");
if(this.fileName == string .Empty)
throw new ArgumentNullException("ADF file name can't be null.");
if (this.winContainer == IntPtr.Zero)
throw new ArgumentNullException("The vega handle of windows container can't be null.");
started = true;
this.vgThread = new Thread(new ThreadStart(new VegaHandler(RunVegaApp)));
vgThread.Start();
}
protected virtual void RunVegaApp()
...{
Process process = Process.GetCurrentProcess();
IntPtr hInstance = process.Handle;
NativeMethod.vgInitWinSys(hInstance, this.winContainer);
NativeMethod.vgDefineSys(this.fileName);
NativeMethod.vgConfigSys();
while (!terminate)
...{
NativeMethod.vgSyncFrame();
NativeMethod.vgFrame();
}
NativeMethod.vgSyncFrame();
}
public void Stop()
...{
this.terminate = true;
}
private void Pause()
...{
if (this.terminate || started) return;
if (vgPause)
NativeMethod.vgDrawEnabled(1);
else
NativeMethod.vgDrawEnabled(0);
vgPause = !vgPause;
}
public string FileName
...{
get
...{
return this.fileName;
}
set
...{
this.fileName = value;
}
}
public bool Terminate
...{
get
...{
return this.terminate;
}
set
...{
this.terminate = value;
}
}
}
}
我们知道在,VEGA中它自已很多处理线程.在这里它必须要与主线程分开.所以我在VegaThread类里面封装了一个线程对像.需要注意的是vgInitWinSys(hINSTANCE, HANDLE)函数,它有两个参数.第一个参数是应用程序的实例的句柄和一个父窗口的句柄. 应用程序的实例句柄,可以从Process.GetCurrentProcess().Handle;
vega在一个应用程序实例中只能运行一次.(这一点很不爽,等有空再研究这个问题,看看能否解决.)
定义了一个重运行的异常类.
//RerunVegaException.cs
using System.Collections.Generic;
using System.Text;
namespace NVega.Framework
... {
public class RerunVegaException:Exception
...{
public RerunVegaException(string message):base(message)
...{
}
}
}
这样一个基本的类库就实现完了.下面就可以进行试用了.
//frmMain.cs
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using NVega.Framework;
namespace VegaTranslation
... {
public partial class frmMain : Form
...{
/**//// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/**//// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
...{
if (disposing && (components != null))
...{
components.Dispose();
}
base.Dispose(disposing);
}
Windows Form Designer generated code#region Windows Form Designer generated code
/**//// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
...{
this.btnStart = new System.Windows.Forms.Button();
this.vgContainer = new System.Windows.Forms.Panel();
this.btnStop = new System.Windows.Forms.Button();
this.dlgOpen = new System.Windows.Forms.OpenFileDialog();
this.btnBrowser = new System.Windows.Forms.Button();
this.SuspendLayout();
//
// btnStart
//
this.btnStart.Location = new System.Drawing.Point(12, 12);
this.btnStart.Name = "btnStart";
this.btnStart.Size = new System.Drawing.Size(75, 23);
this.btnStart.TabIndex = 0;
this.btnStart.Text = "Start";
this.btnStart.UseVisualStyleBackColor = true;
this.btnStart.Click += new System.EventHandler(this.btnStart_Click);
//
// vgContainer
//
this.vgContainer.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.vgContainer.Location = new System.Drawing.Point(0, 42);
this.vgContainer.Name = "vgContainer";
this.vgContainer.Size = new System.Drawing.Size(718, 471);
this.vgContainer.TabIndex = 1;
//
// btnStop
//
this.btnStop.Location = new System.Drawing.Point(93, 12);
this.btnStop.Name = "btnStop";
this.btnStop.Size = new System.Drawing.Size(75, 23);
this.btnStop.TabIndex = 2;
this.btnStop.Text = "Stop";
this.btnStop.UseVisualStyleBackColor = true;
this.btnStop.Click += new System.EventHandler(this.btnStop_Click);
//
// dlgOpen
//
this.dlgOpen.DefaultExt = "adf";
this.dlgOpen.Filter = "ADF files|*.adf";
//
// btnBrowser
//
this.btnBrowser.Location = new System.Drawing.Point(174, 13);
this.btnBrowser.Name = "btnBrowser";
this.btnBrowser.Size = new System.Drawing.Size(75, 23);
this.btnBrowser.TabIndex = 3;
this.btnBrowser.Text = "Browser...";
this.btnBrowser.UseVisualStyleBackColor = true;
this.btnBrowser.Click += new System.EventHandler(this.btnBrowser_Click);
//
// frmMain
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(721, 515);
this.Controls.Add(this.btnBrowser);
this.Controls.Add(this.btnStop);
this.Controls.Add(this.vgContainer);
this.Controls.Add(this.btnStart);
this.Name = "frmMain";
this.Text = ".NET Vega Test";
this.ResumeLayout(false);
}
#endregion
private System.Windows.Forms.Button btnStart;
private System.Windows.Forms.Panel vgContainer;
private System.Windows.Forms.Button btnStop;
private System.Windows.Forms.OpenFileDialog dlgOpen;
private System.Windows.Forms.Button btnBrowser;
my self code#region my self code
private string filename = @"E:My DocumentsVisual Studio 2005ProjectsVegaTranslationVegaTranslationinDebug own.adf";
IntPtr parentHandle;
private VegaThread vgThread;
public frmMain()
...{
InitializeComponent();
parentHandle = vgContainer.Handle;
}
private void btnStart_Click(object sender, EventArgs e)
...{
this.vgThread = new VegaThread(this.parentHandle, filename);
this.vgThread.Start();
}
private void btnStop_Click(object sender, EventArgs e)
...{
this.vgThread.Stop();
}
private void btnBrowser_Click(object sender, EventArgs e)
...{
if (dlgOpen.ShowDialog() == System.Windows.Forms.DialogResult.OK)
...{
this.filename = dlgOpen.FileName;
this.Text = dlgOpen.FileName;
}
}
#endregion
}
}
使用很简单.这里我把一个PANEL控件作为父窗口.但用的是它的句柄.
总结:这个小试验里面,一.是要注意VEGA里的字符处理是ANSI的而非UNICODE.二.应用程序的实例句柄的获取方式.三.VEGA线程封装. 这里可能读者你也感觉到了,我们没有使用VEGA的任何一个类型.的确,现在我们连VEGA显示窗口都无法用代码来最大化.这个就是下一步要做的..NET不能"直接"使用本地类型库.也许你会说用VC++.NET呀,我只想说用这个,前面的代码我们都可以不用写了.那是另外一个主题了.
我决定用COM先把一些简单的类型封装起来,再使用COM包装器.看能否成功把VEGA类型移植过来...