Thursday, January 12, 2006

Oracle has finally joined the bandwagon of creating an express edition of its database server! This is great news to those that want to foray into new uncharted waters of using an Oracle DB. Myself I have only used SQL Server databases, the first one being version 7.0 and finally ending up with SQL Server 2005. So this will be a totally new experience for me.

 

The benefits of using this express edition of the Oracle database is that it will be far easier for software developers to create products that use the Oracle database as its backend. Also for students this means having an actual database to kick around instead of having to Telnet into a database in order to learn the subject matter.

 

There seems to be few limitations to this database as it can hold up to 4GB of user data and use up to 1GB of RAM. This seems plenty for what this database is designed for which is mainly for students and small DB backends for ISV’s to use as their database of choice.

 

At this moment the product is only in Beta so I am going to wait until it is fully released before I install it on my machine. I have a rule of never installing beta products on my machine because of the probability of having my computer getting fried. Not a pleasant situation believe me.

 

You can learn more about this release here.

1/12/2006 1:33 PM Eastern Standard Time  #    Disclaimer  |   | 

This is a tip I learned some time ago on how to make a Windows XP CD bootable. This should work on most cases as  I have never heard anyone complain that this did not work.

 

Here are the steps:

 

1. Make a directory to store the integrated (slipstreamed) OS:
    mkdir <DEST DRIVE>:\XPSP2_Int\Pro

2. Copy my Windows XP w/SP1a to my hard drive:
    xcopy <CD DRIVE>: <DEST DRIVE>:\XPSP2_Int\Pro /E

3. Extract the XP SP2:
    <CD DRIVE>:\xpsp2.exe /X:<DEST DRIVE>:\XPSP2Temp

4. Integrate, or slipstream XP SP2:
    <DEST DRIVE>:\XPSP2Temp\update\update.exe /Integrate:<DEST DRIVE>:\XPSP2_Int\Pro

5. Make the bootable CD-ROM by following the instructions here.

 

That should be all you need in order to create a bootable CD for Windows XP SP2. More tips & tricks coming soon.

1/12/2006 7:50 AM Eastern Standard Time  #    Disclaimer  |   | 
 Wednesday, January 11, 2006

We here in Florida have a very strong developer community. We have many local .Net user groups to help support those just coming into the field of .Net programming and also help those with their particular struggle with a particular project that they are working on.

 

In Orlando we have the Orlando .Net Code camp details as follows:

 

When and where:

When:

March 25th, 2006

Where:

Orlando, Florida

Exact location to be determined (as of this writing)

 

The website for this code camp can be reached here.

 

In the Miramar area we have the South Florida .Net Code camp with details as follows:

 

When and where:

When:

February 4th, 2006

Where:

Devry University

Miramar Campus

2300 SW 145th Ave. Miramar Florida 33027

To register click here

 

To bad there isn’t any local Tampa Bay Code Camps that I am aware of. Maybe I should work on getting one started. Is anyone interested in attending perhaps a half day in Sarasota for a “mini code camp”? Let me know in the comments of this post.

 

1/11/2006 12:39 PM Eastern Standard Time  #    Disclaimer  |   | 
 Monday, January 09, 2006
Data Binding in Windows Forms 2.0 - by Brian Noyes

This meeting will be on Tue, Jan 17, 206 at 6pm. Location: Sarasota Community Foundation, located at 2635 Fruitville Rd., Sarasota, FL 34237 (just west of Tuttle on the north side of Fruitville).

Windows Forms 2.0 introduces a host of new capabilities for managing data binding scenarios. The BindingSources component allows you to easily bind to almost any kind of data source, and the Data Sources window in Visual Studio 2005 makes it easy to generate the code to hook up BindingSources to controls. This session will demonstrate the use of BindingSources and the Data Sources window to handle a variety of complex data binding scenarios including Master-Details, data bound custom controls, and keeping multiple sets of data bound controls synchronized.

About Brian Noyes:

