Computer Magic
Software Design Just For You
 
 

Sending email without all the hassle! Use the pickup directory.

May 26th, 2006

Ok, I just learned something new the other day. I have been using and administering IIS for years with or without the SMTP service running, but I never knew that you could send emails simply by placing them in the pickup directory. Yes, just copy a text file into the c:\inetpub\mailroot\pickup folder and the SMTP service will try and send it.

Why is that a big deal you ask? Ask those developers who have for years used packages like CDONTS. In some languages like PHP, the built in mail features are great and they just work. In ASP, the add-on libraries that you have to use leave a bit to be desired. Quite frankly, I like the idea of writing the whole email to a file and having it just head off into the blue.

How does this work you ask? I generally build up the email string first (easiest way is to send it to myself using outlook, then paste it into my scripts!), then write the whole thing to the directory when it is ready usinge fopen/fwrite. Chances are you will never actually see the file appear in your explorer view if the SMTP service is running as it will see the file and copy it to the queue right away. If it fails to send the email, it will dump the email to the badmail directory along with an error message in a seperate file (remove the boxes and you will see the error). If it doesn’t end up in badmail, it should be delivered shortly.

One thing to note is that we are working in a windows environment here. It is VITAL that you use the proper line feed characters (\r\n). Failure to do so (\n alone won’t cut it) will result in your email being rejected even if everything else is perfect. I kept getting an error code (0xC00402CE) for exactly this reason.

Here is an example of a simple email that is properly formatted.



Date: 27 Nov 2005 0852 GMT To: "Bob Smith" <bobs@smith.com> From: "Franky Rumple" <frankyr@rumple.com> Subject: Testing Email MIME-Version: 1.0 Content-Type: text/plain; Content-Transfer-Encoding: quoted-printable Hello, this is email!

That is a basic email. If you create a text file with that information (put in your email address on the “To” line) and copy it to the pickup folder, you should get it in your inbox shortly. If you don’t, one place to check is the IIS Manager under the SMTP Service area. You can define the domains that it will forward mail to. In my case, I just add *.com, *.org, etc… This tells the SMTP service it is ok to send emails to people at those domains. You do want to be careful here as you could turn yourself into a spam relay if your SMTP service is unprotected. Mine happens to be behind a firewall, so it can only be used by internal applications to send email.

Using this method, it isn’t to tough to add attachments and such. You will have to format the email to use the correct mime headers and possibly use Base64 encoding on your attached files. This isn’t too big a deal though. To get the correct format, I suggest using your regular email client (Outlook?) and sending yourself an email with the attachment. Once it arrives, view the message source. You can copy/paste this and use it as a template to generate your own emails. If your attachement will change, then cut out that part but leave all the MIME headers. Then, with your code, plug in the appropriate data when needed (use str_replace and put a place holder, or concatenate as you go, whatever is easier). Make sure your data encoding matches the MIME header “Transfer-Encoding”. If it is set to Base64, then your data needs to be encoded using Base64 encoding.

If you use scripts, make sure to use \r\n for line feeds instead of just \n. Also, notice that after the headers (MIME or main Email headers) that you need an extra \r\n to seperate the header from the data. This is just a clue that the header is done and the message or data is beginning.

Generating emails is much easier than processing them. You can spend a lot of time learning about all the different headers and such and how to create them by scratch. While learning is always great, if you just want to get an email out, create one using Outlook and send it to yourself and use that as a template. It can really save you some time.

Ray Pulsipher

Owner

Computer Magic And Software Design

Working with Dynamic Connection Strings in VB.NET 2005 WinForms Applications

May 23rd, 2006

When Microsoft released their latest edition of Visual Studio 2005, they got a lot of things right. The data binding is finally ready for use in real projects, click once is a wonderful feature, and the support for connecting and editing data sources is great. One real problem with all this automation is that when something goes wrong, it really goes wrong. Do you scrap the automated features that can save you so much time? Hopefully this article will mean you wont have to when it comes to dynamic connection strings.

In the past, we used to define our connection strings to our database either right in the code or in a config file. Because we defined it and manually assigned it to the connection object, we could modify the connection string as required. It was a simple task to put a new server address in at run time or a new file path to an access database. The problem was that it was time consuming to re-write the connection code each time we needed to use it. There were several solutions that could ease our pain, but we were still doing things by hand.

