2010年8月19日 By xsi640 分类: WPF, WinForm, 未分类

介绍一下如何在实例中相互操作,比如在程序A中调用程序B中的方法,看起来不太可能,不过我们可以利用Win32API来实现。我们需要用到2个Win32函数:

uint RegisterWindowsMessage(string lpString);
注册一个新的窗口消息,该消息确保在系统中是唯一的,返回消息值,可在下面SendMessage函数中调用,如果该消息已经存在,则返回它的消息值

IntPtr SendMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);
向指定的窗口发送消息

IntPtr FindWindow(string IpClassName,string IpWindowName);
查找与指定类名或窗口名相同的顶层窗口句柄

IntPtr WindowProc(IntPtr hwnd, uint msg, IntPtr wParam, IntPtr lParam, ref bool handled);
处理发送给窗口的消息

有了这两个程序就可以实现了,比如说我们在程序B中通过RegisterWindowsMessage函数定义一个字符串为“TestInvoke”的系统消息,再在程序A中,通过RegisterWindowMessage函数获得“TestInvoke”的消息值,再通过FindWindow获得程序B的句柄,通过SendMessage发送给窗口B,窗口B再通过WindowProc处理这个消息,调用相关函数。这个过程看似很复杂,只要我们多加思考,还是很容易理解的。

WindowApp1:

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
    }

    private void button1_Click(object sender, RoutedEventArgs e)
    {
        int handler = FindWindow(null, "WindowApp2");   //查找窗口句柄
        int testInvokeMsg = RegisterWindowMessage("TestInvoke");    //获得TestInvoke消息值
        SendMessage((IntPtr)handler, (uint)testInvokeMsg, IntPtr.Zero, IntPtr.Zero);    //发送消息
    }

    [DllImport("user32.dll")]
    public static extern int RegisterWindowMessage(string msgName);

    [DllImport("user32.dll", CharSet = CharSet.Auto)]
    public static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);

    [DllImport("user32.dll", EntryPoint = "FindWindow")]
    public static extern int FindWindow(string lpClassName, string lpWindowName);
}

WindowApp2:

public partial class MainWindow : Window
{
    int testInvokeMsg = 0;

    public MainWindow()
    {
        InitializeComponent();

        testInvokeMsg = RegisterWindowMessage("TestInvoke");    //获得TestInvoke消息值

        this.SourceInitialized += new EventHandler(MainWindow_SourceInitialized);
    }

    void MainWindow_SourceInitialized(object sender, EventArgs e)
    {
        HwndSource hd = PresentationSource.FromVisual((Visual)sender) as HwndSource;
        hd.AddHook(WindowProc); //添加消息处理函数
    }

    [DllImport("user32.dll")]
    public static extern int RegisterWindowMessage(string msgName);

    public IntPtr WindowProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
    {
        if (msg == testInvokeMsg)
        {
            //TestInvoke处理
            MessageBox.Show("TestInvoke");
        }
        return IntPtr.Zero;
    }
}

代码下载

2010年8月6日 By xsi640 分类: C#

.Net Framework 4.0早已经发布,今天介绍一下ExpandoObject,这个类,这个类是在System.Dynamic这个命名空间下,那么肯定跟动态类型有关,这个类能做什么呢?我们看一下下面的例子:

//实例化扩展类
dynamic obj = new ExpandoObject();
//为对象动态添加成员变量
obj.Name = "张三";
obj.Age = 20;
obj.Birthday = new DateTime(1980, 1, 1);
//为对象动态添加成员方法
obj.Add = new Func<int, int, int>((i, j) => { return i + j; });

//打印输出
Console.WriteLine("姓名:" + obj.Name);
Console.WriteLine("年龄:" + obj.Age);
Console.WriteLine("生日:" + obj.Birthday);
Console.WriteLine("1+2=" + obj.Add(1, 2));

输出:

从上面例子不难看出,ExpandoObject这个类是非常有用的,它可以动态添加成员变量和方法,这样我们在写一些对象时,不需要在new一个class那么麻烦,只要用这个类就可以了,不过,需要注意的是,这个类是在运行时解析的,这样我们就会带来性能上的一些损失,而且,在编写较复杂的逻辑时,不容易发现问题所在,所以,对于简单的对象,我们可以使用这个类,复杂的就不要用了。

2010年7月20日 By xsi640 分类: WPF

Converter可以是在WPF开发过程中经常用到的一个组件,Converter究竟是什么呢?简单的说,Converter给我们提供了一个绑定源到目的过程中的一个转换器。最常见的用途就是,当我们将元数据绑定到用户界面时,因为不能将元数据直接显示到用户界面,我们要将该数据转换成您想要输出的数据显示到用户界面中。

