Paul blog

Explaining thoughts and findings is a great way to learn
CodeProject MVP for 2010

I have been awarded a CodeProject MVP for the articles I wrote in 2009. Thanks Codeproject for this recognition, which will encourage me to keep my passion on writing article.

I love CodeProject.

Thanks All.

Razan

My CodeProject Profile

Implementation of Auto Logoff based on User Inactivity in WPF Application

In some applications, we need to implement Auto logoff feature for security reason. In auto log off feature, the application redirects the user into login window, if the user remains inactive for a certain amount of time. I have just published how I came up with implementing auto logoff feature based on user inactivity in WPF application.

Here it is:

http://www.codeproject.com/KB/WPF/AutologoffWPF.aspx

Making a Drop Down Style Custom Color Picker in WPF

Although WPF provides quite a rich collection of UI controls and components for development, a particular control has been missing. That is a color-picker control. I have just published how I came up with making a drop down style custom color picker in WPF.

Here it is:

http://www.codeproject.com/KB/WPF/WPFDropDownColorPicker.aspx

Perspective camera animation on a cube in WPF 3D

I have started WPF 3D at my work. Actually, i wanted  to make roll animation effect using WPF 3D. After some R&D, I came up with roll animation using 2D animation, which I described in my previous blog post. At first, I tried to make roll animation using perspective camera rotation.  For that, I have made a sample program, which I am discussing in this blog post. In this sample program, a 3D cube rotates along the y-axis. The animation looks like the following:

fun

To rotate a 3D figure, you have to change the projection point. As camera is used for projection in WPF 3D, here a camera is being moved around the 3D figure to achieve rotate animation in y-direction.

How are images painted on cube surface?

You can make an image brush for any image and a visual brush from any visual. We have no special brushes for 3D graphics and we have to use two-dimensional brushes to paint the surfaces of three-dimensional figures. Material is created from brush. Texture coordinates are used to map which part of the material shows up on which part of the surfaces of three-dimensional figures.

Each GeometryModel3D consists of one MeshGeometry3D and one object of type Material, so we can use only one brush for one MeshGeometry3D figure. To use different brushes for different faces of cube, i have splited the figure into multiple GeometryModel3D objects.