When Microsoft added support for partial classes, they allowed much of the plumbing code to be seperated from the logic code. Now, for a form, there are 3 files involved. Much of the connection code is placed in the designer file where it is tucked away nicely. The problem is that this designer file is refactored (rewritten) when certain changes are made so you can’t gaurentee that any changes you make to the designer file will be there later. Manipulating the connection string here puts us back into manual mode and has to be done for each form/connection. What we really want is to just have our connection work and take advantage of the time saving features of drag and drop and data binding.

With all these great tools, we have lost control of the connection string. To really take advantage of the time saving tools in visual studio, we setup a connection in our server explorer. If that is the exact connection properties that will be in use when the project is live, then there is no issue. You can view tables, views, stored procedures, etc.. right from the server explorer. You can drop tables onto your forms and it will automatically setup connections, data adaptors, data sets, navigation bars, etc.. It makes setting up a basic data form extremely simple and fast. When you use a database server such as MS SQL or MySQL, you probly wont notice this issue until you decide to run your app off of two different servers (one for development and one for production). If you use MS Acces for your database, then you are probly reading this because you already have the problem.

With MS Access, your connection string includes the path to your MDB file. Lets say for this example that the MDB file is in your project directory. You could use a full path(c:\projects\myproject\data.mdb) which would work fine while you are developing your application. What about when you send the app off for your friends or coworkers to use? The chances that your program will be in the exact same folder as on your computer can be slim and you don’t want to have to recompile your app each time some one runs it in a different directory (if you even knew what that directory was!).

The easy solution is to use a relative path. In this case, you could just specify the MDB file name without any path. This works great in the IDE when you are dragging and dropping things, but as soon as you push the play button, you compile and create either a debug or release version of your app. This app is then placed in the bin/debug or bin/release directory. Suddenly your MDB file is no longer in the current directory (it is two levels back in the project directory) and your app can’t find it.

Shucks, I will just add my MDB file to the project, then when it is built, it will copy the MDB file over to the bin/debug directory. This actually works, except that each time you build your MDB file will be copied over again meaning that any data you enter while the program is running will be over written (this actually had me confused for hours and I though changes werent sticking and I was trying to debug my save code). You can set the properties of the MDB file in the project to “Copy if newer” which will help, but if you make changes to the main MDB file, then it will copy over the on in the bin/debug folder.

It would be nice for the connection string to be smart enough to use the project folder as the main folder all the time. You can actually mess with this by having your builds reside in the project folder. This almost solves most of your problems. This solution clutters up your folder and while it might work for certain instances, it isn’t the best solution.

Now that we have address most of the issues you come across while developing and testing your software, lets talk about issues you face when you deploy it.

In my case, I had yet another problem. When deployed, the user could pick from more than one database. They had the option of browsing to an MDB file and choosing the current data to work with. How do you put in this new data path without writing custom code in every single form or location where you use a connection string without messing up the configuration while you are in the development environment?

First, go to “My Project” and go to the Settings tab. Click the View Code button on top. Add the event “Settings Loaded”.

This event fires after the settings have been loaded. When you setup connections in your server explorer, it adds connection strings to your settings area. These strings are specifically marked as a connection string. What we can do here is loop through our settings and find the connection strings. This happens early in the application and allows us to set the connection string before they are even utilized by the connection objects in the application. By changing them here, the rest of the application can just work without knowing that anything changed.

You could specifically change one connection string instead of looping, but I found that as I worked on my project that the IDE liked to add CString1, CString2, CString3, and so on. A new string (identical to the first) was added every time the project needed to reconnect to the database. Simply changing the connection string name or deleting it causes problems with data sets later on as the data sets specifically reference the connection strings by name. The easiest method for me was just to update all connection strings to point to the new location.

The advantage here is that the changes can be made in one location and you can put in the code to handle running in the IDE or deployed.

Here is the actual code:



