.net.devcity.weekly ---
If you are unable to see the message, visit http://www.devcity.net/newsletter/archive/devcity/devcity20050815.htm

Advertisement

AdvertisementAdvertisement

The newsletter is compiled by DevCity.NET NewsMasters Ged Mead and Mike McIntyre

Advertisement

Table Of Content:

Advertisement
Diary of a .NET Newbie: Making The Right Move

by Ged Mead

Have you ever had one of those "Eureka!" moments while you were programming?
Of course you have!
Otherwise I'm sure you would have given up programming long ago and got yourself a more rewarding, satisfying and fulfilling job.

Public Toilet attendant, perhaps. Or Keeper of the Royal Underpants. Or Duty Boil Squeezer at County General .
But I digress.....

I was fiddling about trying to knock out a very simple Windows Form on which the user could drag controls at run time and place any of them on top of a large PictureBox.

Now, I know you're probably sat there thinking that that's a pretty easy call.
And I agree.
Mouse Down on the label, drag to chosen new location, release mouse, job done.

Change the values of the Left and Top Properties of the control you want to move and it will move there. Use the relative position of the mouse from the mouse's start point to the point where the user releases the mouse to calculate how far to move .

Doesn't need an MSc in Computing to work that one out. But, strangely, the results I was getting weren't really very satisfactory. And that's putting it kindly.
Actually, it was a total shambles.

If I put this code in the MouseMove event:

Label.Left = e.X
Label.Top = e.Y

I found myself chasing the label round the form until I finally trapped it in the corner. Then when I tried to drag it away, it began to create very shaky, flaky clones of itself.

My thinking at this point was that if I moved the top left corner of the label control to the location of the cursor then any movement of the mouse cursor would be reflected by a corresponding movement of the label. But, nope, that definitely didn't work.

Hmmmm, Plan B then. Swiftly followed by Plans, C, D and E. Most of them created variations of the mysterious "Case of the Disappearing Label"; apparently one of the very few cases that Perry Mason failed to crack.

OK, the Eureka moment. Actually "moments", plural. Searching around for code samples that actually worked (as opposed to my rather sad demos of how not to do it) I came to realise several things.

The first key thing I hadn't understood was that e.X and e.Y were both relative to the control (That is, the Labels and small PictureBox controls I wanted to move). I really don't know why, but for some reason I was under the impression that those X and Y values were related to the Form.
No wonder the attempts had all failed.

Secondly, I realised that it was no good just moving the control whenever the MouseMove event of the control was fired. The control would move even if the cursor was being passed over it with no button being held down. I only wanted the label to move if the Mouse had first been pressed down on the control. So the addition of a Boolean variable to keep track of this was the next step:

Dim Dragging As Boolean

And when the mouse is pressed down on one of the controls that we want to move, the Boolean flag is set to True.

That done, in the MouseMove event we can test to see if the user wants us to move the control:

If Dragging Then  

and if it is, we go ahead and move it. To do this, I needed to track where the user was dragging the mouse to and use that movement to move the control. Crucially, I also had to make proper use of that offset value that we had taken a note of earlier, i.e. when the user first clicked on the control. This would make the cursor stay in the same relative position on the control while the control was being moved, but also that the control would now move as the mouse cursor moved.

Having finally got all that clear in my head, it was relatively easy to put together a set of procedures which could handle all of the movable controls - namely lblAccept,, lblReject and the PictureBox, PBSmall :-