The used c# code for this animation is in the following

   1: public partial class Window1 : Window
   2:   {
   3:       DispatcherTimer _timer = null;
   4:       PerspectiveCamera _perspectiveCamera = null;
   5:       double _angle = 0;        
   6:  
   7:       public Window1()
   8:       {
   9:           this.InitializeComponent();
  10:           this.Loaded += new RoutedEventHandler(Window1_Loaded);
  11:       }
  12:  
  13:       void Window1_Loaded(object sender, RoutedEventArgs e)
  14:       {
  15:           GenerateViewPort();
  16:       }       
  17:  
  18:       private void GenerateViewPort()
  19:       {
  20:           MakeCamera();
  21:  
  22:           Viewport3D Viewport3D1 = new Viewport3D();
  23:           Viewport3D1.Camera = _perspectiveCamera;
  24:           grdAniContainer.Children.Add(Viewport3D1);
  25:           Viewport3D1.Loaded += new RoutedEventHandler(Viewport3D1_Loaded);
  26:  
  27:           ModelVisual3D ModelVisual3D1 = new ModelVisual3D();
  28:           Viewport3D1.Children.Add(ModelVisual3D1);
  29:  
  30:  
  31:           Model3DGroup Model3DGroup1 = new Model3DGroup();
  32:           ModelVisual3D1.Content = Model3DGroup1;
  33:  
  34:           AmbientLight AmbientLight1 = new AmbientLight();
  35:           AmbientLight1.Color = Colors.Gray;
  36:           Model3DGroup1.Children.Add(AmbientLight1);
  37:  
  38:           DirectionalLight DirectionalLight1 = new DirectionalLight();
  39:           DirectionalLight1.Color = Colors.Gray;
  40:           DirectionalLight1.Direction = ((Vector3D)new Vector3DConverter().ConvertFromString("-1,-3,-2"));
  41:           Model3DGroup1.Children.Add(DirectionalLight1);
  42:  
  43:           DirectionalLight1 = new DirectionalLight();
  44:           DirectionalLight1.Color = Colors.Gray;
  45:           DirectionalLight1.Direction = ((Vector3D)new Vector3DConverter().ConvertFromString("1,-2,3"));
  46:           Model3DGroup1.Children.Add(DirectionalLight1);
  47:  
  48:           Model3DGroup Model3DGroup2 = new Model3DGroup();
  49:           Model3DGroup1.Children.Add(Model3DGroup2);
  50:  
  51:           GeometryModel3D GeometryModel3D1 = new GeometryModel3D();
  52:           Model3DGroup2.Children.Add(GeometryModel3D1);
  53:  
  54:  
  55:           MeshGeometry3D MeshGeometry3D1 = new MeshGeometry3D();
  56:           MeshGeometry3D1.Positions = ((Point3DCollection)new Point3DCollectionConverter().ConvertFromString("-1,-1,-1 1,-1,-1 1,-1,1 -1,-1,1"));
  57:           MeshGeometry3D1.TriangleIndices = ((Int32Collection)new Int32CollectionConverter().ConvertFromString("0,1,2 0,2,3"));
  58:           MeshGeometry3D1.TextureCoordinates = ((PointCollection)new PointCollectionConverter().ConvertFromString("0,0 0,1 1,1 1,0"));
  59:           GeometryModel3D1.Geometry = MeshGeometry3D1;
  60:  
  61:          
  62:           DiffuseMaterial DiffuseMaterial1 = new DiffuseMaterial();
  63:           GeometryModel3D1.Material = DiffuseMaterial1;
  64:  
  65:  
  66:           ImageBrush ImageBrush1 = new ImageBrush();
  67:           ImageBrush1.ImageSource = loadBitmap(Fun.Resource1.DSC06460);
  68:           DiffuseMaterial1.Brush = ImageBrush1;
  69:  
  70:           GeometryModel3D GeometryModel3D2 = new GeometryModel3D();
  71:           Model3DGroup2.Children.Add(GeometryModel3D2);
  72:  
  73:  
  74:           MeshGeometry3D1 = new MeshGeometry3D();
  75:           MeshGeometry3D1.Positions = ((Point3DCollection)new Point3DCollectionConverter().ConvertFromString("1,1,1 1,1,-1 -1,1,-1 -1,1,1"));
  76:           MeshGeometry3D1.TriangleIndices = ((Int32Collection)new Int32CollectionConverter().ConvertFromString("0,1,2 0,2,3"));
  77:           MeshGeometry3D1.TextureCoordinates = ((PointCollection)new PointCollectionConverter().ConvertFromString("0,0 0,1 1,1 1,0"));
  78:           GeometryModel3D2.Geometry = MeshGeometry3D1;
  79:  
  80:  
  81:           DiffuseMaterial DiffuseMaterial2 = new DiffuseMaterial();
  82:           GeometryModel3D2.Material = DiffuseMaterial2;
  83:  
  84:  
  85:           ImageBrush1 = new ImageBrush();
  86:           ImageBrush1.ImageSource = loadBitmap(Fun.Resource1.DSC06461);
  87:           DiffuseMaterial2.Brush = ImageBrush1;
  88:  
  89:           GeometryModel3D GeometryModel3D3 = new GeometryModel3D();
  90:           Model3DGroup2.Children.Add(GeometryModel3D3);
  91:  
  92:  
  93:           MeshGeometry3D1 = new MeshGeometry3D();
  94:           MeshGeometry3D1.Positions = ((Point3DCollection)new Point3DCollectionConverter().ConvertFromString("-1,1,-1 -1,-1,-1 -1,-1,1 -1,1,1"));
  95:           MeshGeometry3D1.TriangleIndices = ((Int32Collection)new Int32CollectionConverter().ConvertFromString("0,1,2 0,2,3"));
  96:           MeshGeometry3D1.TextureCoordinates = ((PointCollection)new PointCollectionConverter().ConvertFromString("0,0 0,1 1,1 1,0"));
  97:           GeometryModel3D3.Geometry = MeshGeometry3D1;
  98:  
  99:  
 100:           DiffuseMaterial DiffuseMaterial3 = new DiffuseMaterial();
 101:           GeometryModel3D3.Material = DiffuseMaterial3;
 102:  
 103:  
 104:           ImageBrush1 = new ImageBrush();
 105:           ImageBrush1.ImageSource = loadBitmap(Fun.Resource1.DSC06462);
 106:           DiffuseMaterial3.Brush = ImageBrush1;
 107:  
 108:           GeometryModel3D GeometryModel3D4 = new GeometryModel3D();
 109:           Model3DGroup2.Children.Add(GeometryModel3D4);
 110:  
 111:  
 112:           MeshGeometry3D1 = new MeshGeometry3D();
 113:           MeshGeometry3D1.Positions = ((Point3DCollection)new Point3DCollectionConverter().ConvertFromString("1,1,1 1,-1,1 1,-1,-1 1,1,-1"));
 114:           MeshGeometry3D1.TriangleIndices = ((Int32Collection)new Int32CollectionConverter().ConvertFromString("0,1,2 0,2,3"));
 115:           MeshGeometry3D1.TextureCoordinates = ((PointCollection)new PointCollectionConverter().ConvertFromString("0,0 0,1 1,1 1,0"));
 116:           GeometryModel3D4.Geometry = MeshGeometry3D1;
 117:  
 118:  
 119:           DiffuseMaterial DiffuseMaterial4 = new DiffuseMaterial();
 120:           GeometryModel3D4.Material = DiffuseMaterial4;
 121:  
 122:  
 123:           ImageBrush1 = new ImageBrush();
 124:           ImageBrush1.ImageSource = loadBitmap(Fun.Resource1.DSC06463);
 125:           DiffuseMaterial4.Brush = ImageBrush1;
 126:  
 127:           GeometryModel3D GeometryModel3D5 = new GeometryModel3D();
 128:           Model3DGroup2.Children.Add(GeometryModel3D5);
 129:  
 130:  
 131:           MeshGeometry3D1 = new MeshGeometry3D();
 132:           MeshGeometry3D1.Positions = ((Point3DCollection)new Point3DCollectionConverter().ConvertFromString("1,1,-1 1,-1,-1 -1,-1,-1 -1,1,-1"));
 133:           MeshGeometry3D1.TriangleIndices = ((Int32Collection)new Int32CollectionConverter().ConvertFromString("0,1,2 0,2,3"));
 134:           MeshGeometry3D1.TextureCoordinates = ((PointCollection)new PointCollectionConverter().ConvertFromString("0,0 0,1 1,1 1,0"));
 135:           GeometryModel3D5.Geometry = MeshGeometry3D1;
 136:  
 137:  
 138:           DiffuseMaterial DiffuseMaterial5 = new DiffuseMaterial();
 139:           GeometryModel3D5.Material = DiffuseMaterial5;
 140:  
 141:  
 142:           ImageBrush1 = new ImageBrush();
 143:           ImageBrush1.ImageSource = loadBitmap(Fun.Resource1.DSC06460);
 144:           DiffuseMaterial5.Brush = ImageBrush1;
 145:  
 146:           GeometryModel3D GeometryModel3D6 = new GeometryModel3D();
 147:           Model3DGroup2.Children.Add(GeometryModel3D6);
 148:  
 149:  
 150:           MeshGeometry3D1 = new MeshGeometry3D();
 151:           MeshGeometry3D1.Positions = ((Point3DCollection)new Point3DCollectionConverter().ConvertFromString("-1,1,1 -1,-1,1 1,-1,1 1,1,1"));
 152:           MeshGeometry3D1.TriangleIndices = ((Int32Collection)new Int32CollectionConverter().ConvertFromString("0,1,2 0,2,3"));
 153:           MeshGeometry3D1.TextureCoordinates = ((PointCollection)new PointCollectionConverter().ConvertFromString("0,0 0,1 1,1 1,0"));
 154:           GeometryModel3D6.Geometry = MeshGeometry3D1;
 155:  
 156:           DiffuseMaterial DiffuseMaterial6 = new DiffuseMaterial();
 157:           GeometryModel3D6.Material = DiffuseMaterial6;           
 158:  
 159:           VisualBrush VisualBrush1 = new VisualBrush();
 160:           DiffuseMaterial6.Brush = VisualBrush1;
 161:           Label Label1 = new Label();
 162:           Label1.Content = "Razan";
 163:           Label1.Foreground = new SolidColorBrush(Colors.Orchid);
 164:           Label1.Background = GetRectangleDrawingBrush();
 165:           VisualBrush1.Visual = Label1;            
 166:       }
 167:  
 168:       private void MakeCamera()
 169:       {
 170:           Transform3DGroup transform3DGroup = new Transform3DGroup();
 171:           RotateTransform3D rotateTransform3D_1 = new RotateTransform3D();
 172:           AxisAngleRotation3D axisAngleRotation3D_1 = new AxisAngleRotation3D(new Vector3D(0, 1, 0), 0);
 173:  
 174:  
 175:           transform3DGroup.Children.Add(rotateTransform3D_1);
 176:  
 177:  
 178:           _perspectiveCamera = new PerspectiveCamera();
 179:           _perspectiveCamera.Position = new Point3D(0, 0, 5);
 180:           _perspectiveCamera.LookDirection = new Vector3D(0, 0, -5);
 181:           _perspectiveCamera.UpDirection = new Vector3D(0, 1, 0);
 182:           _perspectiveCamera.FieldOfView = 45;
 183:           _perspectiveCamera.Transform = transform3DGroup;
 184:       }
 185:       private DrawingBrush GetRectangleDrawingBrush()
 186:       {         
 187:  
 188:           DrawingBrush DrawingBrush1 = new DrawingBrush();
 189:           DrawingBrush1.Viewport = ((Rect)new RectConverter().ConvertFromString("0,0,0.25,0.25"));
 190:           DrawingBrush1.TileMode = TileMode.Tile;
 191:            
 192:  
 193:           DrawingGroup DrawingGroup1 = new DrawingGroup();
 194:           DrawingBrush1.Drawing = DrawingGroup1;
 195:  
 196:           GeometryDrawing GeometryDrawing1 = new GeometryDrawing();
 197:           GeometryDrawing1.Brush = ((Brush)new BrushConverter().ConvertFromString("White"));
 198:           DrawingGroup1.Children.Add(GeometryDrawing1);
 199:  
 200:  
 201:           RectangleGeometry RectangleGeometry1 = new RectangleGeometry();
 202:           RectangleGeometry1.Rect = ((Rect)new RectConverter().ConvertFromString("0,0,100,100"));
 203:           GeometryDrawing1.Geometry = RectangleGeometry1;
 204:  
 205:           GeometryDrawing GeometryDrawing2 = new GeometryDrawing();
 206:           DrawingGroup1.Children.Add(GeometryDrawing2);
 207:  
 208:  
 209:           GeometryGroup GeometryGroup1 = new GeometryGroup();
 210:           GeometryDrawing2.Geometry = GeometryGroup1;
 211:  
 212:           RectangleGeometry1 = new RectangleGeometry();
 213:           RectangleGeometry1.Rect = ((Rect)new RectConverter().ConvertFromString("0,0,50,50"));
 214:           GeometryGroup1.Children.Add(RectangleGeometry1);
 215:  
 216:           RectangleGeometry1 = new RectangleGeometry();
 217:           RectangleGeometry1.Rect = ((Rect)new RectConverter().ConvertFromString("50,50,50,50"));
 218:           GeometryGroup1.Children.Add(RectangleGeometry1);
 219:  
 220:  
 221:           LinearGradientBrush LinearGradientBrush1 = new LinearGradientBrush();
 222:           GeometryDrawing2.Brush = LinearGradientBrush1;
 223:  
 224:           GradientStop GradientStop1 = new GradientStop();
 225:           GradientStop1.Offset = 0.0;
 226:           GradientStop1.Color = Colors.Black; 
 227:           LinearGradientBrush1.GradientStops.Add(GradientStop1);
 228:  
 229:           GradientStop1 = new GradientStop();
 230:           GradientStop1.Offset = 1.0;
 231:           GradientStop1.Color = Colors.Gray; 
 232:           LinearGradientBrush1.GradientStops.Add(GradientStop1);
 233:  
 234:           return DrawingBrush1;
 235:  
 236:       }
 237:  
 238:  
 239:       void Viewport3D1_Loaded(object sender, RoutedEventArgs e)
 240:       {
 241:           _timer = new DispatcherTimer();
 242:           _timer.Interval = TimeSpan.FromSeconds(.25);
 243:           _timer.Tick += new EventHandler(_timer_Tick);
 244:           _timer.IsEnabled = true;
 245:       }
 246:       
 247:       void _timer_Tick(object sender, EventArgs e)
 248:       {
 249:           Transform3DGroup transform3DGroup = new Transform3DGroup();
 250:           RotateTransform3D rotateTransform3D_1 = new RotateTransform3D();
 251:           AxisAngleRotation3D axisAngleRotation3D_1 = new AxisAngleRotation3D(new Vector3D(0, 1, 0), _angle );
 252:           rotateTransform3D_1.Rotation = axisAngleRotation3D_1;          
 253:           transform3DGroup.Children.Add(rotateTransform3D_1);             
 254:           _perspectiveCamera.Transform = transform3DGroup;
 255:           _angle = _angle + 2;
 256:       }
 257:       public static BitmapSource loadBitmap(System.Drawing.Bitmap source)
 258:       {
 259:           return System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(source.GetHbitmap(), IntPtr.Zero, Int32Rect.Empty,
 260:               System.Windows.Media.Imaging.BitmapSizeOptions.FromEmptyOptions());
 261:       }
 262:   }