Private Sub MySettings_SettingsLoaded(ByVal sender As Object, ByVal e As System.Configuration.SettingsLoadedEventArgs) Handles Me.SettingsLoaded ' Find the current file... If (Debugger.IsAttached) Then ' Don't mess with the path if we are running in the IDE ValidConnection = True Return End If ' Grab the last MDB file we opened and try to get it Dim fname As String fname = My.Settings.LastDBFile ' Try and load the file.. ' CheckDataFile checks to see if the file exists... ' UpdateCStrings modifies all the connection strings to use the new file name If (CheckDataFile(fname)) Then ' Good file.. lets use it... UpdateCStrings(fname) ValidConnection = True Return End If ' If the last db file cannot be found, start looking in the current directory, then start looking in parent directories ' Load the correct database directory Dim data_directory As String = "" data_directory = Windows.Forms.Application.StartupPath data_directory = data_directory.Replace("/", "") If (Right(data_directory, 1) <> "") Then data_directory += "" End If Dim p_dir As String p_dir = System.IO.Directory.GetParent(data_directory).Parent.Parent.FullName + "" ' Use this in case your MDB file isn't copied to your bin/debug folder when you push play ' Look for: dbfile, ..\..\dbfile Dim last_db_file As String = "" last_db_file = My.Settings.LastDBFile ' Check the current directory If (CheckDataFile(data_directory + last_db_file)) Then UpdateCStrings(data_directory + last_db_file) ValidConnection = True Return End If ' Check the parent directory (../../dbfile) If (CheckDataFile(p_dir + last_db_file)) Then UpdateCStrings(p_dir + last_db_file) ValidConnection = True Return End If ' Those others didn't work, lets try other common locations. ' Try to open from my documents... data_directory = My.Computer.FileSystem.SpecialDirectories.MyDocuments.TrimEnd("") + "" If (CheckDataFile(data_directory + last_db_file)) Then UpdateCStrings(p_dir + last_db_file) ValidConnection = True Return End If ' Couldn't open any db file ' Show some kind of error.... End Sub

The code is really long because it accounts for several different options. First, if we are in the debugger (IDE or playing from the IDE) it doesn’t do anything as the connection strings should work fine already from that location. Next, it tries the currently saved file path (we save the last used file path as a user setting). Next, it tries looking in the current directory, the parent directory (../../dbfile.mdb) to account for your application running in the bin/debug folder. Next it tries to load the db file from the MyDocuments folder.

You can adjust your code any way you like so that it works for you. The CheckDataFile function just uses the File.Exists method to see if the MDB file exists. In our case, if it does exist, it also tries to load it and check a version. That way we can update the MDB file if changes were made to the structure when it is loaded (eg: I add a new table to my MDB file while developing, so I can update the clients MDB file also when it is loaded). You can do whatever you want with the CheckDataFile function. It just takes the current path and checks things out, then returns a true or false based on its ability to find and load the file. I won’t list it here since it is mostly very specific to my project.

The next function that is important is UpdateCStrings. This takes the new file path and loops through all the connection string items in your settings updating them to point to the new path. I will list that here:



Public Sub UpdateCStrings(ByVal fname As String) Dim item As System.Configuration.SettingsProperty ' Loop through each property (each setting)... For Each item In My.Settings.Properties If (item.PropertyType Is GetType(String)) Then Dim keys As System.Collections.ICollection keys = item.Attributes.Keys Dim attr As System.Configuration.SpecialSettingAttribute Dim key As Object ' Each property has multiple attributes, we are looking for the connectionstring special attribute For Each key In keys If (item.Attributes.Item(key).GetType() Is GetType(System.Configuration.SpecialSettingAttribute)) Then attr = item.Attributes.Item(key) If (attr.SpecialSetting = Configuration.SpecialSetting.ConnectionString) Then Dim tmp As String ' Found a connection string... convert the connection string... tmp = ConvertConnectionString(fname, item.DefaultValue) ' Assign the new connection string back to the setting My.Settings.Item(item.Name) = tmp End If End If Next End If Next End Sub Public Function ConvertConnectionString(ByVal fname As String, Optional ByVal cstring As String = "") As String If (cstring = "") Then cstring = My.Settings.MyConnectionString End If If (fname <> "") Then Return cstring.Replace("|DataDirectory|\mydb.data", fname) End If Return cstring End Function