Dim cursorX, CursorY As Integer
Dim Dragging As Boolean

    Private Sub Control_MouseDown(ByVal sender As System.Object, _
      ByVal e As System.Windows.Forms.MouseEventArgs) _
      Handles lblAccept.MouseDown, lblReject.MouseDown, PBSmall.MouseDown
        '  Set the flag
        Dragging = True
        '  Note positions of cursor when pressed
        cursorX = e.X
        CursorY = e.Y
    End Sub

    Private Sub Control_MouseUp(ByVal sender As System.Object, _
      ByVal e As System.Windows.Forms.MouseEventArgs) _
      Handles lblAccept.MouseUp, lblReject.MouseUp, PBSmall.MouseUp
        '  Reset the flag
        Dragging = False
    End Sub

    Private Sub Control_MouseMove(ByVal sender As System.Object, _
      ByVal e As System.Windows.Forms.MouseEventArgs) _
      Handles lblAccept.MouseMove, lblReject.MouseMove, PBSmall.MouseMove
        If Dragging Then
            Dim ctrl As Control = CType(sender, Control)
            '  Move the control according to mouse movement
            ctrl.Left = (ctrl.Left + e.X) - cursorX
            ctrl.Top = (ctrl.Top + e.Y) - CursorY
            '  Ensure moved control stays on top of anything it is 
            '  dragged on to
            ctrl.BringToFront()
        End If
    End Sub

And then it was time for my bath... On reflection, maybe I should have mulled the problem over in the bath first and saved a lot of time and quite a bit of aggravation. Well, it worked for Archimedes!

Programming, huh? Sometimes it's all Greek to me.

- Junior (Ged Mead aka XTab, xtab@vbcity.com)

AfterNote: Having had reason to post up the code in answer to a question while this article was going to print, I can also point you to another approach suggested by Mark Dryden. You can read the Topic here.

Diary Follow-Up: Double Quotes

by Ged Mead

Following my Diary item in the last issue, two newsletter readers - Tinco Andringa and Steve Gravitz - took the time to mail me with a suggestion to ease the problem of those pesky single and double quote combos.

Both of them reminded me that the String.Format method is available in these situations.

So we can apply this method to the examples in that DataView Filtering example in the article:

DataView.Rowfilter = [string].Format("LastName Like " & _
  "'{0}%'",CStr(lstLetters.SelectedItem))

and

dvAddresses.RowFilter = String.Format("{0} Like '%{1}%'", _
  ColToCheck, txtSearchPhrase.Text)

Although it doesn't entirely overcome the fiddly syntax needed for the task, it certainly does compartmentalise the code and so makes it easier to decipher.

... and talking of making spaghetti code easier to decipher, Steve also showed me an example where a very unwieldy SQL statement could be tamed with the help of the String Format method. Notice how in this example, the proliferation of single, double and no quotes are neatly handled.

Sq.AppendFormat("{0} = dbo.{1}('{2}', {3}, '{4}', '{5}'), {6}", _
                "WEBHITS", _
                "dta_TotalsForCell", _
                m_CellMatrix_ID, _
                "Cell_ID", _
                "RESPONSES_WEBHITS", _
                "@@LAST_RESPONSE_DATE@@", _
                vbCrLf)

Thanks to Tinco and Steve for bringing out these suggestions.

- Junior (Ged Mead aka XTab, xtab@vbcity.com)

by Mike McIntyre

Part 1 of 3

This article discusses the ASP.NET 'Session ID Cookie', 'State Cookie', and 'Cookieless Session' state management options which are part of the bigger picture of caching mechanisms in ASP.NET. The diagram below expresses the context of this article.

.NET Framework
   ASP.NET
      Caching
         Session State
            Session ID Cookie
            State Cookie
            Cookieless Session

Session ID Cookies, State Cookies, and Cookieless Session are important caching mechanisms. Choosing which state management option to use in an ASP.NET web application, either cookies or cookieless session, impacts application design, security, performance, scalability, user experience, accessibility, code review, and deployment.

Caching

ASP.NET state caching is a key technology for optimizing an application's security, performance, scalability, and availability. State ID Cookie, State Cookie, and Cookieless Session are important components of the ASP.NET state caching technology.

State

State refers to data, and the status or condition of that data, being used within a system at a certain point in time. That data may be permanently stored in a database, may be held in memory for a short time while a user executes a certain function, may be cached in memory, cached in a SQL database, cached in a session service, or cached to a client computers hard drive.

Session State

ASP.NET session state provides a way to persist a piece of information about a client for the duration of time the user interacts with an ASP.NET web forms application.

