Showing posts with label c#. Show all posts
Showing posts with label c#. Show all posts

Thursday, November 13, 2008

Tutor.com Classroom How-To #9: creating a Path object from a Stroke

These How-To tips are taken from The Tutor.com Classroom: Architecture and techniques using Silverlight, WPF, and the Microsoft .NET Framework.

You can check out the Silverlight Tutor.com Classroom in "practice" mode, although the real experience is with a live tutor on the other side!

Simply transfer Stroke stylus points to a PolyLineSegment on a Path:


static Path getPathFromStroke(Stroke str)
{
//make a path from this stroke
Path path = new Path();
PathGeometry pg = new PathGeometry();

//start our figure from the first stylus point in the stroke
PathFigure fg = new PathFigure();
fg.Segments = new PathSegmentCollection();
fg.StartPoint = new Point(str.StylusPoints[0].X, str.StylusPoints[0].Y);

PolyLineSegment seg = new PolyLineSegment();

//add each additional stylus point to the line segment
for (int x = 1; x < str.StylusPoints.Count; x++)
StylusPoint sp = str.StylusPoints[x];

seg.Points.Add(new Point(sp.X, sp.Y));

fg.Segments.Add(seg);

pg.Figures = new PathFigureCollection();
pg.Figures.Add(fg);

path.Data = pg;

return path;
}

Wednesday, November 12, 2008

Tutor.com Classroom How-To #8: trapping and processing mouse movement in an InkPresenter

These How-To tips are taken from The Tutor.com Classroom: Architecture and techniques using Silverlight, WPF, and the Microsoft .NET Framework.

You can check out the Silverlight Tutor.com Classroom in "practice" mode, although the real experience is with a live tutor on the other side!

In the MouseDown event, instantiate a module-level Stroke object (e.g. m_DrawingStroke) to collect points traversed by the mouse. Fire the StrokeAdded event so that listeners can prepare for the operation as necessary. Most importantly, call CaptureMouse() to notify the mouse input engine to give you high frequency mouse event notifications.


void Whiteboard_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
//get our current position
Point p = e.GetPosition(this);

//create a new styluspoint collection for our new stroke
StylusPointCollection coll = new StylusPointCollection();
coll.Add(new StylusPoint() { X = p.X, Y = p.Y });

m_DrawingStroke = new Stroke(coll);

//fire notification event
if (this.StrokeAdded != null)
this.StrokeAdded(m_DrawingStroke);

//begin capturing mouse input
this.CaptureMouse();
}

In MouseMove, add the traversed point to the Stroke’s StylusPoints collection, and fire the StrokeChanging event to alert interested listeners.

void Whiteboard_MouseMove(object sender, MouseEventArgs e)
{
//get our current position
Point p = e.GetPosition(this);

//add the traversed point to our collection
StylusPoint sp = new StylusPoint() { X = p.X, Y = p.Y };
m_DrawingStroke.StylusPoints.Add(sp);

//fire notification event
if (this.StrokeChanging != null)
this.StrokeChanging(m_DrawingStroke);
}

In MouseUp, release mouse capture and fire the StrokeComplete event.

void Whiteboard_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
//release mouse capture
this.ReleaseMouseCapture();

//fire notification event
if (this.StrokeComplete != null)
this.StrokeComplete(m_DrawingStroke);
}

Tuesday, November 11, 2008

Tutor.com Classroom How-To #7: screen-scraping an application via Win32 PrintWindow() API

These How-To tips are taken from The Tutor.com Classroom: Architecture and techniques using Silverlight, WPF, and the Microsoft .NET Framework.

You can check out the Silverlight Tutor.com Classroom in "practice" mode, although the real experience is with a live tutor on the other side!

In the WPF application, we make calls to the PrintWindow() Win32 API to gather screen contents. We then splice the return bitmap into a 4x4 grid and compare hashes of each of the slices with the previous slices’ hashes. If a slice has changed, we package up its bytes and ship it across the wire.

There are two key components to making this process of screen scrape, comparison, and messaging fast enough to run each second without overburdening the CPU. The first is that the entire process runs on a thread pool thread via a timer, which frees up the GUI. The second is that our Bitmap uses the Format32bppArgb pixel format, which uses more memory but optimizes performance of PrintWindow() calls.


[DllImport("user32.dll", SetLastError = true)]
static extern bool PrintWindow(IntPtr hwnd, IntPtr hDC, uint nFlags);