The first function does the looping and is responsible for identifying which settings are connection strings. Once it finds one, it sends the item to the ConvertConnectionString to change the path in the cstring. One thing that you may notices is that Visual Studio likes to use |DataDirectory| for your file path if the MDB file is in a specific locaiton. The mydata.mdb file is the name of the file I used during development. Thus, all connection strings should point there to start with. The easiest method is to simply replace that with the new path. Note that we call the ConvertConnectionString function using the DefalutValue rather than the current connection string as it could have already been modified and the |DataDirectory| value may no longer be present. You could use fancier parsing techniques, but I have found that the simple string replace method works great for me.

The hardest part by far is the looping through the properties to identify which settings are actually connection strings. There is little real documentation on this and I had to hack it out by hand. Hopefully this will save others a great deal of time. I know that on other projects, being able to drop this in will cut of many hours and allow me to still take full advantage of the built in drag and drop databinding features in Visual Studio .NET 2005.

In our app, we use the UpdateCStrings function later on. The user can browse for a new DB file at any time and the UpdateCStrings function can be called using the new supplied path. The settings event helps to make sure that the connection strings are all set as the application starts.

Ray Pulsipher

Owner

Computer Magic And Software Design

XML Demystified…

May 11th, 2006

I don’t know how many times I hear the question, “I should learn XML so my web pages can be standards compliant.” Huh? XML? Oh, you mean XHTML? Yeah, you should learn that.

There is a whole group of technologies involved when you start talking about XML. There are also so many products out there that advertise its usage. It has become cool to work with XML. In computer land, it is normal for an acronym or term to catch on and be used out of context by those who don’t know better, and even by those who should know better.

Case in point. Every one wants to be on the web, but most people think of the web as what you see in your browser. They don’t understand that the web is really a combination of all the interconnected computers and is protocol indipendant. It has gotten so that when you say, “let’s surf the web”, every one (including techs) assume you mean to open up a browser and use the HTTP protocol to download web pages. While HTTP traffic accounts for a significat part of the web, it is by no means the only traffic flowing through the web. Web traffic includes email, FTP, SNMP, File Sharing, Telnet, SSH, Instant Messengers, online TV/Movies or Radio stations, and the list goes on and on.

When referring to XML, there is the same type of misunderstanding taking place, even among those who should know better. We will try and break down the seperate components that we refer to as XML and show you the differences.

First, XML is a thing all by itself. It isn’t really that exciting. It actually has a number of weekneses, and is kind of wordy which increases your data size (some times significantly). It is a text based specification and requries encoding (base 64 encoding is popular) for binary data which can again increase data size (base 64 ads one third to the size), and it requires a nice XML library to really utilize it in your software (unless you want to rewrite the code to parse and manipulate XML yourself).

Why would you use it then? The main reason is that it allows interoperability in a generic manor. It does this specifically because many ports of the XML processing library have been done. You can use XML in just about any language by plugging in free libraries. This is an important concept. People have been using CSV files for years, but you don’t find much support from language companies for this format. Most languages already have an XML library ready to go or you can get one as an add-on.

One it’s weaknesses is also it’s strengths. It is wordy. If done right, it is often self describing. It makes it easy for developers to simply read your XML file and to find ways to integrage with it.

With this little bit of background, lets actually answer the question, “What is XML?”

XML is a generic way to store data in a self describing, orderly, hierarchal manor. More importantly, people started getting together and promoting a standard which every one else has done a good job of following. This standard is what makes it so people can write software that interacts in an easy and platform independant way. This in and of itself isn’t revolutionary. People have been writing software that interacts with other software for years (web servers and web browsers). The problem with other formats is that they were too specific in their features (why do you think we still use FTP when we have web pages?) or they were too difficult for other developers figure out what went where (try parsing an ms word document even with the complete file specifications). The amazing part is that the industry got together and agreed on something and actually started supporting and using it. Now you can have java web services supplying information to .NET driven applications.

XML itself is just a generic way to store data (store meaning transfer to other software or save as a file, or manipulate in any way you need). Below is a small sample.