How is this animation achieved?

Here we have used perspective camera for projection. To make this animation, I have rotated perspective camera in y direction. As we know second point of vector 3D indicates y coordinate. So AxisAngleRotation3D(new Vector3D(0, 1, 0), _angle ) directs to rotate the 3D object(here cube) to rotate _angle degree in y-axis. Here at each tick event, we have incremented the value of _angle, so it rotates in y direction. If you would like to rotate in x direction you can use AxisAngleRotation3D(new Vector3D(1, 0, 0), _angle ), then it will rotate in x-direction. Here visual brush is used to paint label UIelement, which contains "Razan".

The used XAML for this is in the following:

   1: <Window
   2:     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
   3:     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
   4:     x:Class="Fun.Window1"
   5:     x:Name="Window"
   6:     Title="Fun"
   7:     Height="400" Width="400">
   8:     <Grid Name="grdAniContainer"></Grid>
   9: </Window>

You can download the sample code from here. Hope this will save some of your time.

Creating a Roll animation effect in WPF

I know one picture can tell what the Roll animation looks like instead of writing many sentences. The animation looks like the following:

roll

Opacity masks allow us to make portions of a UIelement or visual either transparent or partially transparent. To apply opacity mask, we can assign a brush to the Opacity Mask property of an element or Visual to provide a mask to the opacity. There is a variety of brushes in WPF: Solid Color Brush, Image Brush, Linear Gradient Brush, and Visual Brush. You can apply any of them you want. The regions, which are not covered by the mask, will remain transparent. The Alpha value of ARGB is used to specify the opacity of the color. An alpha value of 00 indicates completely transparent color and an alpha value of FF indicates fully opaque

How can we give an image 3D look in WPF?

We have used transparent Gradient Stop to give the image 3D look. We have made a Linear Gradient Brush with some gradient stops where centre, top, and bottom  are transparent. Then we set the LinearGradientBrush as the opacity mask of Image.

How can we  reverse the image?

To reverse the image here i have used scale transform. As we want to reverse the image in y Direction so the scale value for y-axis is -1 and scale value for x-axis is 1.

The used c# code for Roll animation is in the following

   1: public partial class Window1 : Window
   2:    {
   3:        DispatcherTimer _timer = null;
   4:        double _rollTopLeft = 0;
   5:        double _imageWidth = 400;
   6:        double _imageHeight = 300;
   7:        double _offset = 3;
   8:        double _3DSize = 50;
   9:        public Window1()
  10:        {
  11:            InitializeComponent();
  12:            this.Loaded += new RoutedEventHandler(Window1_Loaded);
  13:        }
  14:        void Window1_Loaded(object sender, RoutedEventArgs e)
  15:        {      
  16:            LinearGradientBrush maskBrush = new LinearGradientBrush();
  17:            maskBrush.StartPoint = new Point(0, 0);
  18:            maskBrush.EndPoint = new Point(0, 1);
  19:  
  20:            GradientStop BlackStop1 = new GradientStop(Color.FromArgb(30, 255, 255, 255), 0.0);
  21:            GradientStop BlackStop3 = new GradientStop(Colors.Black, 0.0);
  22:            GradientStop BlackStop4 = new GradientStop(Colors.Black, .9);
  23:            GradientStop transparentStop = new GradientStop(Color.FromArgb(175, 255, 255, 255), .5);
  24:            GradientStop BlackStop2 = new GradientStop(Color.FromArgb(100, 255, 255, 255), 1);
  25:  
  26:            maskBrush.GradientStops.Add(BlackStop1);
  27:            maskBrush.GradientStops.Add(transparentStop);
  28:            maskBrush.GradientStops.Add(BlackStop2);
  29:            maskBrush.GradientStops.Add(BlackStop3);
  30:            maskBrush.GradientStops.Add(BlackStop4);
  31:  
  32:            CanAni.OpacityMask = maskBrush;
  33:          
  34:            _timer = new DispatcherTimer();
  35:            _timer.Interval = TimeSpan.FromSeconds(.1);
  36:            _timer.Tick += new EventHandler(_timer_Tick);
  37:            _timer.IsEnabled = true;
  38:        }
  39:  
  40:        void _timer_Tick(object sender, EventArgs e)
  41:        {
  42:            Image im = new Image();
  43:            im.Width = _imageWidth;
  44:            im.Height = _imageHeight;
  45:            im.Source = loadBitmap(RollAnimation.Properties.Resources.bedrijven3);    
  46:            ScaleTransform scaleTransform = new ScaleTransform(1, -1, 0, 0);
  47:            im.LayoutTransform = scaleTransform;
  48:  
  49:            _rollTopLeft = _rollTopLeft + _offset;
  50:            image.Source = loadBitmap(RollAnimation.Properties.Resources.bedrijven3);
  51:            image.Clip = new RectangleGeometry(new Rect(0, 0, _imageWidth, _rollTopLeft));
  52:  
  53:            double yPosition = _rollTopLeft + _3DSize;
  54:            double height = _3DSize;
  55:            if (Math.Abs((_imageHeight - _rollTopLeft)) < _3DSize)
  56:            {
  57:                height = Math.Abs(image.Height - _rollTopLeft);
  58:                CanAni.Height = height;
  59:                CanWrap.Height = height;
  60:                yPosition = _rollTopLeft;
  61:                Linetwo.Y1 = height;
  62:                Linetwo.Y2 = height;
  63:            }
  64:            Lineone.Visibility = Visibility.Visible;
  65:            Linetwo.Visibility = Visibility.Visible;
  66:            if (_imageHeight == _rollTopLeft)
  67:            {
  68:                _timer.IsEnabled = false;
  69:                Lineone.Visibility = Visibility.Collapsed;
  70:                Linetwo.Visibility = Visibility.Collapsed;
  71:            }
  72:            im.Clip = new RectangleGeometry(new Rect(0, yPosition, _imageWidth, height));
  73:            VisualBrush vb = new VisualBrush(im as Visual);
  74:            CanAni.Background = vb;
  75:            Canvas.SetTop(CanWrap, _rollTopLeft);
  76:        }
  77:        public static BitmapSource loadBitmap(System.Drawing.Bitmap source)
  78:        {
  79:            return System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(source.GetHbitmap(), IntPtr.Zero, Int32Rect.Empty,
  80:                System.Windows.Media.Imaging.BitmapSizeOptions.FromEmptyOptions());
  81:        }
  82:    }