Brian Noyes is a Microsoft MVP and an international speaker, trainer, writer and consultant with IDesign (www.idesign.net). He speaks at Microsoft TechEd US, Europe, and Malaysia, Visual Studio Connections, SDC Netherlands, DevTeach Montreal, VSLive!, DevEssentials, and other conferences, and is a top rated speaker on the INETA Speakers Bureau. He has published numerous articles on .NET development for MSDN Magazine, CoDe Magazine, The Server Side .NET, and other publications. Brian latest book, Data Binding with Windows Forms 2.0, part of the Addison-Wesley .NET Development Series, will hit the shelves in the January 2006, and his next book, Smart Client Deployment with ClickOnce will follow in the summer of 2006. Brian’s blog can be found at http://www.softinsight.com/bnoyes/.

Please be sure to register on our website in order to get updated information about all meetings and any other up coming events in the Sarasota area. Also if you are interested in sponsoring our little but growing local developer community please e-mail me.

1/9/2006 6:24 PM Eastern Standard Time  #    Disclaimer  |   | 
 Saturday, January 07, 2006

Today I was looking forward to seeing Bill Gates keynote address that he gave at the latest CES in Las Vegas. I went to Bill Gates webcast website and clicked on the 300K streaming media link as I have a very high speed internet connection. However, to my disappointment the webcast ended up not a fluid dynamic presentation but rather more of an audio show with still images taken from the webcast. So this begs the question as to why is it that Microsoft can not seem to get streaming media correct?

 

I contrast this with the same keynote experience from Steve Jobs using Apple’s Quicktime media player. What did I see a fluid, crystal clear experience of the presentation with just some minor stuttering and glitches as one would expect even from a high speed connection.

 

Now you see I am using a brand new Dell Windows Media Center edition PC with one of the best video cards available and one of the highest speed processor that I can buy. Why is it that on a Windows machine the streaming media experience is so much better with Quicktime than with the Windows Media player? It is pure shameful that this should be the case. How can Apple develop so much better of a Windows program than Microsoft?

 

I would love to see the Bill Gates keynote but I am simply spoiled the sheer quality of the Quicktime experience. I eventually gave up viewing the keynote using the streaming media using the Windows Media player. Hopefully the developers at the Windows Media center are listening and working hard to solve this issue with the program. Because if they do not hurry up Apple will quickly overtake them with the home entertainment experience. Just my little rant for the day I guess.

1/7/2006 2:32 PM Eastern Standard Time  #    Disclaimer  |   | 
 Friday, January 06, 2006

For many developers out in the .Net community it was ASP.Net that initially drove them to switch from some other platform. This was most likely due to the much enhanced programming model that ASP.Net provided and the improvements in performance that were promised and delivered. However, although the ASP.Net platform is a highly robust and scalable system you should still be aware of a few tricks of the trade that may help you increase your performance on your web application.

 

During my years of working with .Net I have learned many things on how to properly deal with certain situations that arise. Hopefully, you will find this information useful.

 

Best Practice #1

It is usually a good idea to set the SmartNavigation property to true on most pages.

The reasoning:

This reduces or eliminates screen flickering during postbacks to the server. Furthermore the scroll position will be preserved.

 

Best Practice #2

Enable the ability for multiple postbacks when using AutoPostback controls by using a user interface device such as a button.

The reasoning:

If the user has disabled Javascript controls in their browser then there is no way for the user to submit the form unless you provide a button or other user interface device.

 

Best Practice #3

It is preferred to use the Server.HtmlEncode method when displaying data taken from the database to an HTML control or Web control.

The reasoning:

This makes sure that the special characters are displayed in the correct manner and prevents cross side scripting attacks.

 

Best Practice #4

It is always best to validate input on the client side by using a validator control. Also, make sure you also validate all data on the server side as well as unforeseen security vulnerabilities can put your server at risk.

The reasoning:

Validation of all data is a best practice in all situations. This ensures a consistent database and data integrity and the integrity of your website.


Best Practice #5

