Mai 2006 - Einträge

Office 2007

Today I downloaded Microsoft Office 2007 Professional Plus Beta 2.

RSS blogging support and the new data visualization features are very cool. Unfortunately the installation didn’t remove my Office 2003 correctly and Office 2007 is unstable and slow

Besides I really miss the ribbon in Outlook. Although it wouldn’t be that powerful as it is in Word it looks like Microsoft forgot something …

Nevertheless it’s great new Ui with animations everywhere make testing efforts easy.

 

Go ahead and download it: http://www.winfuture.de/

Invoke != Dispatcher.Invoke

Sometimes Applications need to do tasks asynchronly to keep the UI responsible. In .NET you can easily achieve this by using Multithreading e.g. via the ThreadPool.
Since methods created on a different thread than the owner thread of an Ui Control are not allowed to access the Ui objects you need to synchronise your worker threads with your Ui threads. To do this you can easily call Dispatcher.Invoke(methoddelegate, arguments) instead of Method(arguments) and the WPF Dispatcher does the synchronization for you.
With all the ease comes a big performance lag when you call Dispatcher.Invoke. For example the Dispatcher does not check whether you are on the same thread. It synchronizes the call in any way even though it wouldn’t be needed. Besides you should avoid calling Dispatcher.Invoke frequently in a short amount of time.

Test Configuration:
Dell Latitude D810
1,73 Ghz Pentium M
1 GB DDR 2 RAM
Windows Server 2k3 SP1
Visual Studio 2005 Professional; WinFX Feb 05 CTP

Example 1
[code language="VB.NET"]Dim Coll1 As New System.Collections.ObjectModel.ObservableCollection(Of String)
   
For i As Integer = 0 To 20000
 Coll1.Add(System.Guid.NewGuid.ToString)
Next[/code]

Dispatcher Thread / Threadpool Thread
30 ms / crash

Objects are added without synchronization. Fast on the dispatcher thread, crash on any other thread.


Example 2
[code language="VB.NET"]Private Delegate Sub AddDeleagte(ByVal item As String)

Dim Coll2 As New System.Collections.ObjectModel.ObservableCollection(Of String)
   
For i As Integer = 0 To 20000
 Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Normal, New AddDeleagte(AddressOf Coll2.Add), System.Guid.NewGuid.ToString)
Next[/code]

8200 ms / 8200 ms

Objects are added with synchronization. Very slow on the dispatcher thread, slow but safe on any other thread.


Example 3
[code language="VB.NET"]Private Delegate Sub AddDeleagte(ByVal item As String)

Dim Coll3 As New System.Collections.ObjectModel.ObservableCollection(Of String)
   
For i As Integer = 0 To 20000
 If Not Me.Dispatcher.CheckAccess Then Me.Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Normal, New AddDeleagte(AddressOf Coll3.Add), System.Guid.NewGuid.ToString) Else Coll3.Add(System.Guid.NewGuid.ToString)
Next[/code]

30 ms / 8200 ms

Objects are added with synchronization when required. Fast on the dispatcher thread, slow but safe on any other thread.


Example 3 would be safe and fast on the dispatcher thread but maybe we could do more.
If Example 3 was executed on any other thread than the dispatcher thread Dispatcher.Invoke would be called 20000 times. Since calling Dispatcher.Invoke produces a lot of overhead it slows down the application significantly.
The solution is easy: Call a method synchronized that adds the 20000 elements.

Example 4

[code language="VB.NET"]

Private Delegate Sub AddToListDelegate()

Private Sub AddToList()
For i As Integer = 0 To ITEM_COUNT
             Coll3.Add(System.Guid.NewGuid.ToString)
Next
End Sub

If Not Me.Dispatcher.CheckAccess Then Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Normal, New AddToListDelegate(AddressOf AddToList)) Else AddToList()

[/code]

30 ms / 31 ms

 

All objects would be added synchronized when required. Save and fast on any thread.

Conclusion
Consider whether executing methods asynchrously is usefull.
Check your Ui Synchronisation needs.
Try to avoid frequently Ui Synchronisation.

Posted von Jan-Cornelius Molnar mit no comments
Abgelegt unter: ,

HowTo: Implement a notification event on a DependencyProperty change

The only way DependencyProperties tell that something happend to them seems to be via a binding.

So I implemented an DependencyObject that binds to the the property to be watched.

[code language="VB.NET"]

Public Class DependencyProperyChangedHelper(Of T)
    Inherits DependencyObject

    Public Shared ReadOnly ValueProperty As DependencyProperty = DependencyProperty.Register("Value", GetType(T), GetType(DependencyProperyChangedHelper(Of T)))

    Public Sub New(ByVal d As DependencyObject, ByVal propName As String)
        Dim bnd As New Binding(propName)
        bnd.Source = d
        bnd.Mode = BindingMode.OneWay

        System.Windows.Data.BindingOperations.SetBinding(Me, ValueProperty, bnd)
    End Sub

    Public Property Value() As T
        Get
            Return CType(Me.GetValue(ValueProperty), T)
        End Get
        Set(ByVal value As T)
            Me.SetValue(ValueProperty, value)
        End Set
    End Property
