什么是WPF?
WPF(Windows Presentation Foundation)是微软推出的基于Windows 的用户界面框架,属于.NET Framework 3.0的一部分。它提供了统一的编程模型、语言和框架,真正做到了分离界面设计人员与开发人员的工作;同时它提供了全新的多媒体交互用户图形界面。
据笨笨所知,WPF是最早的无窗口编程框架,是现代各种DirectUI的鼻祖。
在WPF中,最方便的曲线库当然是微软的Ms-Chart啦,毕竟是自家的,一脉相承,肥水不流外人田。但有时候Ms-Chart的性能或功能不能满足需求,比如Ms-Chart的数据点多了就比较卡,那能不能尝试一下CChart呢?这就需要解决CChart在WPF中的调用问题。
如同SoUI中一样,最简单的方式就是弹出窗口,这几乎没有任何难度。如果要把CChart窗口嵌入WPF界面,技术要点就是需要使用WPF的WindowsFormsHost控件。
下面开始具体介绍调用方法,采用VS2010做演示。
由于WPF是基于C#的,所以很多要点和在C#中调用CChart是一样的。
C#是基于宽字节的,所以动态链接库需要选用CChartu.dll。
函数接口的导出,需要采用前面第A22课中介绍的方法,以便在C#中使用。
第一步,打开Vs2010,新建一个基于Visual C#的WPF应用程序,名为LessonA48。
第二步,为了使用WindowsFormsHost控件,需要在应用程序中添加对WindowsFormsIntegration程序集的引用。程序中还使用了Panel控件,需要添加对System.Windows.Forms程序集的引用。
具体是在解决方案资源管理器视图中,右击“引用”,点击“添加应用”。
在添加应用对话框里的.NET标签中,找到System.Windows.Forms和WindowsFormsIntegration,分别点击确定。
第三步,把主界面划分为左右两部分,计划左边放置两个按钮,右边用来绘制图像。
打开MainWindow.xaml,在文本编辑区的<Grid>和</Grid>标签之间,插入以下文本。
<Grid.ColumnDefinitions>
<ColumnDefinition Width="80"></ColumnDefinition>
<ColumnDefinition></ColumnDefinition>
</Grid.ColumnDefinitions>
第四步,左半边先放置一个按钮。
在MainWindow.xaml中添加如下文本。
<Canvas Grid.Column="0">
<Button Canvas.Left="10" Canvas.Top="10" Click="MyPopupWindow">弹出窗口</Button>
</Canvas>
这里采用了老式的Canvas画布来布局按钮。
同时在MainWindow.xaml.cs中,为MainWindow类添加如下成员函数。
private void MyPopupWindow(object sender, RoutedEventArgs e)
{
}
弹出窗口的基本框架搭建起来了。
第五步,导出所需的函数。
在MainWindow.xaml.cs中,添加如下代码。
using System.Runtime.InteropServices;
有了这句话才能从Dll中导出函数。
在MainWindow类中添加如下代码。
[DllImport(@"CChartu.dll", EntryPoint = "?CreatePopupChartWndGlobal@NsClassless@@YAPAUHWND__@@PAU2@HPA_WHHHH@Z", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)]
protected extern static int CreatePopupChartWndGlobal(int hwndParent, int charttype, string title, int x, int y, int width, int height);
[DllImport(@"CChartu.dll", EntryPoint = "?Attach@NsClassless@@YAHPAUHWND__@@H@Z", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)]
protected extern static int Attach(int hWnd, int nType);
[DllImport(@"CChartu.dll", EntryPoint = "?AddPoint2D@NsClassless@@YAHNNHH@Z", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)]
protected extern static int AddPoint2D(double x, double y, int nCurveIndex, int nPlotIndex);
[DllImport(@"CChartu.dll", EntryPoint = "?SetTitle@NsClassless@@YAXPB_W@Z", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)]
protected extern static void SetTitle(string title);
[DllImport(@"CChartu.dll", EntryPoint = "?ReDraw@NsClassless@@YAXXZ", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)]
protected extern static void ReDraw();
[DllImport(@"CChartu.dll", EntryPoint = "?ChooseCurChart@NsClassless@@YAXPAUHWND__@@@Z", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)]
protected extern static void ChooseCurChart(int hWnd);
这里导出了六个函数。
第六步,在按钮的响应函数MyPopupWindow中,添加弹出窗口绘制代码。
private void MyPopupWindow(object sender, RoutedEventArgs e)
{
string title = "弹出窗口";
int hWnd = CreatePopupChartWndGlobal(0, 0, title, 0, 0, 800, 600);
ChooseCurChart(hWnd);
double x, y;
for (int i = 0; i < 361; ++i)
{
x = 1.6 * Math.Cos(i * 2.0 * Math.PI / 360);
y = 1.6 * Math.Sin(i * 2.0 * Math.PI / 360);
AddPoint2D(x, y, 0, 0);
}
SetTitle(title);
ReDraw();
}
现在可以运行程序了。不过在运行之前,请把CChartu.dll拷贝到可执行文件的位置。
运行程序,并点击程序中的按钮,效果如下。
大家可能会疑惑这里ChooseCurChart有什么作用。这是如果有多个绘图窗口,我们调用的AddPoint2D等全局函数究竟往哪个窗口作用,就存疑了。ChooseCurChart就是选择当前窗口的。
第七步,在MainWindow.xaml增加以下文本。
xmlns:wfh="clr-namespace:System.Windows.Forms.Integration;assembly=WindowsFormsIntegration"
xmlns:wf="clr-namespace:System.Windows.Forms;assembly=System.Windows.Forms"
其中第一条为了使用WindowsFormsHost控件,第二条是为了使用Panel控件。
第八步,在主界面右边部分增加WindowsFormsHost控件,并在其中添加一个Panel控件,名为ChartPanel。
<WindowsFormsHost Grid.Column="1">
<wf:Panel x:Name="ChartPanel" Dock="Fill"/>
</WindowsFormsHost>
第九步,在左边再增加一个按钮。
在MainWindow.xaml文件中,添加文本。
<Button Canvas.Left="10" Canvas.Top="50" Click="MyDrawWindow">弹出窗口</Button>
同时在MainWindow.xaml.cs文件中,添加响应函数。
private void MyDrawWindow(object sender, RoutedEventArgs e)
{
int hWnd;
hWnd = ChartPanel.Handle.ToInt32();
Attach(hWnd, 0);
ChooseCurChart(hWnd);
double x, y;
for (int i = 0; i < 361; ++i)
{
x = i*2.0;
y = 1.6 * Math.Sin(i * 2.0 * Math.PI / 360);
AddPoint2D(x, y, 0, 0);
}
string title = "子窗口模式";
SetTitle(title);
ReDraw();
}
效果如图。
WPF的介绍就到这里,使用还是比较简单的。