By default, session state is maintained in memory in the same process and AppDomain as an ASP.NET web application.

Session state is accessible through the Session property of both the ASP.NET Page and HttpContext classes. When a request comes in to an application, the Session properties of the Page and HttpContext class used to service that request are initialized to the current instance of HttpSessionState that is associated with that particular client.

Session state for specific client is assigned a unique session ID.

Associating Session State Client Requests

To associate session state stored on a host with a client request, it is necessary to identify an incoming request as having been issued by a given client.

A session's ID is used to associate a client's request with a client's session state on the server.

The first time a client connects to an ASP.NET site an ASP.NET Session object is instantiated to hold the client's session data.

ASP.NET generates an encrypted alphanumeric session ID, assigns it to the Session object, and passes the session ID to the client in the response. Session ID can be passed to the client in a cookie or the mangled URL, as explained later in this article.

In subsequent requests the client passes the session ID back to the server.

When the server receives a request that includes a session ID it associates an ASP.NET session object with the client's request. It processes the page and then returns a response that includes the session ID back to the client. This back and forth passing of the session ID in requests and responses goes on until the session is terminated.

IMPORTANT: An ASP.NET web forms application must be configured to use cookies OR cookieless session to associate session state with client requests. It is not possible to specify that an application should use cookies if the client supports cookies and cookieless session if the client does not support cookies.

Session ID Cookie

A Session ID Cookie is the default mechanism for associating a client's session state on the host across multiple requests made by the client. With this mechanism, a session ID cookie is created by the host and stored in a client's web browser memory. A session ID cookie is erased when the client terminates the session.

Clients who have disabled cookies in their browser CAN NOT use an ASP.NET application that uses a session ID cookie.

Some browsers DO NOT support cookies.

State Cookie

A State Cookie is a mechanism for caching state on a client's computer, either in browser memory or on the client computer's hard drive.

With state cookies, state other than session ID can be stored in cookie(s) in the client browser's memory or on the client's hard drive.

Transient State Cookie

A state cookie containing state other than session ID may be stored temporarily in a client's web browser memory. A state cookie stored in web browser memory is transient. It is erased when the client closes the web browser to terminate a session.

If the expiration date property of a cookie is not set, a cookie will be transient.

Client's who have disabled cookies in their browser CAN NOT use an ASP.NET application that uses transient state cookies.

Persistent State Cookie

A cookie containing state other than session ID may be stored permanently or for a period of time on a client's hard drive. A cookie stored on a client computer's hard drive is persistent. It is not erased when the client closes the web browser to terminate a session. A persistent cookie is stored on a client's hard drive until it expires OR until the user deletes the cookie.

If the expiration date property of a cookie is set, a cookie will be persisted on the client's hard drive.

Clients who have disabled cookies in their browser CAN NOT use an ASP.NET application that uses persistent state cookies.


Next Installment: Cookieless Sessions

by Fadzai Chamba

I was reminded of a rather curious issue with floating point numbers last night that I think most new programmers are not familiar with. You would assume that the reason we would use floating point numbers is for greater precision. They have an accuracy that integer types cannot handle. And here is where the point is missed; surprisingly, if you are not careful, you could be serving users with very inaccurate figures.

The floating Types

.NET has given us three floating point types to use and these are Single, Double and Decimal. Single gives us a 32-bit single precision floating point number, while Double is a 64-bit double precision number.

Values that are considered valid for a Single number range from -3.4028235E+38 to -1.401298E-45 for negative numbers and from 1.401298E-45 to 3.4028235E+38 for positive numbers. This is very precise. Valid values for a Double range from -1.79769313486231570E+308 to -4.94065645841246544E-324 for negative values and from 4.94065645841246544E-324 to 1.79769313486231570E+308 for positive values. This is very, very precise; indeed more than the average developer will need

The issues

One issue that might come as a shock to the novice developer is that the precision afforded by these types can cause inaccuracy problems. To illustrate my point, we are going to try to add 0.001 to a Single a thousand times. Of course we know that the result is 1, but stay with me for a moment. Run this code in a new Console application and see what happens.