It is usually a best practice to make sure the client is still connected during a time consuming task. This can be accomplished using the Response.IsClientConnected method during a known time consuming task.

The reasoning:

This method allows you to check to see if the client is still connected to the server. If the client is no longer connected you can then use the Response.End method to end the session and free up resources.

 

Best Practices #6

It is usually a good practice to avoid the use of hidden fields in order to store data between page postbacks.

The reasoning:

There are few very good reasons for storing potentially sensitive information using hidden fields. These do not store data in an encrypted manner or can store any significant amounts of data.

 

Best Practice #7

It is usually a good practice to store data taken from either files or a database in the ASP.Net cache object if the data does not change much over a period of time and can be shared with multiple users on the webpage.

The reasoning:

By storing and caching the data taken from a file or database you increase the performance and scalability of your application.

 

Best Practice #8

It is a best practice to use a Global error handler in the Global.asax file of your application.

The reasoning:

This allows you to recover properly from unexpected exceptions in the current application. Also this may allow you to implement a common error recovery mechanism for your web application.

 

Best Practice #9

It is always best to never use the Off attribute when setting the <custom errors> attribute in the web.config file of your application when it resides on a production server viewable by the outside.

The reasoning:

Doing this will enable unauthorized visitors to view potentially sensitive information about your application thereby increasing the security risk that  your website can be attacked from outside visitors.


Best Practice #10

It is always best to set your application tracing in the web.config file rather than using the @Page directive on individual aspx pages.

The reasoning:

This allows you to enable application level tracing for the entire application rather than for each individual page of  your website.

1/6/2006 1:22 PM Eastern Standard Time  #    Disclaimer  |   | 
 Thursday, January 05, 2006

It can hardly be said that any serious programmer has had to deal with database programming at least some time in their careers. So it would be logical then to make sure your connection to these underlying databases are as efficient as possible. Hopefully I will share some of the best practices I have learned in dealing with ADO.Net programming. These techniques were learned from a variety of sources, many of them I can not remember sorry. Hopefully you will find them equally as useful as I do.

 

Best Practice #1

Always use native .Net data providers.

The reasoning:

It has been proven by using the native .Net data providers always perform better and allow you to take advantage of both the .Net framework and the full power of the underlying database.

 

Best Practice #2

Always use a config file to store your connection strings. Also it might be a good idea to encrypt these connection strings especially if stored in a dubious location.

The Reasoning:

It is always best to store data that might change in a location outside of your application where you can easily update the connection strings. Also encrypting the connection strings is always a good idea from a security standpoint.

 

Best Practice #3

It is always best to use Windows authentication mode when connecting to your SQL Server database, this really applies mostly to Windows Forms applications.

The Reasoning:

Windows authentication is always much safer as the username and password do not pass over the wire.

 

Best Practice #4

Always use an asynchronous delegate when establishing a connection from a Windows Forms application.

The Reasoning:

This will prevent the user interface from seeming to seizing up as the application attempts to connect to the underlying database.

 

Best Practice #5

Prefer to use the sorting methods on the SQL Server such as the ORDER BY, HAVING and GROUP BY statements.

The Reasoning:

By performing the sorting on the server side as opposed to the client side you save time because the server can perform the work faster.

 

Best Practice #6

You should always try to limit the number of rows in a resultset. This can be performed typically by using the TOP keyword or other similar methods.

The Reasoning:

By limiting the amount of information you send through the wire you make the application seem faster and this also allows for a more scaleable design.

 

Best Practice #7

It is always best to use the CommandBehavior.CloseConnection enumerated value when you invoke the ExecuteReader method of a Command object.

The reasoning:

This allows for better connection pooling as the connections that are opened are returned quickly.

 

Best Practice #8

It is always best to cancel before closing a DataReader object if you are finished reading any more rows.

The reasoning:

The close method of the DataReader class continues to read all remaining rows before it finally closes the object. This is a wasteful use of resources.

 

Best Practice #9

It is always best to use a parameterized command over dynamic SQL queries.

The reasoning:

This will improve performance and reduce the a SQL injection attack while also making your code much more easier to maintain.

 

Best Practice #10

It is always best to access tables through views and stored procedures over other methods like dynamic SQL queries.

The reasoning:

The stored procedures and views do not add any overhead to a SQL server while providing some level of indirection which allow you to change the structure of the database table without drastically affecting your client code.

 

Best Practice #11

It is always best to implement some sort of resultset pagination when dealing with results of 50 or more rows.

The reasoning:

Although not an easy task in most cases using this technique you can increase performance on both your server database and your client application as less overhead and network traffic is taking place at any one time.


Best Practice #12

It is always best to close a transaction as quickly as possible.

The reasoning:

When a transaction occurs one or more rows are locked which means other users or applications can not access them. By using as short of a transaction as possible you ensure the scalability and stability of your application.

 

Best Practice #13

Never rely on the default behavior of the DataAdapter object for managing concurrency issues with your database.

The reasoning:

The DataAdapter object relies on the underlying which will leave itself in an inconsistent state if an update occurs, this is because ADO.Net will only throw an exception and not resolve the actual conflict at hand.

 

Best Practice #14

It is usually best to implement a timestamp field when you are using optimistic concurrency.

The reasoning:

This will allow to more easily detect when another user has updated the database.

1/5/2006 7:55 PM Eastern Standard Time  #    Disclaimer  |   | 

SQL Server is a very powerful tool when used properly. It can also come to a screeching halt if left to rot with no maintenance and poor planning. While the program itself is highly scalable it is still subject to performance bottlenecks and slow response times caused by inattentive administrators and developers. I have learned much about SQL Server 2000 in the past year many of those are the best practices used by other developers and senior administrators. I hope to share that information with you now so that those just starting out can learn from what I have learned.

 

Best Practice #1

Download and install and actually use the SQL Server Best Practices Analyzer tool provided by Microsoft.

The Reasoning:

This tool will scan your databases for any code or implementation issues that do not conform to Microsoft Best Practices standards. This should be the starting point on any existing or currently in production database you may have. Now you can take each recommendation with a grain of salt as the tool is probably not aware of every situation a developer may face. So therefore it is always up to the developer or administrator to decide which practices to put into place.

 

Best Practice #2

Never start the name of any stored procedure with the SP prefix.

The reasoning:

All system stored procedures start with the SP prefix. Naming your stored procedures in this manner will cause potential clashes as service packs are released potentially with the exact same naming as your previous stored procedure. This is highly unwise.

 

Best Practice #3

Apply the latest service packs and security packs

The reasoning:

With so many potential threats against a database keeping your system up to date will ensure data integrity. Keeping data integrity should be the duty of anyone either developing on the database or administrating the database.

 

Best Practice #4

Keep your result sets that you return from your database as small as possible.

The Reasoning:

Not only does this greatly improve performance but it makes the database much more scalable and better able to handle more concurrent users.


Best Practice #5

Avoid the Insert statement when performing bulk inserts into your database.

The reasoning:

The DTS or BCP utilities are far better for inserting information in bulk into SQL Server. These utilities are far more flexible then the SQL Bulk Insert statements you may want to use.

 

Best Practice #6

Keep your stored procedures as small as possible.

The reasoning:

If two users are accessing the same stored procedure at the same time then two query plans will be stored in the cache. It is far better to have smaller stored procedures call other stored procedures then one very large stored procedure. This practice makes maintaining the code a bit easier as well.

 

Best Practice #7

Analyze all your query plans using the SQL Query Analyzer to make sure they are performing at optimum speed.

The reasoning:

Getting to know how to use the SQL Query Analyzer is one of the best things any serious developer can do to improve performance in an application. Using this tool you can see where are the bottlenecks in your code and thereby increase performance by altering indexes or even re-writing stored procedures.

 

Best Practice #8

Always code for multiple user scenarios

The Reasoning:

If  you plan ahead and design your database with the proper data concurrency issues already solved then the future up keep of your database will be minimized. While the upfront costs associated with this might be higher the potential payback can be great as a application changes in its lifecycle.

 

Best Practice #9

Use User Defined Functions wisely and sparsely.

The reasoning:

It is far better to use stored procedures in your code then User Defined Functions. While using these functions may at times increase the performance of  your database it is more likely that they will be converted into stored procedures in the future as the database matures.

 

Best Practice #10

Do not use Select * in your query design. Instead make sure you use the proper column names in the query.

The reasoning:

Using the proper column names decreases network traffic, takes less load on the database and hence can greatly improve performance.

Best Practice #11

Avoid the use of nullable columns.

The reasoning:

The use of the nullable column consumes an extra byte on each column used. Furthermore when querying data there is much more overhead with nullable columns. Try to use alternative methods when designing a database to allow for a representation of zero data in the column.

 

Best Practice #12

Analyze and avoid deadlocks at all costs.

The reasoning:

It is far better to access your data the same way each time you query  your database. Doing otherwise will create a deadlock situation when one process takes control while another process is fighting for the same control over the objects. This can greatly tie up resources and can cause your program to crash if not taken into account. Always try to avoid a deadlock before one occurs. Use hints on your queries to make sure they are performing the way you want them to.

 

Best Practice #13

Create indexes on highly selective columns.

The reasoning:

It is far better to create an index on a highly selective column as this will increase the performance of your database design.

 

Best Practice #14

Avoid using cursors or use cursors very wisely.

The reasoning:

Cursors consume far too much database resources to be considered a viable option in most cases. There are other options available and proper design of the program will account for this. However when you need to use cursors, when there is no other alternative, then use them very wisely and make sure  you research any issues with cursors before implementing them in production. Test the database under a realistic load scenario.

 

Best Practice #15

Always make sure your database is as normalized as possible.

The Reasoning:

This is database design 101 here folks. If you have an un-normalized database design make sure to normalize the database design to the 3rd normal form as this is considered to be the standard. The only excuse for a non normalized design is for performance reasons. However my argument with this should be that denormalizing a database schema should be considered a last resort.


Best Practice #16

Remember to SET_NOCOUNT_ON at the beginning of your SQL bataches, stored procedures, triggers, etc.

The reasoning:

Doing this will increase performance by reducing network traffic. Setting SET_NOCOUNT_ON suppresses the messages regarding how many rows are affected after executing INSERT,UPDATE, SELECT and DELETE statements.

 

Best Practice #17

Avoid the use of the TEXT and NTEXT datatypes in your database design.

The reasoning:

There are far too many issues associated with TEXT and NTEXT datatypes for them to be of any great use to you. Instead it is far better to use the varchar and char datatypes instead.

 

Best Practice #18

Do not store BLOBS in your database.

The reasoning:

A database was not designed to stored datafiles or images. Instead it is far better to store the location of these files inside the database and let the operating system handle the file I/O for you. This is far better way to store large data files in your database.

 

Best Practice #19

Always perform referential integrity checks and data validations using constraints such as the foreign key and check constraints.

The reasoning:

It is far better to use constraints as opposed to triggers when performing referential integrity checks. The use of triggers should only be used to perform custom data validation that can not be performed using constraints.

 

Best Practice #20

Make sure all your stored procedures return a value indicating their status.

The reasoning:

Make sure you standardize on the return types your stored procedures should return indicating either success or failure. Doing this will increase the maintainability of the code and make programming against it much easier. This is especially ture if everyone understands and follows the standards.

 

Best Practice #21

Make sure you start each clause of your SQL statement on a new line.

The reasoning:

This makes the SQL code much more readable. You should consider this especially if you are in a team environment or a visiting consultant.


Best Practice #22

It is always best to avoid the use of column numbers in the ORDER BY clause.

The Reasoning:

Using some column numbers does not increase the performance of your query by any significant amount and also this makes  your code harder to read especially in large queries.

1/5/2006 4:24 PM Eastern Standard Time  #    Disclaimer  |   | 