Here four canvases are used here. The outer canvas is the main container for this application. The second canvas is used to wrap necessary UIelements to achieve this animation. The third canvas is used to make transparent portions while the fourth canvas is used to achieve 3D look. I have set an image background to the fourth canvas clipping certain portion of the image. To make this canvas moving, I am changing the top position of the canvas continuously.

This trick is applicable to any UIelement type. Here I have taken image as the UIelement type to implement the Roll animation. I have calculated the height and width of the image and started animation from (0,0) point. Every WPF UIelement type has a clip property and you can set any geometry object to clip. However, for this animation, we have used Rectangle geometry as clip geometry.

As I am changing the brush of animated canvas at runtime, property based animation does not work here. For that reason, I have used dispatcher timer based animation. I am using here dispatcher timer instead of classic Timer as dispatcher timer runs in UI thread and I do not need to write thread switching code

The used XAML for this is in the following

   1: <Window x:Class="RollAnimation.Window1"
   2:     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
   3:     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
   4:     Title="Roll Animation" Height="600" Width="600">
   5:     <Canvas  x:Name="CanOuter" Height="300" Width="400">
   6:         <Image  Canvas.Left="0" Canvas.Top="0"  Height="300" Width="400" Stretch="Fill"  Name="image" />
   7:         <Canvas Canvas.Left="0" x:Name="CanWrap" Canvas.Top="0" Background="White" Margin="0,0" Height="50" Width="400"  >
   8:             <Canvas x:Name="CanAni"   Height="50" Width="400"  >
   9:                 <Line  Visibility="Collapsed"  X1="01" Y1="00" Name="Lineone" X2="400" Y2="0" Stroke="Black"    StrokeThickness="1">
  10:                     <Line.BitmapEffect>
  11:                         <BlurBitmapEffect Radius="1" KernelType="Box" />
  12:                     </Line.BitmapEffect>
  13:                 </Line>
  14:                 <Line Visibility="Collapsed" X1="00" Y1="50" X2="400" Y2="50" Name="Linetwo" Stroke="Black" StrokeThickness="1">
  15:                     <Line.BitmapEffect>
  16:                         <BlurBitmapEffect Radius="1" KernelType="Box" />
  17:                     </Line.BitmapEffect>
  18:                 </Line>
  19:             </Canvas>
  20:         </Canvas>
  21:     </Canvas>
  22: </Window>

You can download the sample code from here. Hope this will save some of your time.

Wheel Clockwise animation in WPF

This animation is like the Wheel Clockwise, 1 spoke, animation of MS power point. Some people also call this animation as Radial animation. This animation starts from a line, which points from the centre to top middle, and then it rotates 360 degrees in clockwise direction and makes the underlying object visible. I know one picture can tell what is the animation looks like instead of writing many sentences. The animation looks like the following:

Wheel

How this animation effect is achieved?

As we know, every WPF UIelement type has a clip property and you can set any geometry object to clip. I have used this clip property to make this animation. I have changed the geometry object with time so that it looks like a wheel animation. All the challenges to make this animation in this way is making the exact geometry object with time.

I am showing this animation for Image type, which is a Uielement type. However, this trick is applicable to any UIelement type. PathGeometry is used here as the geometry to clip the image. Line segments are added to the path geometry dynamically to make the visible region bigger with time. I have calculated the height and width of the image. Then set the first line segment from (width/2, height/2) to (Width/2, 0). Then added the other line segments when they are needed and also change their points. For this animation, i have used DispatcherTimer, which runs in UI thread instead of worker thread. The code for this is in the following:

   1: public partial class Window1 : Window
   2:     {
   3:         DispatcherTimer _timer = null;
   4:         Ellipse _grdMain = null;
   5:         ContentPresenter _circleContentPresenter = null;
   6:         LineSegment LineSegment2 = null;
   7:         PathFigure PathFigure1 = null;
   8:         bool ISIncrementdirectionX = true;
   9:         bool IsIncrementX = true;
  10:         bool IsIncrementY = true;
  11:         LineSegment LineSegmentFirstcorner = null;
  12:         LineSegment LineSegmentseconcorner = null;
  13:         LineSegment LineSegmentThirdcorner = null;
  14:         LineSegment LineSegmentFourthcorner = null;
  15:         double _ofsetOfAnimation = 2;
  16:  
  17:         double _height = 0;
  18:         double _width = 0;
  19:  
  20:         public Window1()
  21:         {
  22:             InitializeComponent();
  23:             this.Loaded += new RoutedEventHandler(Window1_Loaded);
  24:         }
  25:  
  26:         void Window1_Loaded(object sender, RoutedEventArgs e)
  27:         {
  28:  
  29:             image.Source = loadBitmap(WheelClockwise.Properties.Resources.images1);
  30:             _height = image.Height;
  31:             _width = image.Width;
  32:             string topCentre = Convert.ToString(_width / 2) + ",0";
  33:             string centre = Convert.ToString(_width / 2) + "," + Convert.ToString(_height / 2);        
  34:  
  35:             PathGeometry PathGeometry1 = new PathGeometry();      
  36:             PathFigure1 = new PathFigure();
  37:             PathFigure1.StartPoint = ((Point)new PointConverter().ConvertFromString(centre));
  38:             PathGeometry1.Figures.Add(PathFigure1);
  39:             LineSegment LineSegmentdummy = new LineSegment();
  40:             LineSegmentdummy.Point = ((Point)new PointConverter().ConvertFromString(topCentre));
  41:             PathFigure1.Segments.Add(LineSegmentdummy);
  42:             LineSegmentseconcorner = new LineSegment();
  43:             LineSegmentseconcorner.Point = ((Point)new PointConverter().ConvertFromString(topCentre));
  44:             PathFigure1.Segments.Add(LineSegmentseconcorner);
  45:             LineSegmentThirdcorner = new LineSegment();
  46:             LineSegmentThirdcorner.Point = ((Point)new PointConverter().ConvertFromString(topCentre));
  47:             PathFigure1.Segments.Add(LineSegmentThirdcorner);
  48:             LineSegmentFourthcorner = new LineSegment();
  49:             LineSegmentFourthcorner.Point = ((Point)new PointConverter().ConvertFromString(topCentre));
  50:             PathFigure1.Segments.Add(LineSegmentFourthcorner);
  51:             LineSegmentFirstcorner = new LineSegment();
  52:             LineSegmentFirstcorner.Point = ((Point)new PointConverter().ConvertFromString(topCentre));
  53:             PathFigure1.Segments.Add(LineSegmentFirstcorner);
  54:             LineSegment2 = new LineSegment();
  55:             LineSegment2.Point = ((Point)new PointConverter().ConvertFromString(topCentre));
  56:             PathFigure1.Segments.Add(LineSegment2);
  57:             image.Clip = PathGeometry1;
  58:             _timer = new DispatcherTimer();
  59:             _timer.Interval = TimeSpan.FromSeconds(0.01);
  60:             _timer.Tick += new EventHandler(_timer_Tick);
  61:             _timer.IsEnabled = true;
  62:  
  63:         }
  64:         public static BitmapSource loadBitmap(System.Drawing.Bitmap source)
  65:         {
  66:             return System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(source.GetHbitmap(), IntPtr.Zero, Int32Rect.Empty,
  67:                 System.Windows.Media.Imaging.BitmapSizeOptions.FromEmptyOptions());
  68:         }
  69:  
  70:         void _timer_Tick(object sender, EventArgs e)
  71:         {
  72:             if ((LineSegment2.Point.X <= 0) && (LineSegment2.Point.Y <= 0))
  73:             {
  74:  
  75:                 LineSegmentFirstcorner.Point = new Point(LineSegment2.Point.X, LineSegment2.Point.Y);
  76:                 ISIncrementdirectionX = true;
  77:                 IsIncrementX = true;
  78:             }
  79:             else if (((LineSegment2.Point.X >= _width) && (LineSegment2.Point.Y <= 0)))
  80:             {
  81:                 LineSegmentseconcorner.Point = new Point(LineSegment2.Point.X, LineSegment2.Point.Y);
  82:                 LineSegmentThirdcorner.Point = new Point(LineSegment2.Point.X, LineSegment2.Point.Y);
  83:                 LineSegmentFourthcorner.Point = new Point(LineSegment2.Point.X, LineSegment2.Point.Y);
  84:                 LineSegmentFirstcorner.Point = new Point(LineSegment2.Point.X, LineSegment2.Point.Y);
  85:                 ISIncrementdirectionX = false;
  86:                 IsIncrementY = true;
  87:             }
  88:  
  89:             else if ((LineSegment2.Point.X >= _width) && (LineSegment2.Point.Y >= _height))
  90:             {
  91:                 LineSegmentThirdcorner.Point = new Point(LineSegment2.Point.X, LineSegment2.Point.Y);
  92:                 LineSegmentFourthcorner.Point = new Point(LineSegment2.Point.X, LineSegment2.Point.Y);
  93:                 LineSegmentFirstcorner.Point = new Point(LineSegment2.Point.X, LineSegment2.Point.Y);
  94:                 ISIncrementdirectionX = true;
  95:                 IsIncrementX = false;
  96:             }
  97:  
  98:             else if ((LineSegment2.Point.X <= 0) && (LineSegment2.Point.Y >= _height))
  99:             {
 100:                 LineSegmentFourthcorner.Point = new Point(LineSegment2.Point.X, LineSegment2.Point.Y);
 101:                 LineSegmentFirstcorner.Point = new Point(LineSegment2.Point.X, LineSegment2.Point.Y);
 102:                 ISIncrementdirectionX = false;
 103:                 IsIncrementY = false;
 104:             }
 105:  
 106:             double x = 0, y = 0;
 107:  
 108:             if (ISIncrementdirectionX == true)
 109:             {
 110:                 if (IsIncrementX)
 111:                 {
 112:                     x = LineSegment2.Point.X + _ofsetOfAnimation;
 113:                     y = LineSegment2.Point.Y;
 114:                 }
 115:                 else
 116:                 {
 117:                     x = LineSegment2.Point.X - _ofsetOfAnimation;
 118:                     y = LineSegment2.Point.Y;
 119:                 }
 120:             }
 121:             else
 122:             {
 123:                 if (IsIncrementY)
 124:                 {
 125:                     x = LineSegment2.Point.X;
 126:                     y = LineSegment2.Point.Y + _ofsetOfAnimation;
 127:                 }
 128:                 else
 129:                 {
 130:                     x = LineSegment2.Point.X;
 131:                     y = LineSegment2.Point.Y - _ofsetOfAnimation;
 132:                 }
 133:  
 134:             }
 135:  
 136:             LineSegment2.Point = new Point(x, y);
 137:             if ((LineSegment2.Point.X == _width / 2) && (LineSegment2.Point.Y == 0)) _timer.IsEnabled = false;
 138:  
 139:         }
 140:     }