<ROOT>
  <PERSON name="bob" age="84" height="5.0">
    <OPERATION date="5/5/05" type="heart transplant" />
  </PERSON>
  <PERSON name="joy" age="13" height="5.4">
    <OPERATION date="1/1/06" type="hip fracture" />
    <OPERATION date="1/3/06" type="mole removal" />
  </PERSON>
</ROOT>

The example shows how you can stack related information on people (or patients in this case). Each person gets his/her own tag. Notice that the tag opens “PERSON” and closes “/PERSON”. EVERY TAG has to open and close. This is a requirement in XML. NO EXCEPTIONS! Really. None.. Not even the OPERATION tag… Notice at the end, it has a />. The / character at the end is a short cut to close the tag. It is important to note that you can’t use the short and long hand versions at the same time.

You would use the long hand version when you have more data to nest in your current item (as one or more operations that belong to a particular person). If the current item has no child items, then you can use the short hand version (or you could use the long hand version).

Another thing about XML is it HAS to have a single ROOT element. The ROOT element can be called anything you want, but there has to be one. Why? I don’t know, look it up and get back to me. Guess it just likes a single starting point in its hierarchy.

Now that you have seen a basic XML file, you will notice that it is really just a data dump that has been formatted in a generic way. Any XML parser can now read that in and you can grab values at each node. It looks very much like HTML, but it IS NOT! There are a few rules that come with XML, and one is that all XML is well formed. This is an important concept and relates to the requirement above that each tag is closed properly and in the correct order. This is what we call well formed XML code.

When you hear about XHTML, one of the main differences between HTML and XHTML is that the XHTML be well formed also. It was common pracitce to put some tags in without a closing tag (P, BR, IMG, etc..). In XHTML, you HAVE to close these tags. You can use the short or long hand method where appropriate. There are many other enhancements that came along at the same time as the XHTML spec came out, and those really have nothing to do with XML itself. Ehancements to the DOM object model made working with page and content of that page more uniform, but most of the actual XML related features most HTML designers don’t even use.

Now XML itself is just data formatted in a generic way. There are some other tools in available that can take XML and do stuff with it. XSL is basically a style sheet for XML files. Looking at an XML file itself is boring and technical. You wouldn’t want to display results on your website using just XML. You would wrap it with rendering instructions in an XSL file that would apply styles and HTML tags around the XML data and make it into a presentable page. This doesn’t save you from doing HTML, but it can save you from having to write some programming code. XSL can sort, select individual or multiple records and format the display of the data, all with no programming. Will it take the place of languages like PHP? No way. The XML still needs to be generated some how. It could be used in conjunction with current technologies though.

XML is used in many different places, for data storage, for interprocess communications, for impressing your friends, but where is XSL used? There are actually a suite of technologies that go along with XSL including XPath (the part that allows you to query and sort XML files in an SQL like syntax). Generally when you move away from the web, you aren’t worried about the display of the XML file as much as you are worried about having the software on the other end be able to understand what you have sent. Here is an example where we used XML to make a project communicate with the server.

One client of mine has a server where data is stored and entered on a daily basis. This data is manipulated through a web page interface. This works great. At times, they need to go on the road and gather results in places where internet access is limited. We wrote an applicaiton that allows you to download the needed information from the server and take it with you. This information comes down in the form of an XML document generated by a PHP file. The PHP file adds the neede XML tags around the data and includes extra attributes that affect the display properties.

The application itself opens the XML file using the microsoft XML library which parses the XML file for us. We can then ask for the nodes we want andchange them as information is manipulated. The application also uses the extra information in the attributes that can tell it which menu to show when they right click a record, or to hide records in the GUI, or a number of other features. The nice thing about the XML output is that it is generic and extensible which allows us to ad attributes and elements as we go without it breaking everything. We don’t have to worry as much about file version (ever try and open up a word 2003 document in word 97?). As updates are released for the application, we can modify the base XML file without the program blowing up.

After hearing all this great stuff about XML, it is kind of an anti-climax to hear what XML really is. It is just a generic data container. The fact that every one in the world seems to have adopted it is what makes it so great. I can write a service that uses XML to communicate and it is easy for others to write software that can interact with my software without worriyg about languge or operating system

