Posted by: Zeeshan Amjad | July 24, 2009

Visual Class in WPF


This abstract class is defined in System.Windows.Media namespace and responsible for all visual type. In other words, whatever display on the screen is inherited from Visual class or its cousin Visual3D class. This class gives the support of hit test, transformation, clipping and bounding box calculation. It is important to note that this class doesn’t provide any high level functionality of WPF such as data binding, lay out, style and event handling. Here is a class diagram of Visual class.

wpf_12

Although this is an abstract class, but just like the DispatcherObject class, none of its function is defined abstract. It means if you simply inherit class from Visual then you can create its instance without overriding any method. Here is a sample code to demonstrate this.

  1: using System;
  2: using System.Windows;
  3: using System.Windows.Media;
  4: 
  5: public class MyVisual : Visual
  6: {
  7: }
  8: 
  9: public class wpf
 10: {
 11:     [STAThread]
 12:     public static void Main()
 13:     {
 14:         Window win = new Window();
 15:         win.Title = "Visual Class";
 16:         win.Width = 300;
 17:         win.Height = 200;
 18: 
 19:         MyVisual v = new MyVisual();
 20:         win.Content = v;
 21: 
 22:         Application app = new Application();
 23:         app.Run(win);
 24:     }
 25: }
 26: 

Here note that we have to include one more namespace System.Windows.Media because Visual class is defined in this namespace.

The output of this program display “MyVisual” inside the window. This is because frame work calls the ToString function if class is not inherited from UIElement class (next class in the class hierarchy chain). Frameworks call OnRender functions for all the classes that are derived from UIElement and ToString otherwise. If we call the ToString function on the instance of “MyVisual” class then we will get the string “MyVisual”. Here is the output of this program.

wpf_13

If we override the ToString function in MyVisual class and return something else then we will see the same string in the output window. Here is an example to demonstrate this.

  1: using System;
  2: using System.Windows;
  3: using System.Windows.Media;
  4: 
  5: public class MyVisual : Visual
  6: {
  7:     public override String ToString()
  8:     {
  9:         return String.Format("This is my Visual class");
 10:     }
 11: }
 12: 
 13: public class wpf
 14: {
 15:     [STAThread]
 16:     public static void Main()
 17:     {
 18:         Window win = new Window();
 19:         win.Title = "Visual Class";
 20:         win.Width = 300;
 21:         win.Height = 200;
 22: 
 23:         MyVisual v = new MyVisual();
 24:         win.Content = v;
 25: 
 26:         Application app = new Application();
 27:         app.Run(win);
 28:     }
 29: }
 30: 

Here is the output of this program.

wpf_14

On the other hand, if we create the object of UIElement class (next class in the hierarchy chain) then frame work will call OnRender function instead of ToString. Here is a sample program to demonstrate this concept.

  1: using System;
  2: using System.Windows;
  3: 
  4: public class wpf
  5: {
  6:     [STAThread]
  7:     public static void Main()
  8:     {
  9:         Window win = new Window();
 10:         win.Title = "UIElement Class";
 11:         win.Width = 300;
 12:         win.Height = 200;
 13: 
 14:         UIElement uie = new UIElement();
 15:         win.Content = uie;
 16: 
 17:         Application app = new Application();
 18:         app.Run(win);
 19:     }
 20: }
 21: 

UIElement class is defined in System.Windows namespace. We are going to explore more about UIElement class in the coming sections.

Its cousin Visual3D class is providing almost the same functionality that Visual class gives. The main difference is it provides services for 3D objects. Visual3D class diagram is simpler than Visual. Here is a class hierarchy of Visual3D class.

 

wpf_15

Visual class is an interface between managed and unmanaged code. It calls the unmanaged DirectX code using milcore.dll. It can be demonstrated with the following diagram.

wpf_16 

Visual is an abstract class so you have to inherit from it to use it. Visual class provides two functions to covert the coordinate of point from screen to the current visual coordinate system. Let’s take a look at example to use one of these functions.

  1: using System;
  2: using System.Windows;
  3: using System.Windows.Media;
  4: using System.Windows.Input;
  5: 
  6: public class MyVisual : Visual
  7: {
  8: }
  9: 
 10: public class MyWindow : Window
 11: {
 12:     private MyVisual mv;
 13: 
 14:     public MyWindow()
 15:     {
 16:         Title = "MyVisual Class";
 17:         Width = 300;
 18:         Height = 200;
 19:         WindowStartupLocation = WindowStartupLocation.CenterScreen;
 20: 
 21:         mv = new MyVisual();
 22:         AddVisualChild(mv);
 23: 
 24:         MouseDown += new MouseButtonEventHandler(MyWindow.OnMouseDown);
 25:     }
 26: 
 27:     static void OnMouseDown(Object sender, MouseButtonEventArgs e)
 28:     {
 29:         MyWindow win = (MyWindow)sender;
 30:         Point point = new Point();
 31:         point.X = e.GetPosition(win).X;
 32:         point.Y = e.GetPosition(win).Y;
 33: 
 34:         Point screenPoint = win.mv.PointToScreen(point);
 35: 
 36:         String str = String.Format("Before Calling PointToScreen ({0}, {1})\nAfter Calling PointToScreen ({2}, {3})",
 37:             point.X, point.Y, screenPoint.X, screenPoint.Y);
 38: 
 39:         win.Content = str;
 40:     }
 41: }
 42: 
 43: public class wpf
 44: {
 45:     [STAThread]
 46:     public static void Main()
 47:     {
 48:         MyWindow win = new MyWindow();
 49: 
 50:         Application app = new Application();
 51:         app.Run(win);
 52:     }
 53: }
 54: 

Visual class need a host container to host its object and host container must be inherited from FrameworkElement class. We have already seen in the class hierarchy that Window class is inherited from FrameworkElement via Control and ContentControl, therefore we can use it as a host container for Visual class object. We call the AddVisualChild method to add the object of Visual class in the host container i.e. in Window.

In this program if user clicks on the window then it will display the coordinate of mouse pointer in visual coordinate and screen coordinate. Also note that here we also have to include System.Windows.Input. Here is the output of this program.

wpf_17


Leave a comment

Categories