Dim sng As Single = 0, int As Long
'string builder for report...
Dim sb As New System.Text.StringBuilder
'go through the list a thousand times adding .001
For int = 1 To 1000
    sng += CSng(0.001)
Next
sb.Append("The value of 'sng' is: " & sng.ToString())
Console.WriteLine(sb.ToString())

As you will find, the result is 0.9999907. As I did, you may want to stop using Single for any mission-critical floating

I'll take a Double

Let us now run this code using a Double also and see what happens.

Dim sng As Single = 0, dbl As Double = 0, int As Long
Dim sb As New System.Text.StringBuilder
For int = 1 To 1000
    sng += CSng(0.001)
    dbl += 0.001
Next

sb.Append("The value of 'sng' is: " & sng.ToString())
sb.Append("\nThe value of 'dbl' is: " & dbl.ToString())

Console.WriteLine(sb.ToString().Replace("\n", Environment.NewLine))

As we have seen, Single is still inaccurate but Double gives us the value 1 as we expected. However, we should not perhaps be satisfied with one single successful experiment. Instead of going through 1000 times, go through the loop 10,000 times adding 0.0001 in place of 0.001. After running this code you will observe that both cases have some inaccuracies.

Some people might think that it is OK, we can always round off, and the values are close enough to the correct answers. But some users may not to round off those Double and Single precision numbers. It is also worth pointing out that Single has missed the mark by a greater magnitude of error.

Why this happens

Have a look at what the Microsoft Office XP Developer documentation has to say about floating point numbers:

The Single and Double data types are very precise - that is, they make it possible for you to specify extremely small or large numbers. However, these data types are not very accurate because they use floating-point mathematics. Floating-point mathematics has an inherent limitation in that it uses binary digits to represent decimals. Not all the numbers within the range available to the Single or Double data type can be represented exactly in binary form, so they are rounded. Also, some numbers cannot be represented exactly with any finite number of digits - pi, for example, or the decimal resulting from 1/3.

Because of these limitations to floating-point mathematics, you might encounter rounding errors when you perform operations on floating-point numbers. Compared to the size of the value you are working with, the rounding error will be very small. If you do not require absolute accuracy and can afford relatively small rounding errors, the floating-point data types are ideal for representing very small or very large values. On the other hand, if your values must be accurate - for example, if you are working with money values - you should consider one of the scaled integer data types.

What should I use then?

This is not really bad news if you can afford to have small rounding errors. However, if you want to have full accuracy you will have to leave Single and Double alone. The best choice is to use the Decimal type which is a fixed point data type.

Don't take my word for it; let us run the same litmus test on Decimal that we ran on the others.

Dim sng As Single = 0, dbl As Double = 0, dcm As Decimal = 0, int As Long
Dim sb As New System.Text.StringBuilder
For int = 1 To 10000000
sng += CSng(0.0000001)
      dbl += 0.0000001
      dcm += CDec(0.0000001)
Next

sb.Append("The value of 'sng' is: " & sng.ToString())
sb.Append("\nThe value of 'dbl' is: " & dbl.ToString())
sb.Append("\nThe value of 'dcm' is: " & dcm.ToString())

Console.WriteLine(sb.ToString().Replace("\n", Environment.NewLine))

The results are not so shocking in the wake of what we discovered about the other types.

  • The value of 'sng' is: 1.064767
  • The value of 'dbl' is: 0.99999999975017
  • The value of 'dcm' is: 1.0000000

The Decimal data type

Decimal variables are stored as signed 128-bit (16-byte) integers scaled by a variable power of 10. The scaling factor specifies the number of digits to the right of the decimal point; it ranges from 0 through 28. With a scale of 0 (no decimal places), the largest possible value is +/-79,228,162,514,264,337,593,543,950,335. With 28 decimal places, the largest value is +/-7.9228162514264337593543950335, and the smallest nonzero value is +/-0.0000000000000000000000000001 (+/-1E-28).