void processCapture()
{
using (Graphics g = Graphics.FromImage(captureBitmap))
{
//get window content
IntPtr hdc = g.GetHdc();
try
{
result = PrintWindow(m_Win32HostHandle, hdc);
}
finally
{
g.ReleaseHdc(hdc);
}

//process captureBitmap
...
}
}

Monday, November 10, 2008

Tutor.com Classroom How-To #6: creating a horizontal WrapPanel that is transform-aware and exposes row and column counts

These How-To tips are taken from The Tutor.com Classroom: Architecture and techniques using Silverlight, WPF, and the Microsoft .NET Framework.

You can check out the Silverlight Tutor.com Classroom in "practice" mode, although the real experience is with a live tutor on the other side!

Begin by deriving from Panel, which is the base class for container controls, and override the MeasureOverride() and ArrangeOverride() functions. These functions are called iteratively as the layout engine determines how to distribute available visual space. Have them call a custom function that takes either the available size (from the measure pass) or the final size (from the arrange pass), and a ShouldArrange parameter to specify which pass is processing, and returns a Size.


private Size measureAndOptionallyArrangeItems(Size size, bool ShouldArrange)
{
Point point = new Point(0, 0);
Size s = new Size(size.Width, 0);

//consider scale transform that might be affecting us
double xfactor = 1;
double yfactor = 1;
if (this.RenderTransform != null)
{
if (this.RenderTransform is ScaleTransform)
{
ScaleTransform st = (ScaleTransform)this.RenderTransform;

xfactor = st.ScaleX;
yfactor = st.ScaleY;
}
}

double largestHeight = 0.0;

this.Rows = 0;
this.Cols = 0;

foreach (UIElement child in Children)
{
if (child.DesiredSize.Height > largestHeight)
largestHeight = child.DesiredSize.Height;

//first row?
if (this.Rows == 0)
this.Rows = 1;

double desiredWidth = child.DesiredSize.Width;

//does this child cause us to wrap?
if (point.X > 0 && point.X + desiredWidth > size.Width * (1 / xfactor))
{
this.Rows++;

s.Height += largestHeight * yfactor;

//goto the next line
point.X = 0;
point.Y += largestHeight;
largestHeight = child.DesiredSize.Height;

if (ShouldArrange)
child.Arrange(new Rect(point, new Point(point.X + desiredWidth, point.Y + child.DesiredSize.Height)));

//set our current location in this new line
point.X = desiredWidth;
}
else
{
if (ShouldArrange)
child.Arrange(new Rect(point, new Point(point.X + desiredWidth, point.Y + child.DesiredSize.Height)));

point.X = point.X + desiredWidth;

//if we're doing first row, set columns
if (this.Rows == 1)
this.Cols++;
}
}

s.Height += largestHeight * yfactor;

return s;
}

Friday, November 7, 2008

Tutor.com Classroom How-To #5: providing automatic reader-to-writer lock upgrade

These How-To tips are taken from The Tutor.com Classroom: Architecture and techniques using Silverlight, WPF, and the Microsoft .NET Framework.

You can check out the Silverlight Tutor.com Classroom in "practice" mode, although the real experience is with a live tutor on the other side!

Create a class that contains a module-level System.Threading.ReaderWriterLock (e.g. m_Lock) and wrap the AcquireReaderLock() function. Then create an AcquireWriterLock() function that returns a LockCookie wrapper (SafeLockCookie), checks to see if the read lock is held, and upgrades if necessary, and a ReleaseWriterLock()function that processes the SafeLockCookie and releases the lock or downgrades back to read:


public SafeLockCookie AcquireWriterLock()
{
//if we have a read lock, upgrade
if (m_Lock.IsReaderLockHeld)
{
return new SafeLockCookie(m_Lock.UpgradeToWriterLock(TIMEOUT_MS));
}
else
{
m_Lock.AcquireWriterLock(TIMEOUT_MS);
return null;
}
}

public void ReleaseWriterLock(SafeLockCookie SafeLockCookie)
{
//do we need to downgrade?
if (SafeLockCookie != null)
{
m_Lock.DowngradeFromWriterLock(ref SafeLockCookie.LockCookie);
}
else
{
m_Lock.ReleaseWriterLock();
}
}

Then have calling functions request write locks by storing a SafeLockCookie when requesting the lock and returning it when releasing:

SafeLockCookie lc = m_Lock.AcquireWriterLock();
try
{
...
}
finally
{
m_Lock.ReleaseWriterLock(lc);
}

Tuesday, November 4, 2008

Tutor.com Classroom How-To #2: connecting to a TCP/IP Listener

These How-To tips are taken from The Tutor.com Classroom: Architecture and techniques using Silverlight, WPF, and the Microsoft .NET Framework.