接下来,我们用一个例子说明Converter是如何实现的。这个例子是,我们在元数据中定义1,2,3,显示到界面中确是,红、黄、兰。

ColorConverter.cs

[ValueConversion(typeof(int), typeof(Brush))]
public class ColorConverter : IValueConverter
{
    //数据转换的方法
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        int index = (int)value;
        Brush result = null;
        switch (index)
        {
            case 1:
                result = new SolidColorBrush(Colors.Red);
                break;
            case 2:
                result = new SolidColorBrush(Colors.Yellow);
                break;
            case 3:
                result = new SolidColorBrush(Colors.Blue);
                break;
        }
        return result;
    }

    //转换失败的方法
    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        return null;
    }
}

这里就是Converter的一个实现,只需要继承IValueConverter接口,并实现成员方法。

MainWindow.xaml.cs

public partial class MainWindow : Window
{
    private List<int> _ListData = new List<int>() { 1, 2, 3 };

    public List<int> ListData
    {
        get { return this._ListData; }
    }

    public MainWindow()
    {
        InitializeComponent();
    }
}

这里定义了一个int型的集合,由前台代码进行绑定

MainWindow.xaml

<Window x:Class="ConverterDemo.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:ConverterDemo"
        Title="MainWindow" Height="350" Width="525" x:Name="mainWindow">
    <Window.Resources>
        <local:ColorConverter x:Key="converterColor"/>
    </Window.Resources>
    <Grid>
        <ListView x:Name="lstBox" ItemsSource="{Binding ElementName=mainWindow,Path=ListData}">
            <ListView.ItemTemplate>
                <DataTemplate>
                    <TextBlock FontSize="20" FontWeight="Bold" Text="{Binding}"/>
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>
    </Grid>
</Window>

这里我们暂时不使用Converter看看显示效果

WPF Converter 01

WPF Converter 01

MainWindow.xaml

<Window x:Class="ConverterDemo.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:ConverterDemo"
        Title="MainWindow" Height="350" Width="525" x:Name="mainWindow">
    <Window.Resources>
        <local:ColorConverter x:Key="converterColor"/>
    </Window.Resources>
    <Grid>
        <ListView x:Name="lstBox" ItemsSource="{Binding ElementName=mainWindow,Path=ListData}">
            <ListView.ItemTemplate>
                <DataTemplate>
                    <Border Background="{Binding Converter={StaticResource converterColor}}" Width="300" Height="30">
                        <TextBlock FontSize="20" FontWeight="Bold" Text="{Binding}"/>
                    </Border>
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>
    </Grid>
</Window>

这里,我们先在xaml文档Resource中声明这个Converter,再加入一个Border,并且和它的背景颜色进行绑定,我们看一下效果:

WPF Converter 02

WPF Converter 02

是不是很简单?我们可以通过Converter实现各种类型的转换,如输出数据表格的时候,实际数据是一些枚举值,而显示出来的是我们真正要显示的值。

本文代码

2010年7月15日 By xsi640 分类: Javascript

据国外媒体报道,Mozilla已经到达了全新的发展阶段,全新JaegerMonkey JavaScript引擎的速度要明显快于目前使用的TraceMonkey引擎。Mozilla预计将在9月1日发布JaegerMonkey引擎,因此JaegerMonkey将被整合到Firefox 4.0。

V8基准测试显示,JaegerMonkey引擎积分为6829 ms,TraceMonkey引擎积分为6841 ms。Sunspider测试显示,JaegerMonkey引擎仍然要落后于TraceMonkey引擎——754 ms vs. 718 ms,而且JaegerMonkey引擎运行速度仍然落后于Webkit浏览器,Chrome和Safari的积分都要低于400 ms,Chrome浏览器的积分甚至逼近300 ms。Opera的积分也低于300s。

JaegerMonkey引擎在今年初发布是,其目标是突破Sunspider测试的500 ms大关。当然,这已经无法满足一般用户的需求了,毕竟连IE9开发版积分都已经低于500 ms。Mozilla还表示,JaegerMonkey引擎的目标是要超越竞争浏览器,这就意味着Mozilla的目标是300ms以下。

Mozilla称,JaegerMonkey是重新编写的,过去8周的时间JaegerMonkey已经有很大的改进。在下面6周的时间,Mozilla将完善JaegerMonkey引擎,为9月1日顺利发布做好充分地准备。

Mozilla宣传,JaegerMonkey引擎的运行速度是竞争浏览器10多倍。

2010年7月15日 By xsi640 分类: ASP.NET, Javascript, css