The bottom line

The text in the 'Why This Happens' section refers to "one of the scaled integer data types". This was referring to the Currency and Decimal types in Classic VB. However, .NET doesn't support the Currency type, so in our case this refers to Decimal. This gives you the best guarantee of accuracy.

The bottom line is that if you are writing an application for automatic aircraft control, space ship guidance, or a world domination program, you will need much more accuracy than that offered by the Single and Double types and in .NET you will have to use the Decimal data type.

Articles: Recent Articles

MultiThreading in .NET

VBCity Leader John Spano has written a very comprehensive and detailed article on this important topic.
As he explains in his introduction:

"Multithreading, a very powerful technique, is essential for modern software development. Software users expect to work with a very responsive program that they don’t have to wait on, which is a very reasonable demand with the processor speeds that are currently available.Enter multithreading. Multithreading is the concept of having several different paths of code running at the same time."

To read the full article, click here.

http://www.devcity.net

Design Guidelines Book and T-SQL Coding Standards by Serge Baranovsky

Play an embedded WAV via a stream by Mark Dryden

Logo & Web site design - going with the professional! by Serge Baranovsky

PDC05 is filling up quickly by Serge Baranovsky

Using the ClipRectangle with GDI by Mark Dryden

Invisible Underscores by Ged Mead

New Windows Mobile phone devices by Serge Baranovsky

Where will you be sitting for the PDC Keynotes? by Serge Baranovsky

Business for Geeks session notes by Serge Baranovsky

Multiple Forms - Revisiting the StartUp Form Problem by Ged Mead

Failing To Succeed by Ged Mead

vbCity Postcard Wall Update by Serge Baranovsky

TabPageCollection (And Collection ) Woes by Shandy

CodeIt.Once For VS 2005 Beta Now Available! by Shandy

Axosoft OnTime 2005 For VS.NET Beta 2 Has Been Released by Shandy

SQL Delta by Shandy

JetBrains Omea Reader v2 Has Been Released by Shandy

VB.NET Managed DirectX Example (Draw an Image) by Mark Dryden

CodeIt.Once for VS 2005 Beta 2 by Serge Baranovsky

Registered for PDC05 by Serge Baranovsky

Mapping ADO And SQL Server Data Types by Shandy

Picture viewer by Robert Verpalen

CodeSMART 2005 for VS.NET FixPack 4 Released by Shandy

Free Oracle Developer Tools for Visual Studio .NET by Shandy

Removing Duplicate Words From A String by Shandy

Combine - A Complement Function To Split by Shandy

Updating File Creation/Last Modified/Last Access Dates Using VB.Classic by Shandy

Converting VB.Classic Code Into HTML Code by Shandy

Latest DevCity.NET newsletter is available online by Serge Baranovsky

MIT Weblog Survey by Serge Baranovsky

http://blogs.vbcity.com/
Advertisement

by Newsletter Staff

Thanks for voting for vbCity.com!

Vote for vbCity!

Support vbCity in the .NET Developer's Journal 2004 Readers' Choice Awards Voting Ballot.

We've worked hard to make vbCity and DevCity.NET the best VB and .NET Community on the Net. Show your support by casting your vote in the .NET Developer's Journal Readers Choice Awards.

Click here to cast your vote for vbCity in the "Best .NET Web Sites" Section.

Thank you!
DevCity.NET Team

http://dndj.sys-con.com/general/readerschoice.htm
Advertisement

We encourage you to pass this issue of
.net.devcity.weekly on to anyone you know with an interest in .NET technology and News You Can Compile

Manage Your Subscription Here.

You are currently subscribed as '*EMAIL*' to .net.devcity.weekly.

Click here to unsubscribe.

Thanks for reading!

Contact:
vbCity.com, LLC
4957 Lakemont Blvd SE C4 #331
Bellevue, WA 98006


DevCity.NET is hosted by FullControl.NET

Copyright vbCity.com, LLC 2003. All Rights Reserved.