做了6、7年的c/c++编程,偶然的机会到现在的公司,原本是要开发视频会议系统,结果却要开发一个桌面应用,而且要用wpf做,说真的,c#只是看过,dotnet也只是开发了几个webservice,而且使用托管c++的。当然我还不怕使用c#,毕竟语言只是一个工具而已,尽管在开发的过程中老是想用c++去做。 最重要的是我也想开发一个桌面应用,看看这些产品怎么走向成熟的,毕竟以前很少接触到界面
闲话就不扯了,谈谈wpf开发吧!
使用wpf开发应用程序,就像使用dreamwaver开发html页面一样,你可以直接编辑xaml文件,也可以直接写代码实现,真正意义上的app=code+markup.
用wpf开发一个界面稍微复杂一点的应用程序,其进度怎么说呢,应该是比delphi更快,比delphi更漂亮吧,(或许我对delphi不是特别的了解,但是看过朋友用delphi开发过,个人感觉)。,虽然他们都是一种组件堆积得过程。由于微软提供了blend工具,可以做出非常炫的效果,从而程序的界面也是更加漂亮,说到这里,简单介绍一下怎么做出非常漂亮的界面组件,我们是在blend做出非常漂亮的一个组件,blend会自动生成该组件的style,只要将该style直接复制、赋值给应用程序的组件即可,当然你也可以在blend中创建一个自定义控件直接用。下面给出一个简单的例子,使用blend生成的xaml形式的style:
假设我有下面的style:
<
Style
x:Key
=
"OkButtonStyle"BasedOn="{x:Null}"TargetType="{x:Type Button}">
<
Setter
Property
=
"Template">
<
Setter.Value
>
<
ControlTemplate
TargetType
=
"{x:Type Button}">
<
Grid
>
<
Rectangle
StrokeThickness
=
"1"RadiusX="1"RadiusY="1"x:Name="rectangle"Fill="{DynamicResource Brush1}">
<
Rectangle.Stroke
>
<
LinearGradientBrush
EndPoint
=
"0.488,-0.133"StartPoint="0.5,1.107">
<
GradientStop
Color
=
"#FFFFFFFF"Offset="0"/>
<
GradientStop
Color
=
"#00FFFFFF"Offset="1"/>
</
LinearGradientBrush
>
</
Rectangle.Stroke
>
</
Rectangle
>
<
ContentPresenter
SnapsToDevicePixels
=
"{TemplateBinding SnapsToDevicePixels}"HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"VerticalAlignment="{TemplateBinding VerticalContentAlignment}"RecognizesAccessKey="True"/>
</
Grid
>
<
ControlTemplate.Triggers
>
<
Trigger
Property
=
"IsFocused"Value="True"/>
<
Trigger
Property
=
"IsDefaulted"Value="True"/>
<
Trigger
Property
=
"IsMouseOver"Value="True">
<
Setter
Property
=
"Fill"TargetName="rectangle">
<
Setter.Value
>
<
LinearGradientBrush
EndPoint
=
"0.513,1.439"StartPoint="0.512,-0.153">
<
GradientStop
Color
=
"#FF3183D0"Offset="0.254"/>
<
GradientStop
Color
=
"#FF82ECFF"Offset="0.837"/>
<
GradientStop
Color
=
"#FF7CB1E8"Offset="0"/>
</
LinearGradientBrush
>
</
Setter.Value
>
</
Setter
>
</
Trigger
>
<
Trigger
Property
=
"IsPressed"Value="True">
<
Setter
Property
=
"Fill"TargetName="rectangle">
<
Setter.Value
>
<
LinearGradientBrush
EndPoint
=
"0.513,1.439"StartPoint="0.512,-0.153">
<
GradientStop
Color
=
"#FF195FA1"Offset="0.254"/>
<
GradientStop
Color
=
"#FF82ECFF"Offset="0.837"/>
<
GradientStop
Color
=
"#FF7CB1E8"Offset="0"/>
</
LinearGradientBrush
>
</
Setter.Value
>
</
Setter
>
</
Trigger
>
<
Trigger
Property
=
"IsEnabled"Value="False">
<
Setter
Property
=
"Fill"TargetName="rectangle">
<
Setter.Value
>
<
LinearGradientBrush
EndPoint
=
"0.513,1.439"StartPoint="0.512,-0.153">
<
GradientStop
Color
=
"#FF78797A"Offset="0.254"/>
<
GradientStop
Color
=
"#FFBABABA"Offset="0.866"/>
<
GradientStop
Color
=
"#FFD8D8D8"Offset="0"/>
</
LinearGradientBrush
>
</
Setter.Value
>
</
Setter
>
<
Setter
Property
=
"Foreground"Value="#FF858585"/>
</
Trigger
>
</
ControlTemplate.Triggers
>
</
ControlTemplate
>
</
Setter.Value
>
</
Setter
>
</
Style
>
注意上面第一行中的x:key=”OkButtonStyle”,那么假设你创建一个button:
Button btn=new Button();
Btn.style=(
Style)Application.Current.FindResource("OkButtonStyle");
这样一个style就定义了按钮的不可用、可用等情况下的显示状态。如果用visual 2008开发的话,那一定是更容易实现了。当然复杂的应用肯定用到一些额外的技术,下面就简单谈谈在开发过程中遇到的部分问题:
1、关于window,wpf中的window不能设置某些扩展属性,如设置不能获取焦点的属性,但是可以处理window消息,处理消息如下代码:
MainHwnd = new WindowInteropHelper(this).Handle;
if (MainHwnd != null && MainHwnd != IntPtr.Zero)
{
m_source = HwndSource.FromHwnd(MainHwnd);
m_source.AddHook(new HwndSourceHook(MessageHookHandler));
}
public
IntPtr MessageHookHandler(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
{
If(msg=0x001)
{
…
.
}
}
…
.
但是如果把window的ShowInTaskbar设为false,它可能收不到任何消息。
在net framework3.0下,如果将window设为可透明,则在待机、锁定等操作后,必须要处理wm_activeapp消息设定无效区域,否则其中的某些组件如画布将不可用。
2、wpf中的线程用法就不一样,在线程中贸然使用ui组件,那是一定会出错的。这样的文章网上很多,最好的我想应该是这篇:“WPF 线程 使用调度程序构建反应速度更快的应用程序”,google一下就可以了。不多说。只是要提醒一下,对通过 Dispatcher 路由的每个工作来说,UI 线程都被阻止,因此使 Dispatcher 完成的工作小而快非常重要,这个我有深刻体会。
3、图形与visual的转换,在wpf中画布(canvas)以及其中的组件(uielement),都可以统称为visual,visaul与图像之间转换,在msdn中有详细介绍,但是在net framework3.0中,将visual转化成图一般采用renderTargetBitmap,这个过程对资源消耗特别大,要小心使用,如果需要将某个visual作为另外一个组件的背景图,最好用
VisualBrush,效果更好。
4、Element的旋转,首先吸引我的是视频组件的旋转,真是太酷了,以前用c++做这样的东西真是费了很大的功夫,效果还不好,这里就简单了,但是如果你自定义一个uielement,旋转然后缩放,就出问题了,究其原因,主要是中心点在旋转之后的位置变化比较奇怪,解决了这个问题,就ok了。
其他心得以后再写,我们这个产品基本上是花了半年时间做了别人做了3年的东西,虽然我们不需要在需求上从零开始,但是就开发时间的来说,算是够快的。产品的性能按专家和各个展览会上反馈的信息就是可以和世界最好的公司去竞争了。这次偶然的开发经历,让我还真对wpf有点兴趣了。以上简单说了一点开发心得,当然wpf还有很多的东西我还没用到,相信聪明的你一定会有更好的发现。
可以用hzcheng@msn.com和我交流