End Class

[/code]

You can e.g. assign a binding to a TextBox's TextProperty:

[code language="VB.NET"]Dim autoCompleteHelper As New DependencyProperyChangedHelper(Of String)(Me.txtNotify, "Text")[/code]

The constructor builds a Helper for a String Property on txtNotify named Text.

At the moment the Helper does not do anything else than apply the binding but when you take a closer look at the DependencyProperty.Register overloads you will notify that a PropertyChangedCallback can be supplied:

[code language="VB.NET"]

    Public Shared ReadOnly ValueProperty As DependencyProperty = DependencyProperty.Register("Value", GetType(T), GetType(DependencyProperyChangedHelper(Of T)), New FrameworkPropertyMetadata(New PropertyChangedCallback(AddressOf Value_Changed)))

    Private Shared Sub Value_Changed(ByVal d As DependencyObject, ByVal e As DependencyPropertyChangedEventArgs)
        DirectCast(d, DependencyProperyChangedHelper(Of T)).OnValueChanged(e)
    End Sub

    ' A Clr Event that is raied whenever the value changes
    Public Event ValueChanged As DependencyPropertyChangedEventHandler

    ' A Helper Method to raise the event
    Private Sub OnValueChanged(ByVal e As System.Windows.DependencyPropertyChangedEventArgs)
        RaiseEvent ValueChanged(Me, e)
    End Sub

[/code]

From now on the helper object raises clr events whenever the property it is bound to changes.

Complete Code:

[code language="VB.NET"]

Public Class DependencyProperyChangedHelper(Of T)
    Inherits DependencyObject

    Private mTrackedObject As DependencyObject
    Public Shared ReadOnly ValueProperty As DependencyProperty = DependencyProperty.Register("Value", GetType(T), GetType(DependencyProperyChangedHelper(Of T)), New FrameworkPropertyMetadata(New PropertyChangedCallback(AddressOf Value_Changed)))

    Public Sub New(ByVal d As DependencyObject, ByVal propName As String)
        mTrackedObject = d

        Dim bnd As New Binding(propName)
        bnd.Source = d
        bnd.Mode = BindingMode.OneWay

        System.Windows.Data.BindingOperations.SetBinding(Me, ValueProperty, bnd)
    End Sub

    Public ReadOnly Property TrackedObject() As DependencyObject
        Get
            Return mTrackedObject
        End Get
    End Property

    Public Property Value() As T
        Get
            Return CType(Me.GetValue(ValueProperty), T)
        End Get
        Set(ByVal value As T)
            Me.SetValue(ValueProperty, value)
        End Set
    End Property

    Private Shared Sub Value_Changed(ByVal d As DependencyObject, ByVal e As DependencyPropertyChangedEventArgs)
        DirectCast(d, DependencyProperyChangedHelper(Of T)).OnValueChanged(e)
    End Sub

    Private Sub OnValueChanged(ByVal e As System.Windows.DependencyPropertyChangedEventArgs)
        RaiseEvent ValueChanged(Me, e)
    End Sub

    Public Event ValueChanged As DependencyPropertyChangedEventHandler
End Class

[/code]

Posted von Jan-Cornelius Molnar mit no comments
Abgelegt unter: ,

Custom Chrome in WPF

UPDATE: As WPF evolvs everything becomes easier. An updated version (winfx beta 2) of the article can be found here.

Some of you may have wondered who the creators of Microsoft Max did the Chrome.

Microsoft Max

Although this breaks one of the Top 10 Vista rules I will show how to create a WPF window with custom chrome.

You can't get there by simply setting the border of a WPF Window to None because always a thick border remains. You have to do a work around and create an empty Win32 window and fill it with your own WPF controls.

You can use the HwndSource object to do this. This object is intended to place WPF controls into Win32 Applications but you can also use it to place a WPF control onto your Windows Desktop which is also a Win32 application. HwndSource will call the native function CreateWindowEx and create the window for you.


[code language="VB.NET"]Dim params As HwndSourceParameters = New HwndSourceParameters("CustomChrome 1", 400, 300)
Dim hwnd As HwndSource = New HwndSource(params)
hwnd.RootVisual = New Page1[/code]

This code will create a default window for you. The HwndSourceParameters's constructor sets the Name, Width and Height of the window to create. More parameters will be used later in this article.

HwndSource's RootVisual Property points to the WPF control being displayed by HwndSource.

I created a simple page with a green background:

The Window has still the default Windows Chrome but it's very easy to get rid of it. The key is the HwndSourceParameters object passed to the HwndSource constuctor. The
WindowStyle property lets you define how the window looks like.

[code language="VB.NET"]

Public Const WS_POPUP As Integer = &H80000000
Public Const WS_CLIPCHILDREN As Integer = &H2000000
Public Const WS_VISIBLE As Integer = &H10000000

...