The used XAML for this is in the following

   1: <Window x:Class="WheelClockwise.Window1"
   2:     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
   3:     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
   4:     Title="Window1" Height="400" Width="400">
   5:     <Canvas Name="canMain"  Background="White"    Height="300" Width="300"  >  
   6:         <Image Height="300" Width="300" Stretch="Fill"    Name="image" />
   7:     </Canvas>
   8: </Window>

You can download the sample code from here. Hope this will save some of your time.

How to pick numbers at random from a given set of numbers in c#

The Random class defined in the .NET Framework provides functionality to generate pseudo-random number. According to MSDN, the current implementation of the Random class is based on Donald E. Knuth's subtractive random number generator algorithm. The random number generation starts from a seed value. If the same seed is used repeatedly, the same series of numbers is generated. One way to produce different sequences is to make the seed value time-dependent, thereby producing a different series with each new instance of Random.

However, current implementation does not provide the following two functionalities.

  1. Picking random numbers from a given set of numbers: For example, you want random number from the given set of numbers. You have a set of numbers like (2, 4, 13, and 21).You would like to pick one number at a time at random from the list.
  2. Picking random numbers from a range of numbers with no repetition: Current implementation return random numbers within a range with some duplicate number. For example, you want random number from a range of numbers like (4 to 21). You would like to pick one number at a time at random from that range without any repetition or duplicate

However, these two requirements are easy to implement by using the Random class of the .NET Framework. I needed these two functionalities for one of my project, so I wrote a class to implement these two features. I think that this is a trivial work but I am posting it because it can save some of your time. To implement these two functionalities following class named RandomNumberFromAGivenSetOfNumbers is written.

   1: class RandomNumberFromAGivenSetOfNumbers
   2:    {
   3:        List<int> _setOfNumbers = new List<int>();
   4:  
   5:        public List<int> SetOfNumbers
   6:        {
   7:            get { return _setOfNumbers; }
   8:            set { _setOfNumbers = value; }
   9:        }
  10:        Random _random = new Random();
  11:  
  12:        public RandomNumberFromAGivenSetOfNumbers()
  13:        {
  14:  
  15:        }
  16:        public RandomNumberFromAGivenSetOfNumbers(int min, int max)
  17:        {
  18:            for (int i = min; i <= max; i++)
  19:            {
  20:                _setOfNumbers.Add(i);
  21:            }
  22:        }
  23:  
  24:        public int Next()
  25:        {
  26:            if (_setOfNumbers.Count > 0)
  27:            {
  28:                int nextNumberIndex = _random.Next(_setOfNumbers.Count);
  29:                int val = _setOfNumbers[nextNumberIndex];
  30:                _setOfNumbers.RemoveAt(nextNumberIndex);
  31:                return val;
  32:            }
  33:            return -1;
  34:        }
  35:    }

The used code for testing these two features is in the following

   1: static void Main(string[] args)
   2:        {
   3:            Console.WriteLine("Picking random numbers from a range of numbers with no repetition(Range is 0-24)");
   4:            Console.WriteLine();
   5:            RandomNumberFromAGivenSetOfNumbers rdm = new RandomNumberFromAGivenSetOfNumbers(0, 24);
   6:            string str = string.Empty;
   7:            for (int i = 0; i < 25; i++)
   8:            {
   9:                str += rdm.Next().ToString() + " ";
  10:            }
  11:            Console.WriteLine(str);
  12:            Console.WriteLine();
  13:            Console.WriteLine();
  14:  
  15:  
  16:            Console.WriteLine("Picking   random numbers from a given set of numbers( 2, 4, 13, and 21)");
  17:            Console.WriteLine();
  18:            RandomNumberFromAGivenSetOfNumbers rdm1 = new RandomNumberFromAGivenSetOfNumbers();
  19:            rdm1.SetOfNumbers.Add(2);
  20:            rdm1.SetOfNumbers.Add(4);
  21:            rdm1.SetOfNumbers.Add(13);
  22:            rdm1.SetOfNumbers.Add(21);
  23:            string str1 = string.Empty;
  24:            for (int i = 0; i < 4; i++)
  25:            {
  26:                str1 += rdm1.Next().ToString() + " ";
  27:            }
  28:            Console.WriteLine(str1);
  29:  
  30:            Console.ReadLine();
  31:        }

The output of the program is in the following:

random

You can download the sample code from here. This is a very trivial work, but I hope this will save some of your time.

Posted: 08-04-2009 8:40 PM by Razan | with no comments
Filed under: ,
Creating marquee/scrolling text in WPF

mar1

A WPF marquee is a scrolling piece of text displayed either horizontally across or vertically down your container. Here i show you how to make a scrolling marquee using Canvas and TextBlock. I will show only left to right in code. However, you can achieve right to left or vertical marquee text just by changing some portion of code using the same technique.