Stings are a difficult and sometimes touchy subject when it comes to programming. In the C language improper use of strings can crash your whole system. Even some professors in Colleges and Universities do not teach their students how the native string functions in the C language work simply because they consider them far too dangerous for students to learn.

 

I will try to cover the best practices of handling strings that I have picked up over the years in the hope that it will either improve your performance or stop you from making some of the blunders I have made in the past.

 

Best Practice #1

Pertains to Visual Basic

It is always best to use the & to concatenate strings instead of the + operator.

The reasoning:

The + operator was only kept for historical reasons. It is far better to use the & operator because it make your code easier for other programmers to read it.

 

Best Practice #2

Use a char variable instead of a string variable only if you are certain you need to store only one character.

The reasoning:

The char variable takes up less space than a 1 character string.

 

Best Practice #3

Always explicitly initialize string variables to a zero length string.

The reasoning:

By explicitly initializing a string variable you avoid NullReferenceException errors when you reference the string.

 

Best Practice #4

You should always return an empty string when defining a method or property when the end result string has no characters.

The reasoning:

This simplifies the task of the calling code which will then not have to test for a null.

 

Best Practice #5

Never use language specific string functions.

The reasoning:

Language specific functions always perform worse their .Net native methods.


 

Best Practice #6

When checking for empty strings compare the length property with zero rather than with a String.Empty

The reasoning:

Checking the string length for zero has better performance then with the String.Empty method.

 

Best Practice #7

When comparing two strings use the String.Compare method to compare strings in case insensitive mode.

The reasoning:

The ToUpper and ToLower methods both create a new string and by doing this affect the memory heap. Also the Compare static method is far faster then using the ToUpper and ToLower string functions because there is no need to create new strings and then compare them.

 

Best Practice #8

Always use the Regex type to validate string input by the user or read from an external source such as the file system.

The Reasoning:

You should always validate input from any source that could affect the security or performance of your application.

 

Best Practice #9

Never hard code any value or variable that may change once the application goes into production. Instead store those values in a config file that your program can use to update those values dynamically.

The reasoning:

You simply do not want to have to update the entire program simply because something has changed in the production environment. This is a headache you simply want to avoid at all costs.

 

Best Practice #10

Avoid hard coded strings that may appear in the user interface. Instead use a resource file instead.

The reasoning:

You always want to avoid any programming that would make it difficult in the future to update your application.

1/5/2006 1:08 PM Eastern Standard Time  #    Disclaimer  |   | 

It is highly likely that in a certain amount of time of programming you will run into the term Object Relational Mapping. So what is Object Relational Mapping exactly? Object relational mapping is the technique of linking a relational database to a set of objects. There is no one to one relationship between object oriented programming and relational databases, this is called a impedance mismatch in the industry.

 

You see a relational database contains the normalized data structure of a particular entity or series of entities. For instance a “address object” contains information such as house number, street, city and state and zip code that is stored in an underlying database that persists the information for later retrieval. However according to normalization rules this data is stored in a non object oriented format. Object relational mapping attempts to solve the problem by mapping the entities in the relational database with those corresponding objects.

 

Fortunately this problem is well known and can be solved through many free and open source object relational mapping tools. Each program attempts to implement a variation on a particular theme. For instance there seems to be two schools of thought on the matter, a Entity (Chen/Yourdon) approach or a Domain (Fowler/Evans) model approach. Whether you subscribe to one model or the other will depend on which tool you prefer to use.

 

Since I am mostly interested in .Net oriented approaches I am only going to list those open source object relational mapping tools on this blog. This is not to say that the other languages do not have equally adequate tools in fact many of the .Net tools are based upon previous languages own implementations of the tool. Now keep in mind that some of these tools may be open source but not free.

 

Here is just a brief listing of some of the open source object relational mapping tools that I am aware of today.

 

Retina.Net

AtomsFramework

Gentile.Net

iBatis.Net

NHibernate

Neo

NPersist

OJB.Net

