Tuesday, June 10, 2008
Sunday, June 08, 2008
Photos from TechEd 2008 Devs: Party at Universal Studios Orlando
| This panorama comprises five horizontal photos. (Somewhere, Encarta's copy chief is smiling. Even after all these years, I remember the ESG's recipe: "pancake batter comprises butter, milk, eggs.") |
| This very weird panorama comprises six horizontal photos. It isn't totally successful but it's sure fun to look at. |
Labels: Microsoft, pictures, Tech Ed, TechEd2008
Photos from Tech Ed 2008 Devs: Carl Franklin plays the show floor
Sunday now and I'm finally finding time to catch up on all the pictures I shot during Tech Ed Developers last week. The co-host of .NET Rocks!, Carl Franklin has a fine voice and plays guitar with exceptional skill. Many of us milling the conference floor ceased our schwag-collecting and stopped by to hear Carl play.
Labels: Microsoft, pictures, Tech Ed, TechEd2008
Tuesday, June 03, 2008
Microsoft Tech Ed 2008 Developers | Panoramic images from Bill Gates' keynote
Programmatically stitched panoramic images. I shot these pictures during Bill Gates' keynote on Day 2 of Microsoft Tech Ed 2008 Developers.
Empty. Stitched from ten vertically-shot images.
Full! Stitched from six vertically-shot images.
billg takes the stage. Stitched from ten vertically-shot images.
Quizzing Mr. Gates.
This one's an uncropped mess but I sort of like it anyway. Next year maybe I'll bring a full-frame fisheye lens to shoot the keynote.
General call to conference organizers on technology topics: I am happy to exchange unrestricted rights to the thousands of photos I invariably shoot at these events for comps on conference registration fees.
Labels: billg, Microsoft, Tech Ed, TechEd2008
Tech Ed 2008 Photographs | Monday | Jeff Prosise and Panoramas
I returned to Tech Ed 2008 Developers determined to take a picture or two. I took the photographs below during Monday's pre-conference sessions. Many of the images below were programmatically stitched into panoramas from several pictures, a technique I've been playing with recently to communicate the scale of things and to combat the grain associated with shooting handheld in low light.
| Inside: Orange County Convention Center entrance. |
| Outside: Orange County Convention Center entrance. |
| Most denizens of the IT world will appreciate this bus-borne commentary on organizational teamwork. Nice to start Tech Ed with a smile. |
| Colors! |
Jeff Prosise hard at work during his Silverlight PreCon. | |
| Jeff Prosise |
| Jeff Prosise, looking contemplative as he confronts the existential crisis of Q&A. |
| Jeff Prosise with us Q&A groupies |
| Orange County Convention Center at dusk. This panorama comprises eight vertically-shot images. I'm not satisfied with this -- but I've got the rest of Tech Ed Devs and Tech Ed IT Pros to do better! |
Wednesday, October 17, 2007
Ken's Oct. 14 Long Beach Marathon: 3:30:19
Exactly one month after my first marathon in Maui (which I finished in a relaxing 3:48) I ran closer to home in the Oct. 14 Long Beach Marathon. Dr. Fine joined me on this adventure: me on foot, Essie snapping pictures and cracking encouraging jokes from her bicycle the whole way (example: "Don't hold back, Ken! Remember, I know CPR!!!")
Blogging provides a nice look back at the journey. Way back in March I posted pictures from my first training runs in San Francisco, and using Gmap-Pedometer I quickly established the routes that would become the core of my training (Costa Mesa to Newport Pier, Costa Mesa to Huntington Pier, Costa Mesa to chocolate bananas on Balboa ... )
Kudos to the organizers of the Long Beach Marathon: it was a super well-planned and well-executed event, a beautiful course, and a whole lot of fun. I thought it was especially great how they thawed Elvis from his cryogenic storage to cheer us on (pictured below). I will be back for more running fun at Long Beach next year.
The stats for the first printing of my trading cards...
Pace: 8:02 per mile / 3:30:19 total chip time
Place overall: 171 out of 2343
Place among men: 152 out of 1462
Place in my age group (35-39): 29th out of 243
I'm still well off of a Boston qualifying time of 3:15:59, but I'm sure that with enough time and practice, I'll get to that pace and better. Most important: I'm very much enjoying these stabs at amateur athleticism. Try.
Saturday, July 21, 2007
example | C# .NET ASP.NET | Writing a directory's contents as XML, and binding that XML to an ASP.NET databound control
Intent: Write an XML file that describes each file in a directory, and then use that XML file as a datasource for an ASP.NET databound control.
Discussion: .NET has high-level abstractions for creating XML in the form of the XmlTextWriter object. It is fairly easy to use.
Overview: Instantiate a DirectoryInfo Object. Instantiate a FileInfo array by calling the .GetFiles on your instantiated DirectoryInfo object. Instantiate a MemoryStream object. Instantiate an XmlTextWriter object and set its character encoding to UTF-8. Initate a foreach loop over the FileInfo[] array, instatiating a fileInfo object on each iteration of the loop. To open a new element and populate it, call XmlTextWriterObject.WriteStartElement, then call XmlTextWriterObject.WriteString to assign the content of the element, and then call XmlTextWriterObject.WriteEndElement() to close it. Note that elements can be nested; be sure to call the .EndElement() method at the appropriate place for your nest. Write the finished Xml to a file by instantiating a FileWriter object, calling OpenWrite(Filename), instantiating a byte[] array and calling the MemoryStream.ToArray() method, and finally calling the FileStream.Write() using the byte array as a parameter of the method. Once the XML is written, specify it as an XmlDataSource by assigning the byte array to the XmlDataSource.Data property and calling the XmlDataSource.DataBind() method. (whew!)
Weaknesses: I'd like to know how to avoid writing the Xml to a temporary file, as shown below. How can this all happen in memory?
protected void ShowPhotoGrid( string jobID)
{
DirectoryInfo dir = new DirectoryInfo(@"R:\whatever\"+jobID);
FileInfo[] fis = dir.GetFiles("*ld200.jpg");
//FileInfo fi = new FileInfo();
MemoryStream s = new MemoryStream();
XmlTextWriter xw = new XmlTextWriter(s,Encoding.UTF8);
xw.WriteStartDocument();
xw.WriteStartElement("filesystemitems");
string largefilename = "";
foreach (FileInfo fi in fis)
{
xw.WriteStartElement("filesystemitem");
xw.WriteStartElement("filename");
xw.WriteString(fi.Name);
xw.WriteEndElement();
xw.WriteStartElement("filenameandpath");
xw.WriteString("http://whatever.org/content/whatever/" + jobID +"/" + fi.Name);
xw.WriteEndElement();
largefilename = StringManipulation.LeftOfRightmostOf(fi.Name, '_');
largefilename = (largefilename + "_ld600_watermark.jpg");
xw.WriteStartElement("filenameandpathlarge");
xw.WriteString("http://whatever.org/content/whatever/" + jobID + "/" + largefilename);
xw.WriteEndElement();
xw.WriteStartElement("filesize");
xw.WriteString(Convert.ToString(fi.Length));
xw.WriteEndElement();
xw.WriteEndElement();
}
xw.WriteEndElement();
xw.Flush();
// Write memorystream to a file. This is not the most efficient way to do this. What's better?
FileStream fs = File.OpenWrite(@"R:\whatever\blahblah.txt");
byte[] data = s.ToArray();
fs.Write(data, 0, data.Length);
fs.Close();
// Convert the data array to a string and response.write it
string myString = System.Text.Encoding.UTF8.GetString(data);
// Response.Write(myString);
XmlDataSource1.Data = myString;
XmlDataSource1.DataBind();
DataList1.DataBind();
}
//???? How do I convert my MemoryStream object to a string
// It involves Writing the MemoryStream to a byte array, and converting it to a string, but I can't get things working quite right
}
example | C# .NET ASP.NET| Binding image names from a filesystem to an ArrayList, and binding that to ASP.NET databound control
Intent: Sometimes you want to display photographs contained in a filesystem directly, without referencing an intermediate data layer like a database store or XML file. You
Overview: Instantiate an ArrayList. Iterate over the output of the Directory.GetFiles() method, specifying the image extension as a mask. Build up HTML that should be placed in each cell of a databound control. Call the ArrayList's .Add method to write the HTML string to the ArrayList. Assign the Array as the DataSource of a DataList. Bind that DataList to an <ItemTemplate> using the <%# Container.DataItem %> syntax. Call the DataList.DataBind(); method.
Discussion: The example below also allows the user to adjust the number of displayed columns via a DropDownList selection. This works by programmatically assigning the DataList.RepeatColumns property to the DropDownList.Selected property.
ArrayList pics = new ArrayList();
string code;
string image;
//string myFile;
foreach (string myFile in Directory.GetFiles(("T:\\WHATEVER\\WhateverSubDir"), "*.jpg"))
{
image = YOUR_DIRECTORY + Path.GetFileName(myFile);
code = "<img src=\"" + image + "\">";
code += "<br /> " + Path.GetFileName(myFile);
pics.Add(code); // add the image to your ArrayList
}
// Bind the pics to a DataList
dlImages.DataSource = pics;
dlImages.RepeatColumns = Convert.ToInt32(DropDownList1.SelectedValue);
dlImages.DataBind();
<form id="form1" runat="server">
<div>
<asp:DropDownList ID="DropDownList1" runat="server" AutoPostBack="True">
<asp:ListItem Value="1">One column</asp:ListItem>
<asp:ListItem Value="2">Two Columns</asp:ListItem>
<asp:ListItem Value="3">Three Columns</asp:ListItem>
<asp:ListItem Value="4">Four Columns</asp:ListItem>
</asp:DropDownList>
<asp:DataList ID="dlImages" runat="server" RepeatColumns="5" RepeatDirection="Horizontal">
<ItemTemplate>
<%# Container.DataItem %>
</ItemTemplate>
<ItemStyle Font-Names="Arial" Font-Size="X-Small" />
</asp:DataList></div>
</form>
example | C#, .NET, EntitySpaces | Testing whether an item is already in the database
Intent: Using the EntitySpaces ORM framework, test whether an item exists in a database or not. The example below shows a test of whether a "tag" appears in the database.
Overview: Write a function which accepts the item to test as a string parameter. Instantiate an EntityCollection. Execute an ES Query on that collection, using the Like operator and using the tag string as the parameter. Execute the ES .Load() method to load all available items into a collection. Run a comparison operation on whether Entity.Count is greater than or equal to one. If you wish to return a property of the found items, iterate over the EntityCollection using foreach, instantiating a single item within the collection on each loop. Return the property of the found item if you wish.
Discussion: Useful if you want to enforce single entries to a database table. The tags example below is a good application of this: you want to build a directory of categorical tags and list them only once, referencing the single tag many times using a Join table.
public int IsTagInDatabase(string tagToCheck)
{
TagsCollection tagcoll = new TagsCollection();
tagcoll.Query.Where(tagcoll.Query.Name.Like(tagToCheck.ToLower()));
tagcoll.Query.Load();
int tagID = 0;
if (tagcoll.Count >= 1)
{
foreach (Tags tag in tagcoll)
{
tagID = Convert.ToInt32(tag.Tagid);
}
return tagID;
}
else
{
return 0;
}
}
example | C# .NET | Isolating a directory that DOES or DOES NOT contain a particular substring
Intent: This is useful in instances when you have a highly organized archive with different, similarly-named directories in them, e.g. FolderNameRAW and FolderNameTIF
Overview: Declare a string array using the Directory.GetDirectories() method. Iterate over each string in the array. Use the string.IndexOf method to isolate the substring of interest. Execute a comparison, with a result of >= 1 meaning that the substring is found, and a comparison of == -1 indicating that the substring was not found.
string[] dirs = Directory.GetDirectories(sourceImageDirBase);
foreach (string dir in dirs)
{
if (dir.IndexOf("RAW") >= 1)
{
// Do something here to images that DO have the string RAW as part of their name
}
{
if (dir.IndexOf("RAW") == -1)
{
// Do something here to images that DO NOT have the string RAW as part of their name}
}
}
Wednesday, March 21, 2007
Emulating max-width in IE
Great little article concerning how to constrain the maximum width of text columns in IE to a specified pixel width, while still offering users the ability to scale the page more narrowly if necessary. Many versions of IE do not properly implement max-width and so modern CSS2- based solutions are out. On to the hackery:
http://www.svendtofte.com/code/max_width_in_ie/ (the great little article)
http://msdn.microsoft.com/library/default.asp?url=/workshop/author/dhtml/overview/recalc.asp (MSFT page on dynamic properties)
The meat for my purposes (read the original article; it has many implementations that may serve you better):
<html>
<style>
body {
width:100%;
margin:0;
padding:0;}
p {
border:1px solid red;
max-width:800px;
width:expression(document.body.clientWidth > 800? "800px": "auto" );
}
</style>
Somewhat predictably, these hacks don't work at all in HTML mail, which is unfortunate given that's where I wanted to implement it. However, they don't break things either, which is nice for the purposes of webpages that live dual lives as standalone pages and components of multipart mails. My understanding is that max-width is implemented in Outlook 2007 along with a bunch of other CSS properties. By 2019 or so I imagine be able to confidently implement this when we aren't being deservedly chased around by unhappy Replicants.
Friday, March 16, 2007
VS.NET 2005 Basics, Part II: Shortcut Keys
Keep your hands on the keyboard, and you will work with agility. Short list of the best/most useful VS.NET 2005 shortcut keys, plagarized from everywhere:
MAJOR WINDOWS AND TOOLBOXES
Ctrl + Alt + S = Server Explorer
Ctrl+Alt+A = Command Window
Ctrl+Alt+O = Output Window
Ctrl+Alt+T = View Document Outline
Ctrl+Alt+I = Immediate window, evaluate expressions and execute individual commands
Ctrl + Alt + X = Toolbox
Ctrl+ Alt + K = Task List
Ctrl-K, Ctrl-B - Open Code Snippet manager
F4 = Properties Window
Shift + F4 = Property Pages
Ctrl + Shift + C = Class View
Ctrl + Shift + E = Resource View
Ctrl + Alt + C = Call Stack
Ctrl + Alt + V, L = Locals
NAVIGATING CODE
Ctrl-Minus = Takes you backward to the last section of code you were looking at
Ctrl-Shift-Minus = Takes you forward to the next section of code in your history.
F12 = Jump to definition. On a method, it will navigate back to its source. On an overloaded method, you'll be presented with pop-up window that cues you for which method signature you had in mind. Duplicates the (slower-to-use) context menu.
Ctrl + I = Incremental Search Down
Ctrl + Shift + I = Incremental Search Up
Ctrl + D = Go to find Combobox
Ctrl + Shft + F = Find in Files
F8 - Move to next item. Works in many windows, e.g. the task list.
Ctrl+] = Bounce cursor between balancing braces/parens
SNIPPETS
Ctrl-K, Ctrl-B - Open Code Snippet manager
OUTLINING
Ctrl-M, Ctrl-O = collapse all outlines
Ctrl-M Ctrl-L = expand all outlines
Ctrl-M, Ctrl-M = expand a specific outline section
MAKING SENSE OF INTELLISENSE
Ctrl-Shift-Space = Restore Intellisense parameter window. Useful if you "disappear" it via mouse or keyboard input.
Ctrl-J = List members. Restores what you normally get when you hit "." after an object instance
CLEANING UP YOUR CODE
Ctrl-A Ctrl-K Ctrl-F = Reformat page
Shift-Enter = insert new blank line above current line
Ctrl-Shift-Enter = insert new blank line below current line
Ctrl-T = transpose the two characters the cursor between current cursor position
Ctrl-Shift-T = transpose words in current cursor position
WINDOWING AND VIEWS
Crtl+Tab = switch between windows inside the current project
Alt+Space, N = Minimize current application
Alt+Space, X = Maximize current application
Alt+Space, R = Restore current application
Shift+ALT+Enter = Full screen mode. Good for laptop dev.
CTRL+R, CTRL+R = Toggle Word wrap.
Ctrl+ F4 = Close active code windows in project
Number pad * = Expand all in the Solution Explorer
Number pad - = Collapse all in the Solution Explorer
Alt+W, L = Close all windows
COMMENTS
Ctrl+K, Ctrl+C = Comment out the current selected section
Ctrl+K, Ctrl+U = Uncomment the current selected section
BOOKMARKS
Ctrl-K Ctrl-K = Set/unset bookmark in current position
Ctrl-K Ctrl-N = Navigate to the next bookmark
CODE VIEW/DESIGN VIEW
Shift+F7 = show designer window
F7 = show code window
Ctrl+PageDown = Toggle between source and design views in .aspx files (yessssss!)
MSDN HELP
Ctrl + Alt + F1 = View Contents Tab
Ctrl + Alt + F2 = View Index Tab
Ctrl + Alt + F3 = View Search Tab
Ctrl + Alt + F = View Favorites Tab
Shift + Alt + F3 = Search results
Shift + Alt + F2 = Index results
BUILDING AND DEBUGGING
Ctrl+Shift+B = Build solution
F9 = Toggle Breakpoint
F5 = Start
Shift + F5 = Stop Debugging
Ctrl + F5 = Start Without Debugging
F11 = Step Into
Shift + F11 = Step Out
F10 = Step Over
CUT, COPY, 'N PASTE
Cntl+C (with nothing selected) = copy entire line
Ctrl+Enter = copy line above
VS.NET 2005 Basics Part 1: XML Documentation, Intellisense, and automatic documentation generation
XML documentation is an insanely great feature of Visual Studio.
Why? In a word, Intellisense. If you're a total newbie, welcome. Intellisense is simply a collection of informational popup windows that appear while you're programmming, and these popups contain extremely useful information relating to the code you are trying to write. Intellisense saves time, jogs your memory, and helps you write code accurately. If you have written or have inherited a complex hierarchy of reusable programmatic classes, Intellisense will help you remember the organization and needs of that class structure.
If you document your code using VS.NET's simple XML-based tagging, you'll be continually prompted with Intellisense windows with information about what your code does. You can integrate your own writing and documentation into the experience of working with the VS.NET tool. This is so powerful.
A few examples and screenshots will really help explain things here.
Long ago I wrote a class called "FileOps," which is a grab-bag of very useful functionalities (methods AKA functions) relating to file operations on our web application server. I commonly use these methods in my web application work, so I've put the FileOps class in a subfolder of my App_Code folder so it is available to be used by any of my applications.
One of the methods (functions) in that class is CreateYearAndMonthDirectoryBasedOnDate(). This method creates and helps maintain an organized file structure on our server's file system, arranging it in a useful hierarchy similar to the folder structure illustrated below:
Let's have a look at some of the code for that method now. The code includes a bunch of comments structured as XML, positioned just prior to the code that defines the method. These comments document different aspects of the method's operation, including its parameters (inputs) and return type (output.) Structuring your documentation in this particular way is extremely useful if you're working in Visual Studio. We'll soon find out why.
/// <summary>
/// <para>Creates a hierarchical folder structure corresponding to a year and month on a server filesystem, e.g.</para>
/// <para></para>
/// <para>c:\basePhysicalDirectory\2007\July\</para>
/// <para></para>
/// <para>You can subsequently copy files into these folders, creating an automatically organized folder structure. </para>
/// <para>If the folder already exists, then it will simply return the path to the existing directory.</para>
/// </summary>
/// <param name="inputDate">DateTime upon which to base the creation of the new folder</param>
/// <param name="basePhysicalDirectory">The base physical directory on the server filesystem that will be used to create the year and month folders.</param>
/// <returns>Returns a string corresponding to the newly created (or existing) path on the server filesystem.</returns>
public static string CreateYearAndMonthDirectoryBasedOnDate(DateTime inputDate, string basePhysicalDirectory)
{
string yearDirectory = Path.Combine((basePhysicalDirectory), ((inputDate.ToString("yyyy")) + @"\"));
string monthDirectory = Path.Combine(yearDirectory, ((inputDate.ToString("MMMM")) + @"\"));
if (!Directory.Exists(monthDirectory))
{
if (!Directory.Exists(yearDirectory))
{
System.IO.Directory.CreateDirectory(yearDirectory);
[etc.]
"So what?" say the cynics. "It's just a bunch of code comments as XML. Big deal." Well... the Good Part comes two weeks or two years later, when I'm trying to use my handy FileOps class in other programming projects. What follows is my view from Intellisense as I call the FileOps class's methods to do some useful work. Below, I'm saving out a programmatically created PDF file, and I want it to be filed in an organized way. I use CreateYearAndMonthDirectoryBasedOnDate() to generate a folder structure on the server based on a database entry associated with the PDF. What I want you to pay attention to here is how VS.NET uses Intellisense and the XML documentation I wrote for the method to give the programmer a step-by-step cue of what she should be doing next.
(Step 1: As I type "FileOps", the name of my class, notice I'm presented both a selectable list of all of the classes available to me, and a yellow comment box. The comment box includes an XML comment I wrote that describes the entire "FileOps" class. (Interested in the database abstraction code? Check out the sublime EntitySpaces Object-Relational Mapping framework ))
(Step 2: As I hit the period ".", which denotes the fact that I want to call a method of my FileOps class, the previous Intellisense informational window disappears, and a selection of the methods I have written in the past and associated with FileOps pops up. Note that the XML documentation I wrote earlier to accompany my method is appearing as a comment in Intellisense. Very handy! Anything that reduces the amount of stuff the developer has to keep in her brain at once is a great thing.)
(Step 3: I continue typing and am now filling in the parameters that are required by my method. Remember how I described my parameters in XML documentation with the <param>...</param> tags? My context-specific documentation appears right here, right when I want to see it.)
(Step 4: When I reach the last parameter that my function requires, again it shows me the descriptive docs I wrote for what the parameter is and does. Sharper-eyed newbies will also notice that the datatype of the parameter is being indicated, which helps remind the finite and forgetful programmer what information the method requires to do its work.)
This is a deliberately simplified example involving straightforward static methods. For many people, Intellisense is old hat and reading "Run Dick Run" above may seem more than a little patronizing. However, I'm surprised how many otherwise smart developers out there don't use VS.NET's XML documentation to describe their classes or methods at all. Makes no sense. This stuff is great: context-specific information when you need it, and changeable as required with very little investment of time. If you're rooting around for just the right web application technology to learn, Intellisense/VS.NET and this documentation stuff is in itself a compelling argument to take a serious look at ASP.NET.
This XML documentation can also be parsed by external tools and compiled into CHM (Microsoft Help) files, or sets of HTML pages. My understanding is that for a long time the de facto standard for this kind of tool was the free nDoc tool, but as of last summer NDoc is not being developed further. Microsoft is in the process of picking up the external documentation ball with SandCastle, and I imagine we'll see something like it in the next release of Visual Studio.
I'm going to underscore a few things that may not be obvious to VS.NET newbies and newbies at heart.
1) To document your code, get in the habit of hitting three slashes before front of any method, property, class, or other structures in your code files. VS.NET is smart and will figure out what comment types are relevant given where you're at in the code. If you've been hand writing <summary> ... </summary> or <param> ... </param> as XML comments as you've studiously followed some tutorial you picked up somewhere, you have been doing things the hard way. Enter three slashes, and let Visual Studio do the work of writing this cruft for you, including a summary section, a comment for each parameter, and a comment for the return type.
2) The VS.NET Task List is useful, and you can automatically add stuff to the Task List using TODO comments in the correct form. You would think that you might embed todo comments using the same XML patterns, e.g.
WRONG! <todo> Rewrite this method!</todo> WRONG!
This does not work the way you might think. Entering a comment in the following form will automatically place a TODO item on the task list:
//TODO: Rewrite this method. Summary of XML comment tags that are parsed by VS.NET
I'm going to borrow the Code Project's excellent, terse summary of tag types and comments about the tags for my own reference. The text below is courtesy of a great article at the Code Project that also describes how to set up NDoc to generate MSDN-style documentation from XML comments.
The summary tag is the most basic of tags. The list below is the complete set currently supported by VS.NET. The ones marked with a * are the ones I feel are the most useful and the ones we will be dealing in the following examples.
c
The c tag gives you a way to indicate that text within a description should be marked as code. Use code to indicate multiple lines as code.
code*
The code tag gives you a way to indicate multiple lines as code. Use <c> to indicate that text within a description should be marked as code.
example*
The example tag lets you specify an example of how to use a method or other library member. Commonly, this would involve use of the code tag.
exception*
The exception tag lets you specify which exceptions a class can throw.
include
The include tag lets you refer to comments in another file that describe the types and members in your source code. This is an alternative to placing documentation comments directly in your source code file.
para
The para tag is for use inside a tag, such as <remarks> or <returns>, and lets you add structure to the text.
param*
The param tag should be used in the comment for a method declaration to describe one of the parameters for the method.
paramref
The paramref tag gives you a way to indicate that a word is a parameter. The XML file can be processed to format this parameter in some distinct way.
permission*
The permission tag lets you document the access of a member. The System.Security.PermissionSet lets you specify access to a member.
remarks*
The remarks tag is where you can specify overview information about a class or other type. <summary> is where you can describe the members of the type.
returns
The returns tag should be used in the comment for a method declaration to describe the return value.
see
The see tag lets you specify a link from within text. Use <seealso> to indicate text that you might want to appear in a See Also section.
seealso*
The seealso tag lets you specify the text that you might want to appear in a See Also section. Use <see> to specify a link from within text.
summary*
The summary tag should be used to describe a member for a type. Use <remarks> to supply information about the type itself.
value*
The value tag lets you describe a property. Note that when you add a property via code wizard in the Visual Studio .NET development environment, it will add a <summary> tag for the new property. You should then manually add a <value> tag to describe the value that the property represents.
Resources:
Producing Professional MSDN-style Documentation with .NET and NDoc
http://www.devx.com/dotnet/Article/29646
C# and XML Source Code Documentation
http://www.codeproject.com/csharp/csharpcodedocumentation.asp
NDoc on SourceForge:
http://ndoc.sourceforge.net/
Insightful O'rielly article on NDoc and the problem of documentation generation in general:
http://www.ondotnet.com/pub/a/dotnet/2002/12/09/ndoc.html
Saturday, March 10, 2007
Finding JPG image dimensions programmatically using ASP.NET/C#
.NET includes everything necessary to programmatically read the dimensions of image files such as .JPGs. This is useful in cases where you want to explicitly specify the size of an image at runtime. In my case, I had an image cropping control that required I send the dimensions of the image to be cropped. The means to return image size in .NET is a bit verbose, but it is nice that you can do this without going to an external component or anything outside of what's baked into .NET. See below.
using System.Drawing;
using System.Text;
ImageCropper1.ImageUrl = "../../test8180-uweek mail prelim design.jpg";
string myDimensions = ImageProcessing.GetImageDimensions(@"c:\Inetpub\wwwroot\ni\test8180-uweek mail prelim design.jpg");
string[] dimensions = myDimensions.Split(new char[] {','});
string imageWidth = Convert.ToString(dimensions[0]);
string imageHeight = Convert.ToString(dimensions[1]);
ImageCropper1.Width = Convert.ToInt16(imageWidth);
ImageCropper1.Height = Convert.ToInt16(imageHeight);
Imageprocessing is a custom class I wrote/stole: something old, something new, something borrowed, and something blue. It consists mainly of static methods, including the GetImageDimensions function called above:
public static string GetImageDimensions(string fileNameAndPath)
{
System.Drawing.Image theImage = System.Drawing.Image.FromFile(fileNameAndPath);
float UploadedImageWidth = theImage.PhysicalDimension.Width;
float UploadedImageHeight = theImage.PhysicalDimension.Height;
string size = UploadedImageWidth.ToString() + "," + UploadedImageHeight.ToString();
return size;
}
Two things bug me. The first: the Krispware cropping control demands the following structure for the path to the image, at least on my local development machine:
ImageCropper1.ImageUrl = "../../test8180-uweek mail prelim design.jpg";In my case and on my machine, I found I could not use the typical "~/" pathing notation to the root; on the same page I placed an Image control and was able to use "~/" just fine. This could be caused by any of a number of things:
a) an inherent limit of the control
b) something funky that's specific to my dev machine, or
c) something funky with how the virtual directories were set up on installation, which I don't really understand well. (Any help out there?)
Second question. In the course of hacking around with this started to think, "wow, maybe I should write my own augmented image class that would bundle in loads of functionality and allow capabilties like:
KensCoolImageClass CoolImage = new KensCoolImageClass();
Coolimage.RenderAsCropControl();
Coolimage.RenderAsUserControl(300,200,"isZoomable" ...);
Coolimage.SendToFriend(mediumSize, "kenfine@u.washington.edu);
Coolimage.CropByCoords(22, 200,4, 400);
Coolimage.UpdateExifData("metadata1","metadata2,...);
Coolimage.PostToFlickr(encrypedAccountName, encrypedAccountPassword);
Coolimage.ResizeByPercentage(40);
Coolimage.Rotate(90, "clockwise");
int theHeight = Coolimage.Height;
int theWidth = Coolimage.Width;
I'm curious why some of these functionalities are not built into the framework itself: my code above works, but it seems a little more painful than should be necessary.
Thursday, March 08, 2007
The Run from Costa Mesa to Newport Pier in Pictures
Strong run. Left home around sunset-time and ran back on the Santa Ana Trail in darkness.
Running in the dark in a near-abandoned industrial wasteland may not be bright. My uncle-in-law Jerry swears that "they'll slit your throat!" but it hasn't happened quite yet.
Some of the most fantastic runs I've had have been in the dark, at times and places responsible folks tell you not to go. I remember running through NYC's Central Park long after nightfall in 2005. Lovers shared benches, old Greek men perfumed the air with pipes. I ran fast, the summer night thick with stars and fireflies.
My route from Costa Mesa to Newport Pier on Gmap Pedometer
Labels: photography, running
Tuesday, March 06, 2007
The Run from Costa Mesa to Huntington Pier in Pictures
Dreary visions of yesterday's run from my cell phone camera. I like seeing what's possible with such limited equipment.
Labels: photography, running
Sunday, March 04, 2007
Visions of the Golden Gate
Synthetic glimpses of an architectural masterpiece. Some of these photographs are elaborately manipulated in terms of levels (contrast) and perspective. The effect is disquieting: untidy humanity wiped away, leaving only clean abstractions. I'm uncomfortably reminded of the early works of a certain painter-turned-politician ...
I shot these pictures with my "running camera": an older Nikon Coolpix 995 that fits the hand like a baton.
Labels: photography, running
Saturday, October 02, 2004
IMAGE AND REALITY : Marc-André Hamelin
Image...
...and reality. The authentic Hamelin walked onto Meany's black stage Thursday night, tux misplaced. He was clad in simple gray slacks and a casual shirt that might have been pulled from a country-western watering hole in Texas. Great green embroidered ribbons of foliage and threaded red roses graced Hamelin's shoulders. "Cool," Essie offered. Mr. Hamelin received my wife's good tidings and the audience's applause modestly.
Like every other performer I've seen at the "President's Piano" series at the University of Washington, Hamelin can play with the world's best. His first piece of the evening, Bach's "Chaconne from the Violin Partita in D minor" was affecting, but maybe that's just the insinuations of all the Hofstader I've been reading lately. Bach's piano stuff is very hard to play well, so I'm told.
Hamelin reminds me of Stephen Hough, who played like a god as the headliner of the President's Piano series two years ago. Like Hough, Hamelin's technique is immaculate. Also like Hough, Hamelin has a big bright creative mind hanging over those terrific hands. Both men performed some of their own compositions in the course of their performances. Hamelin's haunting "Music Box" evoked the quieting bells of rusting wind-up toys, the last dances of faded and tired things. Hamelin finished the piece with a long sigh, and Meany's full house spontaneously mumured its approval.
Labels: piano