The following three techniques are used to achieve marquee animation:

  • Negative Positioning in canvas: If we set negative value to any of the positioning property of Canvas: Left, Right, Top and Bottom for an UIelement , Canvas draws that Uielement outside of Canvas area.
  • ClipToBounds property of canvas: if you set the value of the ClipToBounds property to true, Canvas will clip its children when they go outside of Canvas.
  • Changing Position of Uielement continuously: By changing continuously any of the canvas positioning property Left, right, Top, Bottom we can get moving text.

How is Left to right marquee text implemented in this sample?

Here a canvas is used as the container of marquee text. To move the text outside of canvas negative Left property of canvas is used. However, if someone uses negative left property of canvas, it will go outside of its parent container but will still remain visible outside of the parent container. To make marquee text invisible outside of canvas CliptoBound property is used. Then using double animation left property of canvas for that element is being changed continuously to get moving text. The whole thing is done using the following code.

   1: void Window1_Loaded(object sender, RoutedEventArgs e)
   2: {
   3:     DoubleAnimation doubleAnimation = new DoubleAnimation();
   4:     doubleAnimation.From = -tbmarquee.ActualWidth;
   5:     doubleAnimation.To = canMain.ActualWidth;
   6:     doubleAnimation.RepeatBehavior = RepeatBehavior.Forever;
   7:     doubleAnimation.Duration = new Duration(TimeSpan.Parse("0:0:10"));
   8:     tbmarquee.BeginAnimation(Canvas.LeftProperty, doubleAnimation);
   9: }

For Left to right marquee: use Left Property of Canvas

For right to left marquee: use Right Property of Canvas

For upward marquee: use Bottom Property of Canvas

For Downward marquee: use Top Property of Canvas

The used XAML for this is in the following

   1: <Window x:Class="MarqueText.Window1"
   2:     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
   3:     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
   4:     Title="Window1" Height="500" Width="700" >
   5:     <Canvas Background="White" >
   6:         <Canvas Margin="50" Canvas.Left="150" Canvas.Top="100" ClipToBounds="True" Name="canMain" Background="Red"   Height="100" Width="300"  >
   7:             <TextBlock Margin="0,40" FontSize="25" Name="tbmarquee">Bangladesh</TextBlock>
   8:         </Canvas>
   9:     </Canvas>
  10: </Window>

You can download the sample code from here. Hope this will save some of your time.

Making circle animation in WPF

circle2

This animation is like the circle animation of MS power point. You can set any geometry like ellipse geometry to define the visible region of a WPF UIelement type. To make it possible every WPF UIelement type has a clip property and you can set any geometry object to clip. However, for circle animation, we need circle geometry but WPF does not have built-in circle geometry.

How we can make circle geometry in WPF from ellipse Geometry?

An Ellipse Geometry is defined by a center point, an x-radius and a y-radius. As we know an ellipse geometry has two radius: radiousx and radiousy. If we keep the value of these two radiuses same, it will behave as circle. Just we will keep Radiousx = Radiousy all the time.

How this animation effect is achieved?

This trick is applicable to any UIelement type. Here I have taken image as the Uielement type to implement the circle animation. I have calculated the height and width of the image. Then set the centre of circle as (width/2, height/2) to start the animation from centre point. At first we keep the radius of the circle is 0. Then increment the radius proportion to time. For animation, we use double animation. Next thing is how much we will increase the radius. I have just compared the height and width of UIelement and set the radious equal to bigger one divided by two.

   1: EllipseGeometry ellipseGeometry = new EllipseGeometry();     
   2: ellipseGeometry.RadiusX = 0;
   3: ellipseGeometry.RadiusY = 0;
   4: double centrex = image.Source.Width / 2;
   5: double centrey = image.Source.Height / 2;
   6: ellipseGeometry.Center = new Point(centrex, centrey);
   7:  
   8: image.Clip = ellipseGeometry; //The most important line
   9:  
  10: if (image.Source.Width > image.Source.Height)
  11:    animationLength = image.Source.Width / 2;
  12: else
  13:    animationLength = image.Source.Height / 2;
  14: DoubleAnimation a = new DoubleAnimation();
  15: a.From = 0;
  16: a.To = animationLength+50;
  17: a.Duration = new Duration(TimeSpan.Parse("0:0:10"));
  18: ellipseGeometry.BeginAnimation(EllipseGeometry.RadiusXProperty, a);
  19: ellipseGeometry.BeginAnimation(EllipseGeometry.RadiusYProperty, a);

The used XAML for this is in the following

   1: <Window x:Class="circle.Window1"
   2:     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
   3:     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
   4:     Title="Window1" Height="300" Width="300">
   5:     <Canvas Name="canMain"    Height="300" Width="300"  >            
   6:         <Image   Canvas.Left="100" Canvas.Top="60"  Name="image"/>   
   7:     </Canvas>
   8: </Window>

You can download the sample code from here. Hope this will save some of your time.

Posted: 08-01-2009 5:29 PM by Razan | with no comments
Filed under: , ,
How can we convert a local path to a UNC path in c#?

Uniform Naming Convention (UNC): According to wiki, UNC specifies a common syntax to describe the location of a network resource, such as a shared file, directory, or printer in Windows OS.