Dim params As HwndSourceParameters = New HwndSourceParameters("CustomChrome 1", 400, 300)
params.WindowStyle = WS_POPUP Or WS_CLIPCHILDREN Or WS_VISIBLE
params.SetPosition(20, 20)Dim hwnd As HwndSource = New HwndSource(params)
hwnd.RootVisual = New Page1

[/code]

Now the Chrome has gone but we aren't finished yet. As you can see, the Max Window
has round corners ours not.


To create a non rectangular Window you need a Region, which can be created by serval API functions. In this special case let's pick CreateRoundRectRgn which creates a rectangle with round corners.

[code language="VB.NET"]Public Declare Auto Function CreateRoundRectRgn Lib "gdi32" Alias "CreateRoundRectRgn" (ByVal X1 As Integer, ByVal Y1 As Integer, ByVal X2 As Integer, ByVal Y2 As Integer, ByVal X3 As Integer, ByVal Y3 As Integer) As IntPtr[/code]

X1 and Y1 define the StartPoint of the region, X2 and Y2 the EndPoint. X3 and Y2
define the radius of the edges.

Now you have to set the Window's region to the created one by calling SetWindowRgn.


[code language="VB.NET"]Public Declare Auto Function SetWindowRgn Lib "user32.dll" (ByVal hWnd As IntPtr, ByVal hRdn As IntPtr, ByVal bRedraw As Boolean) As Integer[/code]


SetWinowRgn requires the Handle to the window whose window region is to be set.
You can get this Handle from HwndSource.Handle.

[code language="VB.NET"]Dim rgn As IntPtrrgn = CreateRoundRectRgn(0, 0, 400, 300, 10, 10)
SetWindowRgn(hwnd.Handle, rgn, True)[/code]

The result should look like this:

I created the Chrome with WPF Elements using Interactive Designer.

Last but not least you have to react on a closing of your window. The Disposed Event
is raised when the window is either closed by ALT+F4 etc. or HwndSource.Dispose is called (Close Method).

[code language="VB.NET"]AddHandler hwnd.Disposed, AddressOf hwnd_Disposed

Private Sub hwnd_Disposed(ByVal sender As Object, ByVal e As EventArgs)
MyApp.Current.Shutdown()
End Sub[/code]

Creating a Window with custom chrome in WPF is very easy. You can define any shape you want by combining regions and use every effect and animation feature you like.

Our Window does not yet support Sizing and Moving but I will continue this tutorial in a few days ;-)

Read On:

Posted von Jan-Cornelius Molnar mit no comments
Abgelegt unter: ,

Panda Internet Security 2006 - Never again!

Nach der Installation von Panda stürtze mein System häufig mit einem BlueScreen ab. Dannach erkannte Windows beschädigte Dateien auf meiner Festplatte. Eine Deinstallation der Software schlug fehl und resultierte darin, dass sich Windows nicht mehr straten lies.

Nach einer Neuinstallation von Windows habe ich lediglich Panda Platinum 2006 Internet Security installiert, um einen Konflikt mit anderer Software auszuschließen. Mein System war nach der Installation stark verlangsamt. Der TruePrevent Dienst verursachte stets 50% CPU-Auslastung. Eine Abschaltung von Panda bewirke nichts, eine Deaktivierung des TruePrevent Dienstes bei den Windows Diensten führte jedoch zu einer Besserung. Jedoch meckerte Panda dannach ständig, dass mein System nicht vollständig geschützt sei.
Auch nach der Deaktivierung von TruePrevent traten Fehler auf. Die Windows Interne ZIP Datei Funktion war nicht mehr benutzbar und führte zum Absturz. Des Weiteren wurde mein Internet spürbar verlangsamt bei 2 MBit DSL. Einige ActiveX PlugIns sind nicht mehr benutzbar. Die Windows Update Funktionen haben seit der Installation sehr lange Reaktionszeiten. Alle Office Produkte haben starke Performance Verluste seit der Installation von Panda Platinum.

Es ist nicht möglich irgendeine Hilfe von Panda Software zu erhalten. In der Online Knowledge Base findet man zu diesen Problemen keine Stellungsnahme. Meine Emails wurden ignoriert und eine Rückgabe des Produkts ist nicht möglich.

Obwohl viele Tests aussagen, dass Panda das vergleichbare Produkt Norton Internet Security 2004 u. 2006 übertreffe, kann ich dem nicht zustimmen. Norton funktioniert mit meinem Sytsem ohne Probleme absolut stabil. Des Weiteren ist der Support von Symantec viel besser.

Abschließend muss ich sagen, dass der Kauf von Panda Platinum 2006 Internet Security eine Fehleintscheidung war. Mein PC (Pentium 4 2,8 GHz HT, 1GB DDR 400 RAM, 200 GB HDD, ATI SAPPHIRE 9200 PRO) wurde durch die Installation unbenutzbar. Eine Deinstallation war nicht mehr möglich und zwang mich Windows neuzuinstallieren.

Ich kann nur den Kauf von Norton Internet Security empfehlen und von jeglicher Panda Software abraten.