You can check out the Silverlight Tutor.com Classroom in "practice" mode, although the real experience is with a live tutor on the other side!

Using the Socket class, we just need to create a SocketAsyncEventArgs and call ConnectAsync(). Notice an example of the “#if WPF” directive for subtle Silverlight/WPF differences (as described in the "Code Sharing" post) when we set the SocketAsyncEventArgs RemoteEndPoint.


public void Connect(string host, int port)
{
//instantiate socket
m_Socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

//set up endpoint
#if WPF
m_SocketSendArgs.RemoteEndPoint = new IPEndPoint(Dns.GetHostAddresses(host)[0], port);
#else
m_SocketSendArgs.RemoteEndPoint = new DnsEndPoint(host, port);
#endif

//set up args
SocketAsyncEventArgs args = new SocketAsyncEventArgs();

args.UserToken = m_Socket;
args.RemoteEndPoint = m_SocketSendArgs.RemoteEndPoint;
args.Completed += new EventHandler(OnConnect);

m_Socket.ConnectAsync(args);
}

Thursday, August 7, 2008

Action<> and Func<> delegates

these new generic delegates were added in .NET 3.5 for LINQ, but they’re also very useful in your own classes. Action<> allows you to specify types for up to 4 parameters and returns void, and Func<> does the same except you can also specify a return type. if you look at the LINQ extension methods, you’ll see these delegates extensively.

so for example, if you needed a delegate that returned void and took no parameters, you’d have to write something like:

public delegate void VoidDelegate();

public event VoidDelegate MyEvent;

so what you end up with is repetitive declarations of such a VoidDelegate delegate in lots of classes. now, you can just use the Action<> delegate to do this (Action<> works in any case where you return void and take up to 4 parameters):

public event Action MyEvent;

same goes for Func<>. before, you’d have to create a delegate for each specific set of input variable and return types:

public delegate string TakeTwoStringsAndReturnStringDelegate(string String1, string String2);

and then call it like:


return (String)Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Normal,
(TakeTwoStringsAndReturnStringDelegate)delegate
{
return TakeTwoStringsAndReturnString("1", "2");
}
);

now you can use Func<> instead (Func<> also works for up to 4 parameters):

return (String)Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Normal,
(Func<String, String, String>)delegate
{
return TakeTwoStringsAndReturnString("1", "2");
}
);

there are probably still times when you’ll want to create your own delegate, but these two generics are very useful for filling in the gaps—

Monday, July 28, 2008

catching and ignoring an exception

if you want to catch an exception and ignore it, do this to avoid the compiler warning:

catch
{
//do nothing
}

instead of:

catch (Exception ex)
{
//do nothing
}

you can similarly catch exceptions of a certain type without assigning a variable to them, for example:

catch (ArgumentException)
{
//do nothing
}

instead of:

catch (ArgumentException ex)
{
//do nothing
}

Friday, July 18, 2008

when logging exceptions, use Exception.ToString()

this will get you error type, message, and stacktrace, not only for the Exception but also for its InnerException if there is one--

Thursday, May 22, 2008

code snippet for INotifyPropertyChanged

import this snippet and use “propnp” to implement a property in an object that implements INotifyPropertyChanged--

http://www.russellgreenspan.com/software/code/propnp.zip

Monday, February 4, 2008

chaining the C# ?? Operator

?? operator was news to me, Rick Stahl's blog is great: http://www.west-wind.com/weblog/posts/236298.aspx. snippet:

string value1 = null;
string value2 = "Test1";
string result = value1 != null ? value1 : value2;

which causes result containing Test1 or the second value.

In C# you can shortcut this special null comparison case with the new ??:

string result = value1 ?? value2;

Friday, June 22, 2007

avoid finalizers/use "using"

this is something we’ve gotten wrong a bit in places: in c#, only use a finalizer (i.e. a ~ClassName() method) if you need to clean-up unmanaged resources you’ve allocated. the reason for this is that if your class has a finalizer, the garbage collector will place it in the finalization queue and will not release it immediately. if you do have unmanaged resources and require a finalizer, implement IDisposable and do your cleanup in a shared Dispose(bool isDisposing) method. make sure to call GC.SuppressFinalize() in your Dispose() method so that if your client has already called Dispose(), your object is not placed in the finalization queue. for example:

public class ClassName : IDisposable
{

private bool m_IsDisposed;

~ClassName()
{

Dispose(false);

}

public void Dispose()
{

Dispose(true);

GC.SuppressFinalize(this);

}

public void Dispose(bool FromDisposeMethod)
{

if (!m_IsDisposed)
{

m_IsDisposed = true;

if (FromDisposeMethod)
{

//release managed resources; only do this if from Dispose method since they themselves might have been finalized

//...

}

//release unmanaged resources

//...

}

}

}

also, use "using" as much as possible. you can do this with any object that implements IDisposable:

using (MemoryStream ms = new MemoryStream())
{

//do whatever you want with ms

//...

}

using will automatically call Dispose() when the scope of this block ends, so you get very readable code and know that resources are properly released--

Wednesday, May 30, 2007

declaring variables inside a loop in c#

interesting thread here: http://www.thescripts.com/forum/thread505814.html

in the past (c++) it was best practice to avoid declaring variables inside a loop; in c#, both of these compile to the same IL:

for (int i = 0; i < 100; i++)
{
StringBuilder sb = new StringBuilder();
}

StringBuilder sb;

for (int i = 0; i < 100; i++)
{
sb = new StringBuilder();
}
and since the first example has the StringBuilder scoped to the for loop, you can’t accidentally use it after this code block executes. so: declare variables inside loops in c#.

Wednesday, May 16, 2007

devscovery 2007 5/9 - 5/11

this was a great conference run by Wintellect, a training/consulting company that works very closely with msft on product development. the speakers were Wintellect’s technical leads (jeff richter, john robbins, jeff prosise, etc.), who are the authors of some of the Microsoft Press books we read, and all were excellent. topics covered included some of what’s in store for us in the near future (wpf, wcf, silverlight) and some stuff we can start taking advantage of right now (asp.net ajax extensions, asynchronous programming, debugging). the c# 3.0 language enhancements are very interesting; lots of syntactic shortcuts to reduce what you have to type that end up making things look very javascript-looking.

wpf (part of .NET 3.0)

  • does not replace Winforms; for quick development of standard GUI, not-so-flashy desktop apps, Winforms will still have a place
  • page layout defined in XAML
    o easy to exploit graphics and animation compabilities
    o nearly every property of every object is animatable
    o binding allows the property of an object to change as the property of another object changes
  • similar structure to ASP.NET in that .xaml page containing markup has .xaml.cs code-behind page containing coding logic

BETA - silverlight (formerly WPF/E)

  • cross-platform browser plugin
  • "silverlight CLR" provides sandboxed capabilities (limited access to file system, networking, etc.)
  • allows you to write almost-identical xaml pages as wpf apps
  • v1.0 currently in beta
    o requires you to interact with xaml objects via javascript
    o v1.1 (currently in alpha) allows
    o allows you to interact with xaml object using C#
    o will likely displace Flash in Microsoft development shops

CTP - c# 3.0 (next version of the c# language)

  • in general, the language is becoming more functional looking (LISP-like), and most new constructs are easy-to-write shortcuts to the actual operations that are rewritten at compile-time
    § implicitly typed local variables - allow you to say:

    var x = new String("hi");

    instead of:

    string x = new string("hi");

    which is particularly useful when you are instantiating a complex type
  • extension methods - you can define a static method in a static class with new "this" keyword in parameters as follows:

    public static int StringToIntFunction(this string s) {...do something...}

    and then this function is available in instance-syntax to any String object, so you can say:

    string s = "hi";int i = s.StringToIntFunction();
  • anonymous types - compiler will generate a type name for you, with specified property accessors:

    var someEmployee = new { Name = "MyName", Title = "Developer" }

    and you can then call someEmployee.Name and someEmployee.Title as if you had created an Employee class and specified these properties
  • LINQ (Language INtegrated Queries) - new constructs allow for T-SQL-like syntax for IEnumerable interactions:int[] numbers = { 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 };var lowNums = from n in numbers where n < products =" GetProductList();var" productinfos =" from" price =" p.UnitPrice};" href="http://download.microsoft.com/download/5/8/6/5868081c-68aa-40de-9a45-a3803d8134b8/csharp_3.0_specification.doc">http://download.microsoft.com/download/5/8/6/5868081c-68aa-40de-9a45-a3803d8134b8/csharp_3.0_specification.doc

asp.net ajax extensions - http://ajax.asp.net/

  • we can and should start using this NOW! if you see something that will speed development time or provide richer user experience, use it!
  • the asp.net ajax control toolkit contains lots of widgets that use the ajax extensions and is open-sourced
  • tag allows you to specify path the your webservice; this generates a javascript-callable wrapper for your webservice methods, so you get real nice webservice.methodName() syntax on webservice calls
  • JSON (JavaScript Object Notation), which is a much less-verbose SOAP alternative we should also be using already