HTML5最近炒的火热,我们今天先说说HTML的发展史,HTML是一种Web浏览器统一语言,是一种标记型语言,从1991年,一个名字叫Tim Berners-Lee编写的一份叫做“HTML标签”的文档发展而来,当时包含了大约20个用来标记网页内容的标签,他直接借用了SGML标记语言,也就是后来的HTML语言。HTML的第一个官方版本是由IETF(互联网工程任务组)推出的版本是2.0,先前由Tim Berners-Lee设计的为HTML 1.0,所以,HTML 1.0并没有官方发布。

后来,由W3C,取代了IETF的工作,成为了HTML的标准组织,此后,HTML被多次修改,直到1999年的HTML 4.01,至此,HTML到达了他的第一个拐点,之后W3C推出了也就是我们现在常用的XHTML 1.0,其实就是XML风格的HTML,是严格按照编码规范HTML的实践,之后,W3C相继推出XHTML1.1,XHTML2,不过,由于XHTML2并不向前兼容,甚至不兼容之前的HTML,这直接加速了XHTML的灭亡,直到2009年,W3C宣布终止XHTML2的工作,XHTML2将不复存在。
在此之前,W3C的闭门造车的作风引起了不满,Opera,Apple,Mozilla的代表开始发表反对声音,2004年Opera的Ian Hickson提议在HTML基础上进行扩展以适应新的Web应用,该提议遭到了W3C的拒绝,于是他们自发组织了超文本应用技术工作组,也就是WHATWG。

从一开始,WHATWG就和W3C走不同的路线,W3C对问题是集体投票,WHATWG则由Ian Hickson定夺,表面上看W3C更民主,而事实上,各种内部纷争会使一些决议陷入泥潭,而WHATWG就会进展的更顺利,不过,Ian Hickson的权力并非无限大,他们的委员可以进行反驳。

开始,WHATWG的工作内容主要是两部分,Web Forms 2.0和Web Apps 1.0,他们都是HTML的扩展,后来,他们合并一起成为现在的HTML5规范。在WHATWG致力于HTML5的同时,W3C也继续他们的XHTML2.0,W3C也慢慢的陷入困境。2006年10月,Web之父Tim Berner-Lee发表了一篇博文,表示HTML走向XML的路是行不通的。几个月后,W3C组建了新的HTML工作组,他们明智的选择了WHATWG的成果,WHATWG的成果作为基础。W3C同时进行这两套规范,XHTML2和HTML 5(W3C的HTML 5中间有个空格,WHATWG的则没有),而WHATWG也在进行着同样的工作。

HTML5的现状是有两个不同的组织再给他制定规范,两个组织有着完全不同的行事风格,最终我们必须面临一个是选择HTML5还是HTML 5的问题。好在现在多款主流浏览器已经对HTML5的应用有了良好的支持,IE9更是将HTML5视为核心,所以,我们不必为HTML5担心,一切都会朝着好的方向发展的。

2010年7月14日 By xsi640 分类: WPF

在实际应用中为了更好的提高用户的交互效率,我们经常在表格中实现这样的功能,如:单击表头标题,实现按这一列自动排序的功能,在WPF中如何实现这一功能呢?我们知道在WPF中显示GridView要使用ListView,那么,我们可以通过继承ListView实现单击表头自动排序的功能。看下面代码

cs代码:

public class SortableListView : ListView
{
    //最后单击的标题
    private GridViewColumnHeader _lastHeaderClicked = null;
    //默认升序
    private ListSortDirection _lastDirection = ListSortDirection.Ascending;

    //排序字段的附加属性
    public static readonly DependencyProperty SortPropertyNameProperty = DependencyProperty.RegisterAttached("SortPropertyName", typeof(string), typeof(SortableListView));
    // 附加属性的Get方法
    public static string GetSortPropertyName(GridViewColumn obj)
    {
        return (string)obj.GetValue(SortPropertyNameProperty);
    }
    //附加属性的Set方法
    public static void SetSortPropertyName(GridViewColumn obj, string value)
    {
        obj.SetValue(SortPropertyNameProperty, value);
    }

    public SortableListView()
    {
        //注册单击标题事件
        this.AddHandler(
            GridViewColumnHeader.ClickEvent,
            new RoutedEventHandler(GridViewColumnHeaderClickedHandler));
    }

    /// <summary>
    /// 排序方法
    /// </summary>
    /// <param name="sortBy">排序字段</param>
    /// <param name="direction">升序/降序</param>
    private void Sort(string sortBy, ListSortDirection direction)
    {
        ICollectionView dataView =
            CollectionViewSource.GetDefaultView(this.ItemsSource);

        if (dataView != null)
        {
            dataView.SortDescriptions.Clear();
            SortDescription sd = new SortDescription(sortBy, direction);
            dataView.SortDescriptions.Add(sd);
            dataView.Refresh();
        }
    }