One area where XML is getting a lot of use is in the Ajax libraries. There is plenty of descriptions of Ajax and what it does (including on this website), but not all of them explain how XML fits in. In our previous example, we use XML to transfer database information to the applicaiton in a generic way that can be parsed and understood. Ajax does the same thing. When you add Ajax to a website, you make it behave more like an application. In doing so, you still need to make requests to the web server. These requests are sent via HTTP, but the requests still need to be understood by both parties. HTTP is like the telephone in this case and XML is like the conversation. The XML that comes back from the server can be interperated in the background and used to populate information on the web page in realtime. The XML is again, just a generic way to do this as often times the XML returned is customized for the particular application and instance. They really could have used any file format (CSV, etc..) but XML was chosen because of its generic intreface and for JavaScripts built in ability to parse and work with XML.

If you want all the other bells and whistles associated with XML, you should look further into XSL to see how easy it is to manipulate XML without being a programmer. We are actually using XSL to format a data driven printout. If I ever get done with this articile, I am off to finish it.

In any attempt to get people to adopt your product, you have to remove the barriers to entry so that it is as easy as possible. XML libraries are available for all langauges and platforms and most often now included in development tools. Browsers have built in support for XML. People have been using XML forever now and haven’t even realized it. They have done a good job of defining XML (at least for the programmers) and making it easy to use. The marketing has also been particularly good at making people aware. Even though many people don’t totally understand what it is, they know they want it. I have used it in several projects to date and have found that it can save me significant time because the libraries are so avialable and they do what we would have to do manually with our own file formats. This alone saves me enough time to adopt XML in my projects.

Ray Pulsipher

Owner

Computer Magic And Software Design

Finding the current line and column in a multi-line text box

April 30th, 2006

There are times where you want to drop a multi-line text box into your form to allow your user to edit large ammounts of text. In my own particular case, I am writing a GUI to let programmers make changes in real time to a game engine using Python scripts. It works pretty good, but one of the main problems we have with it is that when there is an error in the Python scripts, it identifies the line where the error occured by its number. This can make it difficult to scroll through the text box manually counting the lines, especially as the script gets longer.

Our solution was to simply put a label on the form that would show the current position of the cursor. As far as I could find, there is no event that fires when the cursor moves. This isn’t a real problem though as you can simply catch two different events and cover most situations where the cursor might change postion. We caught the KeyDown and the MouseDown events. Every key (including arrow keys) fires the KeyDown event. We tried the KeyPress event at first and this only worked for valid printable keys since this event has a different purpose. The MouseDown event allows you to update the cursor position when a user click a specific spot in the text box.

In both events, you put the same code. Just one line will do it. This function is responsible for finding the current line and column from the supplied text box and setting the text property of the supplied label control to show the current line and postion.



ShowCaretPos(lblPos, txtPythonCode)

The ShowCaretPos function is responsible for setting the label text. The other two functions which we will show later are responsible for actually calculating the position. The ShowCaretPos function just uses these to get the values and display them.



Public Sub ShowCaretPos(ByVal lbl As Label, ByVal txt As TextBox)
   Dim l As Long
   l = GetCurrLine(txt)
   Dim c As Long
   c = GetCurrColumn(txt)
   lbl.Text = "ln " + l.ToString() + " col " + c.ToString()
End Sub

ShowCaretPos itself really isn’t that special. Modify the display of the lines and columns to suit your tastes. The real work is done in GetCurrLine and GetCurrColumn. These functions manually figure out the current line and column of the cursor. A common way to find this information is to use the SendMessage function in the Win32 API. The problem with that method is that you get the exact line you are on in the text box and not the line in the file. This means that if you have word wrap turned on and you have 12 lines that each wrap to a second line, when your cursor is at the end it will show line 24 rather than line 12. In our case we are trying to jump to a line where the error occured. If the line number is calculated based on the text box rather than the file, it is basically useless.

This code actually starts with the current position and counts backwards until it quits finding line feeds (chr(10)). It is a little more processor intensive, but for our purposes it is more accurate and that is what counts. Also, our files don’t get too big (100’s of lines, not 1000’s or more) so the delay isn’t noticable. On a very large file, I could see this function running away with the CPU.