threading and asynchronous programming model

  • as much as possible, use beginread()/endread() instead of read(), etc.
  • can create UI issues and is a bit more difficult model to program using (since everything is done with callbacks), but keeps threadpool lean and mean
  • use Interlocked class for thread-safe variable increment/decrement

debugging, unit testing, and perf tuning

  • VSTS provides almost all the necessary tools
  • UI automation testing in .NET 3.0 provides APIs for driving Winform and wpf apps
  • developers average 1 bug for every 10 lines of code; with unit testing and code-coverage averaging 80-90% coverage, ratio moves toward 1/1000
  • beware of finalizers (cause objects to be moved to GC finalizer queue, which is not cleaned until next GC run)

tools

  • BETA - Blend (formerly Expressions)
    o Flash-like IDE for creating xaml for animations
    o release versions due later this year
  • CTP – “Orcas” (next version of Visual Studio)
    o project types for Silverlight apps
    o intellisense for xaml and javascript
    o release versions due later this year
    o reflector – FREE - see c# code for .NET library
    o http://www.aisto.com/roeder/dotnet/
  • web development helper – FREE - firebug-like plugin for IE
    o http://projects.nikhilk.net/Projects/WebDevHelper.aspx
  • .net memory profiler - awesome tool to analyze .net memory usage
    o http://www.memprofiler.com/

Tuesday, May 8, 2007

coding standards

having standards makes it much easier to read code you didn’t write, so i do as much as i can to encourage adherence to the list here.

Definitions:
  • “UpperCamelCased” = capitalize first letter of each keyword (.NET style); do not use underscores)
  • “lowerCamelCased” = captialize first letter of each keyword except the first (java-style); do not user underscores
  • “Hungarian Notated” = prefix variable name with indicator of its type (i.e. string sMyString or strMyString)

C#: (in general, follow Microsoft .NET standards)

Functions

  • Public functions “UpperCamelCased”
  • Private functions “lowerCamelCased”
  • Parameters “UpperCamelCased”

Variables

  • Module-level variables begin “m_”
  • Local function variables either:
    o “lowerCamelCased”
    o Keywords separated with “_”
    o Prefixed with “tmp_”
    o “Hungarian Notated”

Enums

  • “UpperCamelCased”
  • Type name pluralized (i.e. “MyItems”, not “MyItem”)

Constants

  • “UPPER_CASE” (all capitalized; keywords separated with “_”)

For example:

public class MyClass
{

public const THIS_IS_MY_CONSTANT = 0;

public enum MyItems
{

None = 0
,SomeItem = 1
,AnotherItem = 2

}

private string m_MyVariable;

public void TellMeEverything(string Input1)
{

bool localVar = false;
bool local_var = false;
bool tmp_LocalVar = false;
bool bLocalVar = false;

}

private void tellYouNothing(string Input1)
{

}

}


Database Tables

  • Table names “UpperCamelCased_WithAnyExtras” (capitalize first letter of each key word and use a single “_” character as desired)
  • Column names “UpperCamelCased”
  • T-SQL keywords “UPPERCASE” (all capitalized)
  • T-SQL Datatypes “alllowercase” (do not capitalize any character)

For example:

CREATE TABLE Groups
(
GroupId int
,GroupName varchar(50)
)

Database Sprocs

  • Sproc names “UpperCamelCased”
  • Separate input parameters or returned columns with comma on line of subsequent parameter or column name
  • Clearly separate SELECT/FROM/WHERE or UPDATE/SET/WHERE clauses using carriage returns or tabs

For example:

CREATE PROCEDURE UpdateUser

@UserId int
,@StatusId int
,@
UpdateByUserId int


AS

UPDATE Users

SET StatusId = @StatusId
,ChangedBy = @UpdateByUserId

WHERE UserId = @UserId

GO


Thursday, July 27, 2006

try/catch with open transaction

something i’m noticing we haven’t been so good about: when you write a try/catch block with an open transaction, make sure that the last line of code in the try block is the CommitTransaction(). if there is code after the Commit() that throws an error, the catch handler will try to rollback a transaction that has already been committed, and that will throw its own unhandled exception.

void dbcall()
{

try
{

ds.OpenConnection();

ds.BeginTransaction();

//db calls here

//make this the
last line of the try block:

ds.CommitTransaction();

}

catch (Exception x)
{

ds.RollbackTransaction();

handleError(x);

return;

}

finally

{

ds.CloseConnection();

}

//put any other code that
happens after you Commit here

}