    //单击标题调用的方法
    private void GridViewColumnHeaderClickedHandler(object sender, RoutedEventArgs e)
    {
        GridViewColumnHeader headerClicked = e.OriginalSource as GridViewColumnHeader;
        ListSortDirection direction;

        if (headerClicked != null &&
            headerClicked.Role != GridViewColumnHeaderRole.Padding)
        {
            if (headerClicked != _lastHeaderClicked)
            {
                direction = ListSortDirection.Ascending;
            }
            else
            {
                if (_lastDirection == ListSortDirection.Ascending)
                {
                    direction = ListSortDirection.Descending;
                }
                else
                {
                    direction = ListSortDirection.Ascending;
                }
            }
            //获得排序字段
            string sortBy = SortableListView.GetSortPropertyName(headerClicked.Column);
            if (string.IsNullOrEmpty(sortBy))
            {
                sortBy = headerClicked.Column.Header as string;
            }
            //排序操作
            this.Sort(sortBy, direction);

            _lastHeaderClicked = headerClicked;
            _lastDirection = direction;
        }
    }
}

xaml代码:

<local:SortableListView x:Name="lstView">
    <local:SortableListView.View>
        <GridView>
            <GridViewColumn Width="50" Header="ID" DisplayMemberBinding="{Binding ID}" local:SortableListView.SortPropertyName="ID"/>
            <GridViewColumn Width="100" Header="姓名" DisplayMemberBinding="{Binding Name}" local:SortableListView.SortPropertyName="Name"/>
            <GridViewColumn Width="50" Header="年龄" DisplayMemberBinding="{Binding Age}" local:SortableListView.SortPropertyName="Age"/>
            <GridViewColumn Width="200" Header="生日" DisplayMemberBinding="{Binding Birthday}" local:SortableListView.SortPropertyName="Birthday"/>
        </GridView>
    </local:SortableListView.View>
</local:SortableListView>

我们给ListView添加一个附加属性,定义排序的字段名称,通过构造函数注册单击标题的事件,当单击标题时,激发该事件时,进行排序操作。在xaml文件中,我们只要指定排序字段即SortableListView.SortPropertyName属性即可。

代码下载

2010年7月14日 By xsi640 分类: WPF

WPF中引入了一个非常重要的“新的类型”叫依赖属性,在WPF中我们会经常用到它,他是贯穿WPF中实现数据绑定、动画效果等特效的实现。依赖属性,是依靠多个数据或者程序来为它提供值的,这些数据可能随时会改变,依赖属性的值也会随之改变,或是从上级元素传递过来的值。依赖属性最大的特性就是为我们提供了变更通知的能力。
依赖属性给我们提供了那些特性呢?
1.变更通知
2.属性值继承
3.对多提供程序的支持

如何定义一个依赖属性呢?

public class TextBoxEx : TextBox
{
 public static readonly DependencyProperty IsFocusProperty =
 DependencyProperty.Register("IsFocus",                  //依赖属性的名称
 typeof(bool),               //依赖属性的类型
 typeof(TextBoxEx),          //依赖属性所有者的类型
 new PropertyMetadata(false, new PropertyChangedCallback(OnIsFocusPropertyChanged)) //元数据(初始值false,数据发生变化的委托OnIsFocusPropertyChanged)
 );

 public bool IsFocus
 {
 get { return (bool)this.GetValue(IsFocusProperty); }
 set { this.SetValue(IsFocusProperty, value); }
 }

 private static void OnIsFocusPropertyChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)
 {
 //数据发生变化的实现
 }
}

这就是一个依赖属性最简单的定义,我们不需要实现它的具体方法,就可以直接使用它的一系列特性。例如:在xaml中的数据绑定等

2010年7月8日 By xsi640 分类: WPF

在WPF中如何将一张彩色图片变成灰色的,可以用WPF给我们的bitmap转换器完成,或者使用算法将彩色的rgb转化成灰色rgb。这种效果用的地方很多,比如QQ头像离线时头像会变成灰色。
下面我们看一下代码:
第一种:

FormatConvertedBitmap bitmap = new FormatConvertedBitmap();
bitmap.BeginInit();
bitmap.Source = (BitmapSource)source;
bitmap.DestinationFormat = PixelFormats.Gray32Float;
bitmap.EndInit();
return bitmap;

第二种:

BitmapSource sourceImage = (BitmapSource)source;
byte[] orgPixels = new byte[sourceImage.PixelHeight * sourceImage.PixelWidth * 4];
byte[] newPixels = new byte[orgPixels.Length];
sourceImage.CopyPixels(orgPixels, sourceImage.PixelWidth * 4, 0);
for (int i = 3; i < orgPixels.Length; i += 4)
{
    int grayVal = ((int)orgPixels[i - 3] +
    (int)orgPixels[i - 2] + (int)orgPixels[i - 1]);
    if (grayVal != 0)
        grayVal = grayVal / 3;
    newPixels[i] = orgPixels[i]; //Set AlphaChannel
    newPixels[i - 3] = (byte)grayVal;
    newPixels[i - 2] = (byte)grayVal;
    newPixels[i - 1] = (byte)grayVal;
}
return BitmapSource.Create(sourceImage.PixelWidth, sourceImage.PixelHeight, 96, 96, PixelFormats.Bgra32, null, newPixels, sourceImage.PixelWidth * 4);

从上面两种方式都会返回灰阶的ImageSource对象,不难看出,第一种要简单的多,使用wpf内置FormatConvertedBitmap类进行图像格式转换,要方便的多,同时也给我们提供了非常丰富的转换格式,通过设置DestinationFormat属性就可以方便的将图像转换成各种格式。

2010年6月23日 By admin 分类: WPF

同步和异步操作是我们在C/S开发过程中要经常使用的,下面我们来介绍一下WPF中的同步和异步操作。

先来看一下什么是同步、异步:

同步:当前操作在执行过程中,要执行另一个操作,必须等待当前操作完成后,再执行另一个操作。

异步:和同步相反,当前操作在执行过程中,要执行另一个操作,无需等待当前操作完成,即可执行另一个操作,两个操作互不干扰。

那么,在WPF中如何进行同步异步操作呢?看代码。

同步:

Action action = new Action(delegate() {
    Thread.Sleep(5000);
    MessageBox.Show("123");
});
action.Invoke();

异步:

Action action = new Action(delegate() {
    Thread.Sleep(5000);
    MessageBox.Show("123");
});
action.BeginInvoke(null, null);

两段代码中,我们分别实力话了两个委托,一个用Invoke()方法同步调用,一个用BeginInvoke(null,null)方法异步调用。实际开发过程中,如果,我们使用异步操作时,直接操作对主窗体的对象时,会出现“调用线程无法访问此对象,因为另一个线程拥有该对象。”这样的一个异常,这是因为,我们在异步操作过程中,实际上wpf会新建一个线程处理异步操作,而这个线程是无法访问UI线程的,所以我们要这样在异步中操作主窗口的对象:

Action action = new Action(delegate()
{
    Thread.Sleep(5000);
    Dispatcher.BeginInvoke(new Action(delegate()
    {
        this.txtbTime.Text = "123";//操作主窗口的对象
    }), null);
});
action.BeginInvoke(null, null);

WPF的同步、异步操作,其实和Winform的没什么太多的不同。大家了多用用就明白了。

2010年5月29日 By xsi640 分类: ASP.NET, C#, Silverlight, WCF, WPF, WinForm, 软件下载

微软MSDN简体中文版、繁体中文版已经从MSDN上正式发布,有MSDN账号的网友可以直接下载,没有的网友可以从下面地址下载,由于刚出啦不久,目前只有电驴资源,大家可以用迅雷下载。

注:下面地址的版本已经包含序列号,这下大家省心了,呵呵

MSDN Visual Studio 2010 Professional简体中文版本:
ed2k://|file|cn_visual_studio_2010_professional_x86_dvd_532145.iso|2591844352|6001253431AFE573E4344F5A0B1D9CAC|/

MSDN Visual Studio 2010 Ultimate简体中文版本:
ed2k://|file|cn_visual_studio_2010_ultimate_x86_dvd_532347.iso|2685982720|4AE6228933DDE49D9BFA4C3467C831C2|/

MSDN Team Foundation Server简体中文版本:
ed2k://|file|cn_visual_studio_team_foundation_server_2010_x86_x64_dvd_531909.iso|1963589632|C9C77B2707DF100621B3FB653C285524|/

MSDN Visual Studio 2010 Ultimate繁體中文版本:
ed2k://|file|ct_visual_studio_2010_ultimate_x86_dvd_532348.iso|2691330048|BF50926EAB061C7D0D92580F4132F9EA|/

MSDN Team Foundation Server繁體中文版本:
ed2k://|file|ct_visual_studio_team_foundation_server_2010_x86_x64_dvd_531915.iso|1966714880|D6BD12D5B693E7EDA545D52FB54CC8E5|/