Public Function GetCurrLine(ByVal txt As TextBox) As Int32 Dim found As Int32 = -1 Dim linenum As Int32 = 1 Dim pos As Int32 pos = txt.SelectionStart If (pos = 0) Then Return 1 End If Do Until found = 0 found = InStrRev(txt.Text, Chr(10), pos, CompareMethod.Binary) If (found = 0) Then Exit Do linenum += 1 pos = found - 1 Loop Return linenum End Function

As mentioned before, it takes the text, looks at the current caret position (selectionstart) and rewinds counting the actual line feeds. Pretty simple.



Public Function GetCurrColumn(ByVal txt As TextBox) As Int32 Dim pos As Int32 Dim found As Int32 = -1 Dim cnt As Int32 = 0 pos = txt.SelectionStart If (pos = 0) Then Return 1 End If found = InStrRev(txt.Text, Chr(10), pos, CompareMethod.Binary) If (found = 0) Then ' We are on the line... cnt = txt.SelectionStart + 1 Else cnt = txt.SelectionStart - found + 1 End If Return cnt End Function

GetCurrColumn follows the same idea as GetCurrLine. It starts from the current position, but it only rewindws to the immediatly previous line feed and counts characters from there to determine the current column. One thing to note is that a tab character is considered one character according to this function. You could easily use the replace function to substitute tab characters for X number of spaces.

This solution is specifically designed for multi-line text boxes. It should work in any VB.NET and in VB 4,5,6 with a little modification (change int32 to long). It would probly also work on the Rich Text Box control, but that one already has current line properties and such. Eventually I think I will change my text boxes out for RTF boxes and add syntax highlighting, but since I have little time for extras on low priority projects, this will have to wait. Until then, this should save some time spent manually counting lines to find the error.

Ray Pulsipher

Owner

Computer Magic And Software Design

AJAX for .NET – Don’t use Prototype…

April 26th, 2006

I have been using the Prototype AJAX library for a little while now to add AJAX capabilities to my PHP web applications. It works great! It works so great in fact that I tried to use it in an ASP.NET2005 project recently. After figuring out that my CSS and Theme support could thank the Prototype library for its troubles (they didn’t work at all) I went looking for a new AJAX library for .NET.

Was Prototype a bad library? No, it was and is a great library. The automated nature of the .NET framwork and the way it mangles the names of controls and auto generates script events creates a conflict between the Prototype library and .NET. If you are planning on using PHP or other web languages, Prototype is a great choice.

I read some reviews and dug around a little bit and I came up with MagicAjax as the favorite for a .NET Ajax implentation. Let me tell you, once you get it included/referenced into your project properly, it is an absolute joy to use! It is SOOO easy! It automatically adds AJAX features to existing controls! It gives you Postback withouth the Postback. All you really have to do is add an Ajax Panel control and place any controls you want Ajax Enabled into that panel and presto! It’s done! The click or change event will now happen via the Ajax wrapper.

The secret is that the MagicAjax Panel control will modify its child controls when they are rendered so that they fire the Ajax event rather than the Post Back event. Like I said, this happens automatically for any controls placed inside the Ajax Panel. You can override this functionality and turn Ajax support off for particular controls. You can also use multiple panels to create groups of controls. This is a great feature as it allows you to send only the needed information to the server.

Here is an example. Ever notice on car sites that you can search by make and model? Well, model should change depending on which make is selected. There are many ways to do this dynamically (I wrote complex javascript arrays in the past). With Ajax, you can populate that list from the server in real time from a database list. The Ajax Panel could wrap just these two controls and leave the rest of the page alone. This can greatly reduce the ammount of information that has to be sent and returned from the server.

Check out MagicAjax at http://www.magicajax.net/. It is a great libaray and makes adding Ajax capabilties almost transparent. Note that it is easier to setup in ASP.NET 2.0 than in version 1.1, but once it is setup, it is just as easy to use.

Ray Pulsipher

Owner

Computer Magic And Software Design


Home | My Blog | Products | Edumed | About Us | Portfolio | Services | Location | Contact Us | Embedded Python | College Courses | Quick Scan | Web Spy | EZ Auction | Web Hosting
This page has been viewed 832679 times.

Copyright © 2005 Computer Magic And Software Design
(360) 417-6844
computermagic@hotmail.com
computer magic