In client-server development, we  can send a server path to its clients as UNC path. Therefore, those clients can access resources from the server. The UNC syntax for Windows systems has the generic form: \\ComputerName\SharedFolder\Resource. However, the safe side is using IP instead of computer name like \\IP\SharedFolder\Resource. Here we are going to see how we can convert a local path (say d:\razan\\x.zip') to its UNC-name ( say '\\192.168.1.56 \razan\x.zip').

Why cannot we use string concatenation to do so?

The shared folder or drive can be shared as something other than the folder name/drive letter. Moreover, it is possible to have one-to-many mapping between local paths and UNC paths.

To implement this functionality, I have written the following class named UNCHelper.

   1: class UNCHelper
   2: {
   3:     public static string ConvertLocalFilePathsToUNCPath(string fileName, string sharedFolderpath)
   4:     {
   5:         string strPath = fileName.Substring(sharedFolderpath.Length);
   6:         string sharedFolderPathInUNC = ConvertLocalFolderPathToIPBasedUNCPath(sharedFolderpath);
   7:         string networkPath = sharedFolderPathInUNC + strPath;
   8:         return networkPath;
   9:     }
  10:  
  11:     public static string ConvertLocalFolderPathToIPBasedUNCPath(string localFolderName)
  12:     {
  13:         string ipBasedUNCPath = string.Empty;
  14:  
  15:         ManagementObjectSearcher managementObjectSearcher = new ManagementObjectSearcher("SELECT Name FROM Win32_share WHERE path ='" + localFolderName.Replace("\\", "\\\\") + "'");
  16:         ManagementObjectCollection managementObjectCollection = managementObjectSearcher.Get();
  17:         if (managementObjectCollection.Count != 0)
  18:         {
  19:             foreach (ManagementObject item in managementObjectCollection)
  20:             {
  21:                 String ComputerName = ReturnMachineIP().ToString();// use  Dns.GetHostName(); for computername instead of IP
  22:                 ipBasedUNCPath = item["Name"] as String;
  23:                 ipBasedUNCPath = "\\\\" + ComputerName + "\\" + ipBasedUNCPath;
  24:                 return ipBasedUNCPath;
  25:             }
  26:         }
  27:         return ipBasedUNCPath;
  28:     }
  29:  
  30:     private static IPAddress ReturnMachineIP()
  31:     {
  32:         String hostName = Dns.GetHostName();
  33:         IPHostEntry ipEntry = Dns.GetHostEntry(hostName);
  34:         IPAddress[] addr = ipEntry.AddressList;
  35:         IPAddress ipV4 = null;
  36:         foreach (IPAddress item in addr)
  37:         {
  38:             if (item.AddressFamily == AddressFamily.InterNetwork)
  39:             {
  40:                 ipV4 = item;
  41:                 break;
  42:             }
  43:  
  44:         }
  45:         if (ipV4 == null)
  46:         {
  47:             throw new ApplicationException("You have no IP of Version 4.Server can not run witout it");
  48:         }
  49:         return ipV4;
  50:     }     
  51: }

ManagementObjectSearcher is the class that is commonly used to query disk drives, network adapters, processes, shared folder and many more management objects on a system. To test the code you can use the following line:

   1: Console.WriteLine( UNCHelper.ConvertLocalFilePathsToUNCPath("F:\\clustershare\\ razan_3.evp","F:\\clustershare"));

Here clustershare is the shared folder name. It has been tested in Windows XP and Windows Vista.

Hope this will save some of your time.

Posted: 07-24-2009 9:27 PM by Razan | with no comments
Filed under: , ,
Testing server whether it is reachable or not in c#

In client server development, we need this feature in many situations including:

  • When client starts before server, it should periodically check whether server is UP or not. As soon as it gets server is up, it will connect with it to do its own business.
  • Sometimes network between server and client can be broken and to reestablish this you can use reachability testing.

This technique can be used in WCF, .net remoting and socket programming. I have used this technique in several applications. Here testing reach ability is done by asynchronous socket programming with timeout for better performance. You can call isServerUp method at certain inteval according to your requirement. The following method checks whether server is reachable or not. If the server is reachable, It indicates that the network and server is ok and we can start doing business with server  

   1: public static bool isServerUp(string ip, int port, int timout)
   2:        {
   3:            IPAddress validIP;
   4:            if (IPAddress.TryParse(ip, out validIP))
   5:            {
   6:                IPEndPoint remoteEndPoint = new IPEndPoint(validIP, port);
   7:                bool fg = TimeOutSocket.Connect(remoteEndPoint, timout);
   8:                return fg;
   9:            }
  10:            else
  11:            {
  12:                return false;
  13:            }
  14:  
  15:        }

 You will notice that neither of the two classes, System.Net.Sockets.TcpClient nor System.Net.Sockets.Socket has a timeout to connect a socket. I mean a timeout you can set. .NET Sockets do not provide a Connect Timeout when calling the Connect or BeginConnectmethod while establishing a Synchronous or Asynchronous socket connection. Instead, connect is forced to wait a very long time before an Exception is thrown if the server it tried to connect to is not listening or if there is any network error. The default timeout is 20 - 30 seconds. There is an option in socket library named SocketOptionName.SendTimeout, which is used for timeouts on Send data not initial connects. To get this functionality, I have implemented the following class named TimeOutSocket.

   1: class TimeOutSocket
   2:    {
   3:        private static bool IsConnectionSuccessful = false;
   4:        private static Exception socketexception;
   5:        private static ManualResetEvent TimeoutObject = new ManualResetEvent(false);
   6:  
   7:  
   8:        public static  bool  Connect(IPEndPoint remoteEndPoint, int timeoutMSec)
   9:        {
  10:            TimeoutObject.Reset();
  11:            socketexception = null;  
  12:  
  13:            string serverip = Convert.ToString(remoteEndPoint.Address);
  14:            int serverport = remoteEndPoint.Port;           
  15:            TcpClient tcpclient = new TcpClient();
  16:        
  17:            tcpclient.BeginConnect(serverip, serverport, new AsyncCallback(CallBackMethod), tcpclient);
  18:  
  19:            if (TimeoutObject.WaitOne(timeoutMSec, false))
  20:            {
  21:                if (IsConnectionSuccessful)
  22:                {
  23:                    tcpclient.Close();
  24:                    return true;
  25:                }
  26:                else
  27:                {
  28:                    tcpclient.Close();
  29:                    return false;
  30:                }
  31:            }
  32:            else
  33:            {
  34:                tcpclient.Close();
  35:                return false;
  36:            }
  37:        }
  38:        private static void CallBackMethod(IAsyncResult asyncresult)
  39:        {
  40:            try
  41:            {
  42:                IsConnectionSuccessful = false;
  43:                TcpClient tcpclient = asyncresult.AsyncState as TcpClient;
  44:             
  45:                if (tcpclient.Client != null)
  46:                {
  47:                    tcpclient.EndConnect(asyncresult);
  48:                    IsConnectionSuccessful = true;
  49:                }
  50:            }
  51:            catch (Exception ex)
  52:            {
  53:                IsConnectionSuccessful = false;
  54:                socketexception = ex;
  55:            }
  56:            finally
  57:            {
  58:                TimeoutObject.Set();
  59:            }
  60:        }
  61:    }

Here ManualResetEvent plays the main role to implement this. It has a method WaitOne which has an overload WaitOne(TimeSpan,Boolean). According to MSDN, aitOne(TimeSpan, Boolean) blocks the current thread until the current instance receives a signal, using a TimeSpan to measure the time interval  and specifying whether to exit the synchronization domain before the wait.

So in the main thread, we call TimeoutObject.WaitOne(timeoutMSec, false) to block the main thread until timeout or till the signal has been  got using TimeoutObject.Set(). When waitone faces timeout, then it returns timeout exception. Otherwise socket is successfully connected or it faced any network error.

Here BeginConnect of tcpclient is used because this method does not block. After calling BeginConnect, we wait using waitone. If BeginConnect does not complete operation within timeout, then waitone will signal and TimeoutException is returned. IfBeginConnect does complete operation within timeout, then it will signal ManualResetEvent using TimeoutObject.Set() from theCallBackMethod which we passed as delegate in BeginInvoke that references the CallBackMethod to invoke when the operation is complete.

Thanks for reading this write up. I hope that this write up will be helpful for some people. If you guys have any questions, I would love to answer.

Posted: 07-18-2009 1:46 PM by Razan | with no comments
Filed under: , ,
JavaScript VS C# threading model

We were developing an application, which emulates the functionality of a real time device. In this application, we need real time event; we pool the service by a certain time interval and need to send some key presses. Moreover, we have a large number of timers to show real time effects of device by manipulating DOM elements.

Our assumption was that each timer of JavaScript runs in separate thread and asynchronously as c# and any windows programming language do. However, we were wrong and all the timers run in the same thread in serialize manner.

We put a callback in asynchronous service call to retrieve the result when service call back. In c# and any windows programming language, each callback runs in a separate thread instead of main (UI) thread. In JavaScript, all callbacks run in the main (only) thread.

What problems have we faced? As JavaScript is a single threaded model and we have a large number of JavaScript timer to retrieve real time status and to manipulate UI, UI becomes very slow. It is because some of the timer function has loops and bad code that stop the main thread to proceed.

The following are the main points to remember:

  • JavaScript is a single threaded model where as C# is a multi-threaded model.
  • In JavaScript, all the timers run in the same thread but in C# each timer run in the different thread.
  • In JavaScript, all callbacks run in the main (only) thread but in c#, each callback runs in a separate thread instead of main (UI) thread. 

If you does not keep this in mind, there is a possibility that you will end up with UI, which is not refreshing fast enough.

A scheduler to process a list of requests by a specific number of threads in c#.

This scheduler is not a time-based scheduler. It schedules the user tasks according to scheduling policy; scheduling policy is First Come First Serve. It performs the following tasks:

  •       It decides which request to execute next.
  •       Execute the request by one of the threads of  manual thread pool  if there is an idle thread in manual thread pool.

Here a specific number of threads is used to process the clients request. When Scheduler starts, A pool of threads is created to process pending requests of client, which may be created by software to meet certain requirements , sent by some  network client , polled from database . In thread pooling, after a thread is created, it is placed in the pool and it is used over again so that a new thread does not have to be created. If all the threads are being used, the requests remain in pending. As soon as one of the threads becomes free, it handles the next client request in FIFO manner.

   1: class Scheduler
   2:    {
   3:  
   4:        private ManualResetEvent manualResetEvent = new ManualResetEvent(false);
   5:  
   6:        private Queue _ClientRequests;
   7:        public Queue ClientRequests
   8:        {
   9:            get { return _ClientRequests; }
  10:            set { _ClientRequests = value; }
  11:        }
  12:  
  13:        private int _NumberofThreads = 3;
  14:        public int NumberofThreads
  15:        {
  16:            get { return _NumberofThreads; }
  17:            set { _NumberofThreads = value; }
  18:        }
  19:  
  20:        private bool IsSchedulerStarted = false;
  21:        private Thread[] StaticThreadPool = null;
  22:  
  23:        public Scheduler()
  24:        {
  25:            _ClientRequests = Queue.Synchronized(new Queue());
  26:            StaticThreadPool = new Thread[_NumberofThreads];
  27:  
  28:            for (int i = 0; i < StaticThreadPool.Length; i++)
  29:            {
  30:                StaticThreadPool[i] = new Thread(new ThreadStart(this.Work));
  31:                StaticThreadPool[i].IsBackground = true;
  32:            }
  33:        }
  34:  
  35:        private void Work()
  36:        {
  37:            while (true)
  38:            {
  39:                ICommand request = null;
  40:                lock (_ClientRequests.SyncRoot)
  41:                {
  42:                    if (_ClientRequests.Count > 0)
  43:                    {
  44:                        request = (ICommand)_ClientRequests.Dequeue();
  45:                    }
  46:                }
  47:                if (request != null)
  48:                    request.Execute();
  49:                else
  50:                    manualResetEvent.WaitOne();
  51:                if (!IsSchedulerStarted) break;
  52:            }
  53:        }
  54:  
  55:        public void Enqueue(ICommand request)
  56:        {
  57:            lock (_ClientRequests.SyncRoot)
  58:            {
  59:                _ClientRequests.Enqueue(request);
  60:            }
  61:            manualResetEvent.Set();
  62:        }
  63:  
  64:        public void StartScheduler()
  65:        {
  66:            foreach (Thread item in StaticThreadPool)
  67:            {
  68:                item.Start();
  69:            }
  70:            IsSchedulerStarted = true;
  71:        }
  72:  
  73:        public void StopScheduler()
  74:        {
  75:            IsSchedulerStarted = false;
  76:            foreach (Thread item in StaticThreadPool)
  77:            {
  78:                if (item != null)
  79:                {
  80:                    if (item.IsAlive)
  81:                    {
  82:                        item.Join();
  83:                    }
  84:                }
  85:            }
  86:        }
  87:    }

According to MSDN, Enumerating through a collection is intrinsically not a thread-safe procedure. Even when a collection is synchronized, other threads can still modify the collection, which causes the enumerator to throw an exception. To guarantee thread safety during enumeration, you can either lock the collection during the entire enumeration or catch the exceptions resulting from changes made by other threads. To guarantee the thread safety of the queue, all operations  is done through the synchronized (thread safe) wrapper of queue.

To  improve performance, when we do not have any messages to process in the queue, we simply block the thread until a new message appears.  According to MSDN, WaitOne( )  method  of  ManualResetEvent blocks the current thread until the current instance receives a signal. So in  each working  thread, we call manualResetEvent.WaitOne  to block each working  thread  when there is no request to process.

   1: interface ICommand
   2:   {
   3:       void Execute();
   4:   }
   5:  
   6:   class ClientRequestType1 : ICommand
   7:   {
   8:       // data structure for requst type 1    
   9:  
  10:       #region ICommand Members
  11:  
  12:       public void Execute()
  13:       {
  14:           //write code to process a requet type 1
  15:       }
  16:  
  17:       #endregion
  18:   }
  19:  
  20:  
  21:  
  22:   class ClientRequestType2 : ICommand
  23:   {
  24:       // data structure for requst type 1  
  25:  
  26:       #region ICommand Members
  27:  
  28:       public void Execute()
  29:       {
  30:           //write code to process a requet type 1
  31:       }
  32:  
  33:       #endregion
  34:   }

To process each type of user request, there  is a  method with some  parameters. Here we represent these methods using ICommand type to encapsulate each method with its parameters into an object. To process each type of user  request, we ask the corresponding  Icommand object to execute and it knows what to do.

IP address spoofing in c# using P/Invoke

According to Wiki, the term IP (Internet Protocol) address spoofing refers to the creation of IP packets with a forged (spoofed) source IP address with the purpose of concealing the identity of the sender or impersonating another computing system. For one of my project, I needed IP spoofing. According to a requirement, I need to commutate with a device over crossover cable for configuring it. But the problem is , when device boots  up , it gets an arbitrary IP when it is operating  over crossover connection as it cannot contract with DHCP Server. My PC is in a different network from the device. So i cannot communicate with that device thru socket programming. But one thing I can do, i can search the device using some proprietary protocol and find its information like its IP.

As I can get the IP of device, if I change the pc IP according to Device IP so that they are in the same network then I will be able to communicate with the device and configure it.  AddIPAddress Function of iphlpapi.dll can be used to add a specified IPv4 address to the specified adapter and    DeleteIPAddress function can be used to delete an IP address previously added using AddIPAddress. So using these two functions you can do IP spoofing .Your real IP4 address will be changed for a very short time when you are sending the packet. Another thing to note, a network interface can hold multiple IIP address and holds it in a IP table.

The code that is used is in the following:

   1: [DllImport("iphlpapi.dll", SetLastError = true)]
   2:  static extern UInt32 AddIPAddress(UInt32 Address, UInt32 IpMask, int IfIndex, out IntPtr NTEContext, out IntPtr NTEInstance);
   3:  
   4: [DllImport("iphlpapi.dll", SetLastError = true)]
   5: static extern UInt32 DeleteIPAddress(IntPtr NTEContext);
   6:  
   7:  static IntPtr ptrNteContext = new IntPtr(0);
   8:  
   9: public static UInt32 AddIPAddressToInterface(string ipAddress, string subnetMask, int ifIndex)
  10: {
  11:   System.Net.IPAddress ipAdd = System.Net.IPAddress.Parse(ipAddress);
  12:   System.Net.IPAddress subNet = System.Net.IPAddress.Parse(subnetMask);
  13:   unsafe
  14:   {
  15:       int nteContext = 0;
  16:       int nteInstance = 0;
  17:       ptrNteContext = new IntPtr(nteContext);
  18:       IntPtr ptrNteInstance = new IntPtr(nteInstance);
  19:       return AddIPAddress(IpAddressToUInt32(ipAdd), IpAddressToUInt32(subNet), ifIndex, out ptrNteContext, out ptrNteInstance);
  20:   }
  21: }
  22:  
  23: public static void  DeletePreviouslyAddedIP()
  24: {
  25:   DeleteIPAddress(ptrNteContext);
  26: }
Posted: 04-24-2009 1:19 PM by Razan | with no comments
Filed under: , ,
Testing whether two IP addresses are in the same network using c#.

IPv4 address has two basic parts:  the network part and the host part. As we know, if network potions of two IPs are same, they are in the same network. By performing and operation between subnet mask and IP address, we can get the network portion of an IP. By this way, we have found the network portions of two IPs. Then just check whether the network portions are equal or not. For this the following code is written:

   1: private static bool CheckWhetherInSameNetwork(string firstIP, string subNet, string secondIP )
   2:    {
   3:        uint subnetmaskInInt = ConvertIPToUint(subNet);
   4:        uint firstIPInInt = ConvertIPToUint(firstIP);
   5:        uint secondIPInInt = ConvertIPToUint(secondIP);
   6:        uint networkPortionofFirstIP = firstIPInInt & subnetmaskInInt;
   7:        uint networkPortionofSecondIP = secondIPInInt & subnetmaskInInt;
   8:        if (networkPortionofFirstIP == networkPortionofSecondIP)
   9:            return true;
  10:        else
  11:            return false;
  12:    }
  13:  
  14:    static public uint ConvertIPToUint(string ipAddress)
  15:    {
  16:        System.Net.IPAddress iPAddress = System.Net.IPAddress.Parse(ipAddress);
  17:        byte[] byteIP = iPAddress.GetAddressBytes();
  18:        uint ipInUint = (uint)byteIP[3] << 24;
  19:        ipInUint += (uint)byteIP[2] << 16;
  20:        ipInUint += (uint)byteIP[1] << 8;
  21:        ipInUint += (uint)byteIP[0];
  22:        return ipInUint;
  23:    }

Hope this will save some of your time.

Posted: 04-22-2009 2:14 PM by Razan | with no comments
Filed under: ,
More Posts Next page »