LLBGenPro

 

Hopefully you now have a better understanding of Object Relational Mapping and the why this is such a problem and the tools you can use to solve this problem. I know I have really only scratched the surface of the subject here but I do play on writing more about this subject as it is one that interests me.

1/5/2006 10:00 AM Eastern Standard Time  #    Disclaimer  |   | 
 Wednesday, January 04, 2006

Published by: Apress

Author: Eric White

 

Introduction:

 

It is stated in this book that this book is for developers who wish to enhance their programming skills in order to create custom controls. The primary language for this book is C#, this is most likely just a personal preference by the author of the book and it should not really adversely affect any other developer who writes code in other languages. Basically the techniques in this book can be applied by any Visual Basic .Net developer or even an Visual C++ .Net developer. The approach the author chose to take is to first give a brief introduction of what GDI+ actually is and then dive into the nuts and bolts of the underlying framework of GDI+ and then finally go into the architecture and development of Windows custom controls.

 

It is important to note that the source code for this book is available online at the APress website. You must download the code yourself if you want to see examples the coincide with each chapter of the book.

 

You can download the source code here:

 

Chapter 1: .Net Graphics Programming

This chapter provides a good introduction of .Net graphics programming. All the necessary topics are covered for even the most novice programmer. The highlight of this chapter is the overview of the namespaces of GDI+ programming which are listed in the table below.

 

Namespaces

Description

System.Drawing

This namespace is where all the basic graphics functionality. This includes the drawing surfaces, images, colors, brushes, pens and fonts.

System.Drawing.Drawing2D

This is where the raster and vector graphics functionality is located in the GDI+ namespace.

System.Drawing.Imaging

This is where the advanced imaging functionality is located which is an extension of the System.Drawing namespace.

System.Drawing.Printing

This is where the printing and print preview functionality of the framework resides.

System.Drawing.Text

This is where the advanced font functionality is located.

System.Drawing

This is where the advanced design time support of custom controls.

 

An overview of the basic of custom controls is also covered in this chapter quite well.

 

Chapter 2: Drawing Surfaces

This chapter covers what to consider when drawing to specific target environments. These target environments are a window on a screen (known as a form), a page (sent to a printer) and an image (such as a bitmap) since these all can be drawn to by pixels it is important to note the differences between these drawing surfaces simply because not doing so can affect your program in a very negative manner. I have personal experience debugging a C++ program that had its share of pagination issues and I have to note that many of those issues were most likely caused by the poor translation from one drawing surface to another.

 

The author does a fairly good job in explaining how to deal with each target environment. However as this is an early chapter some points are purposely left to other chapters to fill in. As there is a complete chapter printing it is wise to reason that the more in depth discussion of that drawing surface would be covered in more detail in that chapter.

 

Chapter 3: Pens and brushes

This chapter builds on the previous one in that it describes how to actually draw images on the screen using pens and brushes. Pretty much every aspect of the task of using pens and brushes is covered exhaustively in this chapter. Also, when covering this topic the author makes sure you understand how these methods are interacting with the screen, printer, etc to make absolutely sure you take all considerations into effect before setting down and using this namespace.

 

Chapter 4: Text and fonts

This chapter is perhaps the most drawn out text on fonts and text I have ever seen. Now this is not necessarily a bad thing as without text no information can be conveyed to the end user. Furthermore, the first GUI interface main attraction was the use of the fonts only seen in well published novels and magazines. Again every aspect of the namespaces that control how and where text is laid out on the screen or printer is covered very well in this chapter.

 

Chapter 5: Images

The use and manipulation of images is covered exhaustively in this chapter. However I would not use this chapter as a sole resource on the subject of image manipulation. Rather I would turn my eye to the open source projects that do the same thing but in an actual application. This would be something like the open source project Paint .Net. You can use this chapter to get a better understanding of what is going on in the underlying code in the project but since the examples are rudimentary and elemental at best it is far better to see this code in an end product such as Paint .Net.

 

Chapter 6: Graphics P