July 12, 2008
@ 10:34 AM

I mentioned Dependency Injection / Inversion of Control (DI/IoC) recently and I really didn't explain what it is, why you might want to use this particular pattern, and why on earth you'd need a framework for it. It's a fancy name for a fairly simple concept. Instead of creating objects inside of your classes, you let the calling code "inject" the necessary instances into your code. It's probably easiest to see this in some code. I'm going to show both C# and VFP code, since I don't want you to get the idea that this is a .NET-only type thing.
 

   1 public class SampleDependency

   2 {

   3    public string SayHello()

   4    {

   5       return "Hello";

   6    }

   7 }

   8 

   9 public class Sample

   10 {

   11    protected SampleDependency m_depend;

   12 

   13    public SampleDependency Depend

   14    {

   15       set { this.m_depend = value; }

   16    }

   17 

   18    public Sample(SampleDependency depend)

   19    {

   20       m_depend = depend;

   21    }

   22 }

 

      Sample sample = new Sample(new SampleDependency());

 

VFP Version
DEFINE CLASS SampleDependency AS Session 
   FUNCTION SayHello() 
      RETURN "Hello" 
   ENDFUNC 
ENDDEFINE 

DEFINE CLASS Sample AS Session 
   oDepend = NULL 
   FUNCTION Init(toDepend) 
      This.oDepend = toDepend 
   ENDFUNC 
ENDDEFINE 

loSample = CREATEOBJECT("Sample", CREATEOBJECT("SampleDependency"))
 

Notice that in both cases, we are passing in the instance we want the class to use instead of letting the class create the instance itself. That's all DI/IoC is. Honest, that's it. This is DI via a constructor (you can also do it via a property setting instead; notice in the sample C# code I created a write-only property which could hold the reference).

So the next obvious question is, why? What's wrong with just creating the object inside of the class?

One thing DI gives you is the ability to easily swap in different objects. In the C# example, we probably would change the parameter from a specific type to an interface. Now any class which implements that interface can be injected into this class. In VFP, since it's not strongly typed, you can just pass in whatever instance you'd like (it's up to you to make sure it doesn't blow up at runtime by accessing some method or property which isn't on the passed in object). My initial thought after seeing this was, well, can't I just use an abstract factory pattern instead? In an abstract factory you delegate object creation to a "object factory" - usually passing in a name or calling a method which returns the actual instance you'd like to use. This sounds like almost the same thing.

An abstract factory does let you do that, but it doesn't let you easily do something the DI/IoC pattern does: test your objects. Let's suppose you want to write a test for a class which uses another class to send out an e-mail. You aren't really trying to test sending an e-mail - that's just one of the things the class you're testing happens to do during some process. In fact, you really don't want to send out an e-mail; we don't want to spam our users. If you happen to use the abstract factory pattern, you would need to modify it to create your dummy/stub/mock object for sending an e-mail (in VFP that's most likely by editing a record in a table, but the idea is the same), then test the object in question. If you used the DI/IoC pattern the only thing you need to do is pass in your dummy/stub/mock object. No other modifications are necessary.

OK, so this all looks simple enough. Why would you need a framework for the above?! One of the biggest reasons - less typing. You'll notice that in order to use any of these objects you may have to pass in a bunch of other dependency objects (which themselves may have other dependencies). For a complex set of objects that could really suck. A DI framework does that for you along with the benefits of an abstract factory, all rolled up into one. In your code you call the DI framework and tell it to get you an instance of a class - it figures out what objects need to be passed in for you so you don't need to do it. In your tests, you can instanciate the objects directly and pass in your stub/dummy/mock objects instead.

Links:

http://weblogs.asp.net/rosherove/archive/2007/09/16/mocks-and-stubs-the-difference-is-in-the-flow-of-information.aspx
http://www.hanselman.com/blog/ListOfNETDependencyInjectionContainersIOC.aspx


 
Categories: .NET | Software | VFP

July 11, 2008
@ 08:42 PM

I just ran across this and it's a welcome option - you can add "(loband)" to any of the MSDN documentation links on the website and it will serve up a much faster version of the docs. For example,

Instead of:

http://msdn.microsoft.com/en-us/library/cc707819.aspx

Try:

http://msdn.microsoft.com/en-us/library/cc707819(loband).aspx

There is also an option at the top of the page once you've selected this option to persist the low bandwidth view, so all of the pages come up like this by default. I appreciate the treeview when I'm just poking around, but sometimes the site is just painful to navigate to since it takes a bit to render them.


 
Categories: MSDN

July 6, 2008
@ 12:24 PM

I attended a Day of Dot Net event in Lansing a few week back. If you're not familiar with them, they are free mini-conferences (one day) about, not surprisingly, .NET.

I had originally planned on driving out to it Saturday morning, but then Jenn pointed out I'd have to get up really early to get there around 8am. I already work in Farmington, which is 45 minutes to 1 hour from home (and 45 minutes to 1 hour closer to Lansing) and would end up being a really long day for me. So I ended up just staying at a hotel in Lansing Friday night. That turned out to be a great idea. Note to self: the Best Western in Lansing feels and smells like a 80's style bowling alley.

When I got to the hotel, I had some time to look up directions to the college where it was being held. It was only a few miles away, so I decided to not bother to drive over there on Friday night (which is what I would normally have done). In the morning I followed the directions Google Maps had given and found myself in a church parking lot (hmm..."Day of Dot Net and Evangelical Revival??"). I checked the map a few times and it looked OK, and I was exactly where it said I should be. I think that was about the point where I starting cursing out Google maps. I had left all my information about the conference in the trunk so I had to get out of the car to get at it. I happened to notice that the road I was on looked like it actually continued around the side of the church (imagine a light bulb going off above my head: "hey...maybe...."). I jumped back in the car and drove around the parking lot and sure enough, the trees suddenly cleared on my left hand side where the college was hiding. I noticed another car stop right about where I stopped, so it wasn't just me being dense (honest!). Note to organizers - great event, but a small sign would have been appreciated.

When I got into the building (which also wasn't marked, so I still wasn't entirely sure I was at the right entrance), I was surprised at how few people were there - that kind of surprised me since I wasn't able to make it to the last DoDN because it had filled up. It turns out that as the morning wore on the sessions really started to fill up.

The sessions were an hour long - which is REALLY short; they flew by. The sessions all seemed to run a few minutes long which pushed into the next session running a bit longer. The lunch break helped to reset everything.

A few notes to the various presenters:

  • The bottom 1/3 of the screen really isn't visible if you're sitting in the back of the room. I was sitting in the second row and couldn't read some of it.
  • White text on a black background might be easier on your eyes for development, but it's impossible to read when it's projected up on a screen. I'd suggest sticking with black text on a white background.
  • Don't try to wing demo's. Only a few people can successfully pull that off - you're probably not one of them.

I actually ran into a few people I knew - one was someone from the local VFP user group, the other was a old-VFP developer that I haven't seen in a few years. That was a nice surprise. Overall, I was impressed by the number of people who attended, considering you're basically giving up a weekend day to attend. It's nice to see that some people actually care about getting better as developers (either that or they, like me, needed a few new shirts for their wardrobe).

One session happened to stand out in my mind - a session about Dependency Injection / Inversion of Control (specifically, the Windsor framework) by Jay Wren. Well organized, hit every question I had about DI/IoC. Honestly, I didn't "get" DI/IoC before this session; yeah, I understood what it was, but not really why on earth I might need a framework for it. It is actually an elegant way of solving a particular development problem, giving you the benefits of a factory pattern and the flexibility of DI, without getting in your way (at least that's what my notes say). I had the "a ha!" moment, then promptly lost it in one of the other sessions. I'm sure it will come to me at some point, although at this point I'm getting a bit nervous ;-)

At the end of the conference, they ended up giving away of ton of stuff. Just not to me. Oh well, maybe next time.

Overall, I definitely attend another one - a big thanks to the organizers and presenters and sponsors, I know it's a lot of work to put something like this on - it was appreciated. Just try to make sure you've got some soft drinks (Coke, Mt. Dew, etc.) available in the morning next time around <g>. It's hard for some of us to get moving in the morning without some caffeine (for us non-coffee drinkers). Sure I feel all healthy from the orange juice I ended up drinking, but it didn't help much to put a spring in my step.

Links

http://www.dayofdotnet.org/Lansing/2008/
http://jrwren.wrenfam.com/blog/


 
Categories: .NET | Conference

I've been working on an application which relies heavily on WCF to communicate. I have a very simple interface (contract) that the server supports to connect and disconnect: it exposes the methods Register() and Unregister(). When the client starts up and connects, it calls the Register() method, passing in some identification info. I save this information in a List<T> so that it can be used by the server to provide callbacks. When the client disconnects, it calls Unregister() which then removes the client from the collection.

That works well enough, right up until a client abruptly disconnects (ex. a connection error, network line goes down, etc.) Then suddenly I end up with a reference to a disconnected client on the server. If I attempt to use this connection to send a message back to the client an exception is thrown (which still works OK). It would be nice to know immediately as soon as a client disconnects.

If you are using TCP (full duplex) as the communication channel, you can do this pretty easily - note: this doesn't work for some of the other communication modes, like HTTP duplex. For those, you might have to rely on the various timeout settings in the .config file.

Here's what that ends up looking like (I happen to be taking advantage of LINQ here, but you can easily adjust that code if you're using an older vesion of the framework):

  203 private void IServer.Register(string systemName)

  204 {

  205     IClientCallback remoteMachine = OperationContext.Current.GetCallbackChannel<IClientCallback>();

  206     // Hook up events to let us know if the client disconnects w/o telling us.

  207     OperationContext.Current.Channel.Faulted += new EventHandler(ClientFaulted);

  208     OperationContext.Current.Channel.Closed += new EventHandler(ClientClosed);

  209 

  210     // Get object reference to figure out the IP address of the connected client

  211     MessageProperties prop = OperationContext.Current.IncomingMessageProperties;

  212     RemoteEndpointMessageProperty endpoint = prop[RemoteEndpointMessageProperty.Name] as RemoteEndpointMessageProperty;

  213 

  214     // (threading/locking code removed)

  215 

  216     client = m_callbackList.Find(c => c.SystemName == systemName);

  217     if (client == null)

  218     {

  219         // It's not already on our list, add it

  220         m_callbackList.Add(new RegisteredClient(systemName, endpoint.Address, remoteMachine));

  221     }

  222 }

 

When the client disconnects, the ClientFaulted/ClientClosed events will be fired. Honestly, at this point, the Unregister method isn't really needed, assuming you follow the same disconnection process in both cases.
 
Categories: WCF

April 19, 2008
@ 08:07 PM

 

I admit it - the above comic could be about me. I can be easily distracted by shiny things, so I sometimes have to fight off the urge to spend way too much time playing around with some cool bit of technology, code, or idea. If you're like me, these links may be your downfall. Lot's of things to sidetrack you with. The site I snagged the above comic from is just one of them.

http://www.xkcd.com

MIX is a web development conference put on by Microsoft. They've made all (well, at least I think it's all of them) of the conference topics available online. Very cool - there are bunch of really good sessions available here. Silverlight is looking interesting.

http://visitmix.com/

The TED (Technology, Entertainment, Design) conference is a four day conference with one "track" of speakers that each get 18 minutes to there thing. From what I've gathered, it's mostly an "invite only" type of event of around 1000 people (and even if it wasn't, the $6000 membership fee would probably keep the number of people attending under control). At any rate, they've made something like 200 of the talks available for free, so there are a ton of interesting videos to watch here. Since they're all under 18 minutes, it's easy to fit a video or two in a sitting. Then you can waste another few hours Googling some of the things they talk about.

http://www.ted.com

Google Earth - An "oldie" but a goodie. I can waste a ton of time with this one. Something about the interactivity of it really appeals to me. I can't say I was ever really a map-person until apps. like this and GPS became readily availble. And if you get bored, there are a bunch of neat 3D buildings and map overlays to download. Zoom in, zoom out, zoom in, zoom out...

http://earth.google.com/

Photosynth - If Google Earth appeals to you, you'll probably also love this one. It's basically a Microsoft research project (well, Microsoft owns it now) that takes pictures of some scene and projects it (or builds it, I'm not exactly sure) onto a 3d framework of the original location. Check out the Collections they've got - I swear I wasted a good 45 minutes rotating and zooming into the images. Even if you've seen this in the past, visit it again: they've added a few new collections that are pretty cool.

http://labs.live.com/photosynth/

The above should keep you busy for a while. I had planned on "featuring" a timewaster once a week or so, but at my current blogging pace it'd probably be closer to once a month, so I decided to just group a bunch of the more general ones together into one post. Have fun.


 
Categories: Other

April 15, 2008
@ 10:18 PM

One request that comes up from time to time is to embed a checkbox inside of an ASP.NET grid control for boolean data.

Unfortunately, one of the downsides to this is that the controls are "read only" - they don't let you check or uncheck them

without putting the row into edit mode. That works, but in some cases this isn't all that great either. What do you do if you just want a checkbox on each row, that's "live" and causes a postback as you check/uncheck items? Thankfully this doesn't take much code but figuring out the first time can be really painful. To get the "live" checkbox, just wrap it inside of a template. (In the example code I created a new Web Form named "GridCheckbox").

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="GridCheckbox.aspx.cs" Inherits="WebApplication1.GridCheckbox" %>

 

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

 

<html xmlns="http://www.w3.org/1999/xhtml" >

<head id="Head1" runat="server">

    <title>Untitled Page</title>

</head>

<body>

    <form id="form1" runat="server">

    <div>       

        <asp:GridView runat="server" ID="grdList" AutoGenerateColumns="false"

            onrowdatabound="grdList_RowDataBound">

            <Columns>

                <asp:TemplateField>

                    <ItemTemplate>                       

                        <asp:CheckBox runat="server" ID="chkItem" Checked='<%# Container.DataItem %>' AutoPostBack="True" OnCheckedChanged="CheckChanged"/>                                              

                    </ItemTemplate>

                </asp:TemplateField>

            </Columns>

        </asp:GridView>

    </div>

    </form>

</body>

</html>

 

Make sure you set the "AutoPostBack" to true. Then set it's OnCheckedChanged event handler to call your server side code.

Now let's add some code to the Page_Load to give our grid something to bind to:

protected void Page_Load(object sender, EventArgs e)

{

    bool[] items = { true, true, false, false, true };

    if (!Page.IsPostBack)

    {

        this.grdList.DataSource = items;

        this.grdList.DataBind();

    }

}

 

 

In my example code, I'm just binding to a simple boolean collection to keep things simple. Now we need an event handler to respond to our checkbox event:

protected void CheckChanged(object sender, EventArgs e)

{          

}

 

The code doesn't do anything yet but at this point you might be wondering how we figure out which checkbox we checked - normally, your grid is bound to a different row in some table. Each checkbox is related to that specific row. How or where do we get that from? The grid isn't much help in this case because it's not raising the event. If we were using a Button we could set it's CommandName and/or CommandArgument properties to hold something like the primary key of the row in our table. The checkbox control doesn't have any such properties. ASP.NET controls have an InputAttributes collection where you can place name/value pairs - this information is passed to the client (and back to the server), so it makes this relatively painless.

First, add an event to onRowDataBound of the grid (already shown in the ASPX above). Now add the event in our code-behind:

protected void grdList_RowDataBound(object sender, GridViewRowEventArgs e)

{       

}

 

We can't reference the control directly by name, since it was embedded in the grid and ASP.NET has made sure it's uniquely named. Let's use the FindControl method to do this. I've also added the code to add a Value attribute and added a member called m_row. I'm just using this so we can have a different value on each and every row of the grid. In a real application this is where you'd pull the primary key value from your datasource (probably using e.Row.DataItem).

private int m_row = 0;

protected void grdList_RowDataBound(object sender, GridViewRowEventArgs e)

{

    CheckBox chk = e.Row.FindControl("chkItem") as CheckBox;

 

    if (chk != null)

        chk.InputAttributes.Add("Value", this.m_row.ToString());

    this.m_row++;

}


Now we're just about done - all that's left is retrieving this value back on the server when the Checkbox is checked or unchecked:

protected void CheckChanged(object sender, EventArgs e)

{

    CheckBox chk = sender as CheckBox;

    string val = "";

    if (chk != null)

        val = chk.InputAttributes["Value"];

}


So our completed codebehind page looks like this:

using System;

using System.Collections;

using System.Configuration;

using System.Data;

using System.Web;

using System.Web.Security;

using System.Web.UI;

using System.Web.UI.HtmlControls;

using System.Web.UI.WebControls;

using System.Web.UI.WebControls.WebParts;

 

namespace WebApplication1

{

    public partial class GridCheckbox : System.Web.UI.Page

    {

        private int m_row = 0;

        protected void Page_Load(object sender, EventArgs e)

        {

            bool[] items = { true, true, false, false, true };

            if (!Page.IsPostBack)

            {

                this.grdList.DataSource = items;

                this.grdList.DataBind();

            }

        }

 

        protected void CheckChanged(object sender, EventArgs e)

        {

            CheckBox chk = sender as CheckBox;

            string val = "";

            if (chk != null)

                val = chk.InputAttributes["Value"];

        }

 

        protected void grdList_RowDataBound(object sender, GridViewRowEventArgs e)

        {

            CheckBox chk = e.Row.FindControl("chkItem") as CheckBox;

 

            if (chk != null)

                chk.InputAttributes.Add("Value", this.m_row.ToString());

            this.m_row++;

        }

    }

}

Now when you run this every time you check or uncheck an item you should see the page post-back (set a breakpoint on CheckChanged). You can now update your data, or whatever else you need to do in response to this event.
 
Categories: ASP.NET

April 4, 2008
@ 06:15 PM

This has hit me more than once already. If you create an HTTP Handler (ASHX) file, by default the context object reference (passed in to ProcessRequest) doesn't contain a reference to the Session object, so attempting to access context.Session will fail.

The fix is to add a "using System.Web.SessionState" to the using section, then inherit from the IReadOnlySessionState interface.

 

Ex.

 

using System.Web.SessionState;

public class MyAshx : IHttpHandler, IReadOnlySessionState
{

}

 

This will give you read only access to the session state. If you need to add to the session, inherit from IRequiresSessionState instead.


 
Categories: ASP.NET

April 3, 2008
@ 08:19 PM

I've been playing around a bit with WPF lately (with Visual Studio 2008) and was disappointed that there wasn't any intellisense in the designer (like what you'd see in the ASP.NET designer). I happened to mention this on the UT and John Fenton there pointed me to this link:

 

http://blogs.msdn.com/windowssdk/archive/2008/02/22/workaround-installing-win-sdk-after-vs2008-breaks-xaml-intellisense.aspx

 

Apparently installing the Windows SDK after installing VS2008 breaks XAML intellisense. The link above walks through fixing it (very simple registry entry fix).

 

Links

 

http://www.universalthread.com
http://blogs.msdn.com/windowssdk/archive/2008/02/22/workaround-installing-win-sdk-after-vs2008-breaks-xaml-intellisense.aspx


 
Categories: Visual Studio | WPF

March 23, 2008
@ 12:05 PM

I've finally gotten all set-up in Microsoft's Empowerment program. I wish I could say it went smoothly, but that definitely wasn't the case. I think I may have signed up at the worst possible time - they were in the process of revamping their website which caused me a bunch of different problems. I finally got tired of playing e-mail tag and called Partner support a few weeks ago. They had been telling me to complete the application process, but every time I tried to log back into the Empowerment site it just told me my application had been denied and it wouldn't let me sign back up (or even tell me WHY it had been denied). When I called they took a look at it then told me they needed to have someone else take a look at the problem. I received an e-mail a few days later claiming the problem should be resolved.

I tried logging back in but had the same problem I had been having. I called them again two weeks ago Monday and while I was on the phone they were finally able to clear whatever flag was keeping me from being able to resubmit my application - they definitely added a few more required fields from when I initially signed up. Last Monday I figured I'd try logging back into the Partner site and see if they had any way of checking the status. I ended up trying to sign up again but this time I got to a page which wanted me to agree to some EULA, but the buttons were all disabled. Was that a good sign or a bad sign?

I found out two days later (on Wednesday) when I received my Empowerment CD's and DVD's. Unfortunately, they don't include any kind of documentation about how to actually get your license keys. Since I've worked at a few places which had their Universal subscription (when it was available), I assumed I might just be able to log into the MSDN subscriber download section using my MS Live ID. I clicked on the "Associate your subscription with your WIndows Live ID" link but it also wanted me to enter my

MSDN

Benefit Access Number, Subscriber ID, or MSPP Technical Contact ID. Unfortunately I didn't receive anything labeled that way in the kit they sent me. I tried using my partner ID and my MCP ID, neither of which worked. I dug through the partner website and found that I actually had a "Technical ID" associated with my name. To find this - log into the partner site and click on the "Requirements & Assets" menu at the top, then select "Associated People"

PartnerAssoc

At the bottom of the screen that opens is a list of all people associated with your company and their technical ID. I tried entering this and it unfortunately didn't work. I thought (maybe) the site required a Live ID e-mail address instead of my other e-mail address, so I entered it instead and saved it. Then I tried signing in again. At that point the site complained that I had entered the wrong info. in too many times and to try again in 5 minutes. At that point I gave up.

The next day I dug up the MSDN support number and gave them a call. They had me re-enter the information I had tried the night before, fiddled with a few things and suddenly it let me log in!

I know someone who is planning on signing up as well and I'm curious to see if it goes smoother for them than it did for me - hopefully it does.

 

Links:

http://www.rcs-solutions.com/blog/2007/10/12/MicrosoftsEmpowerProgramForISVs.aspx
http://www.rcs-solutions.com/blog/2007/11/20/EmpowermentProgramUpdate.aspx
https://partner.microsoft.com/40011351
http://msdn2.microsoft.com/en-us/default.aspx


 
Categories: Software

March 9, 2008
@ 10:48 AM

Wow, local DAFUGer Frank Perez has actually posted new content on his blog. He's worse than I am with keeping it updated regularly (and I'm pretty sure only 3 or 4 people even knew he HAD a blog; that probably keeps the pressure to update it regularly to a minimum). Anyway, he's showing off a neat plug-in tool for Beyond Compare that let's you run comparisons against various VFP-specific filetypes (DBF/MNU/SCX/VCX among others). Check it out.

Links:

http://www.dafug.org
http://www.pfsolutions-mi.com/blog/2008/03/08/BeyondCompare.aspx


 
Categories: VFP

March 8, 2008
@ 02:16 PM

We ran into an interesting performance issue a few weeks back. We had migrated our primary fileserver over to a new machine (it was previously running on the same machine as our website). We expected some of the pages on our website to be a bit slower since the files were no longer on the same box (we have both data in VFP and in SQL Server 2005), but some of them were suddenly painfully slow. They went from 1-2 seconds to more than 7+ seconds. We talked about installing a dedicated network card to link two servers to help, but it still didn't seem like the performance should take that much of a hit.

My boss spent some time tracing the problem and found it was really slow when we opened the company file from our accounting system (Sage Pro). I've talked about the performance of USE in the past, but it was still amazing to see how slow it was. He tried using a mapped drive and UNC mapping but the performance of each was about the same. This particular table is part of a database, so he tried prefixing the USE statement with the database name, ex. USE F:\PathTo\Data\MyDatabase!MyTable IN 0 - the difference was amazing. That 7+ seconds dropped back down to 1-2 seconds: a bit slower than it was when it was local, but still much faster than it had been. Resolving the database is apparently very slow.


 
Categories: VFP

March 8, 2008
@ 02:00 PM

I was just checking out the PPCGeeks website, checking up to see if anyone had any status updates on the Sprint Mogul PPC. I've had this phone since late August, and have been waiting for a promised upgrade which is supposed to finally enable the built-in GPS-A support and support for EVDO Rev A. It finally looks like it may actually see the light of day on Monday, according to this post. It would have been nice to have had it released on Friday so I'd have the weekend to get it installed and get my phone customized again, but as a developer, I can appreciate not doing a release on a Friday.

I'm hoping Google Maps will support the built-in GPS. I've got an external blue tooth GPS I could use, but it's just not as convenient as something built-in. I'm not really looking forward to reinstalling all of my applications and customizing it with the HTC Touch interface (which is a MUCH nicer interface than the stock one), but thankfully this isn't something I have to do on a regular basis.

Links:

http://forum.ppcgeeks.com/showthread.php?t=20363
http://www.america.htc.com/support/mogul/software-downloads.html
http://www.google.com/gmm


 
Categories: Cellphones

February 10, 2008
@ 01:17 PM

I just uploaded a new version of the VFP calendar. I've fixed the problem where the drop-down version of the calendar wouldn't collapse if you clicked away from it. I initially thought it would be a simple matter of just adding some code to the calendar form's LostFocus event. That appeared to work, but had the side effect of breaking the drop-down button. If the calendar was being displayed and you then tried to click on the drop-down button to hide the calendar, the LostFocus would fire (hiding the calendar), then the Click event of the button would fire which would redisplay the calendar. Not quite what I was expecting.

I experimented with a few different ways of attempting to address this, but I just couldn't get the events to fire the way I wanted. Ultimately, I ended up adding code in the Click event to save off the last time since the calendar was hidden. If it is under the configured minimum interval, we don't do anything (the assumption is the the LostFocus just fired and hide the calendar). If the interval has been exceeded, the calendar is displayed as normal. A little weird, but relatively simple to code.

I've also added another sample to show how the rcsDateTimePicker controls can be hooked together for Start/End date scenarios. The controls keep the start date from being later than the ending date. The parent (Start) / child (End) relationship is setup via two properties on the control: uParentPicker and uChildPicker. These properties are evaluated to resolve to an object reference to the proper control.

 

Links

http://www.rcs-solutions.com/downloads.aspx


 
Categories: VFP

January 13, 2008
@ 05:33 PM

I'm happy to say my winter cleaning give away was a success. Almost all of the books that were available have new owners (although they may still be waiting for them, since they were shipped at the book rate which can take forever), and my huge pile of computer equipment is also gone. I had a taker for the computer equipment within a day of posting it on my local Freecycle site. I thought he'd pick through the rubble, but he ended up taking the whole pile (including my Windows NT 3.51, NT 4.0, and Windows 2000 Resource Kits - those alone took up a full bookshelf).

There are a few books still available, if anyone is interested.

Img_4417

 

Links:

http://www.rcs-solutions.com/blog/2007/12/13/WinterCleaning.aspx
http://www.freecycle.org


 
Categories: Other | VFP

January 13, 2008
@ 05:17 PM

I was just reading some of the threads over on the UT and ran across one where someone was looking for a drop-down calendar control. Someone suggested they look at the one that I've got in the downloads section on my site. Unfortunately, the version I've had up forever doesn't actually have a "drop down" version of the control. I've had an updated version for a long time now, but I've never gotten around to posting it (until now). This thread kicked me in the butt a little to update this on the site.

Here's a screenshot of the updated control:

DropdownCalendar

Hopefully you find it useful.

 

Links:

http://www.universalthread.com
http://www.rcs-solutions.com/Downloads.aspx


 
Categories: VFP

December 12, 2007
@ 10:23 PM

I've been spending a lot of time lately doing some winter cleaning. We're trying to free up some space in the basement for a play area for Brendan. It's amazing how much stuff you can collect. We've thrown away a LOT of stuff - I'm pretty sure the garbage guys hate us by now. Jenn mentioned that one of them didn't look too pleased when he tried to lift one of the bags we put out. We've been donating anything with think might still be useful, and we have people who drive through our subdivision on garbage days looking for interesting finds. More power to them, I say; I'd rather someone finds some use for this stuff instead of throwing it out. Besides, who's got the patience for a garage sale? And who really wants to deal with people trying to get half price for an item marked $1 that originally cost $50.

Since I've been involved with computers for quite some time (and not all of it as a developer), I've managed to collect quite a collection of old computers. Old Pentiums, 486's, a few 386's, motherboards, cases, power supplies, an unbelievable amount of cables, network cards, video cards, etc. I'm planning on posting that stuff on our local freecycle site to see if anyone might be interested in it before tossing it. One of my regrets with a lot of this is that I didn't give it away sooner, while it still may have been of more use to someone. I guess that may have been why I kept it.

A big part of this collection is a ton of books and magazines. I've whittled the magazines down to something manageable, but I still have way too many books. I'm sure I'll add more to the list as soon as I can convince myself that I really don't need them anymore, and once I have time to go through the ones still hiding in the basement (and hopefully before some of them aren't useful anymore). Here's a list of what's on the chopping block (you might be surprised; there are some good books here):

  • Apple II Plus/IIe Troubleshooting & Repair Guide, Robert C. Brenner. Sams. ISBN: 0-672-22353-8
  • DNS and BIND 3rd Edition, Paul Albitz & Cricket Liu. O'Reilly. ISBN: 1-56592-512-2
  • XML Extensible Markup Language (w/CD), Elliotte Rusty Harold. IDG Books. ISBN: 0-7645-3199-9
  • The Unified Modeling Language User Guide, Booch, Rumbaugh, Jacobson. Addison-Wesley. ISBN: 0-201-57168-4
  • The Visual FoxPro 3 Codebook (CD is missing), Yair Aan Griver. Sybex. ISBN: 0-7821-1648-5
  • Object Orientation in Visual Foxpro, Savannah Brentnall. Addison-Wesley. ISBN: 0-201-47943-5
  • Object Models: Strategies, Patterns, & Applications (Second Edition), Coad, North, Mayfield. Yourdon Press. ISBN: 0-13-840117-9
  • Visual Basic 6 Business Objects, Rockford Lhotka. Wrox. ISBN: 1-861001-07-X
  • ASP.NET 2.0 Unleashed, Stephen Walther. Sams. ISBN: 0-672-32823-2
  • Hacker's Guide to Visual FoxPro 6.0, Granor, Roche. Hentzenwerke Publishing. ISBN: 0-96550-936-2
  • The Inmates Are Running The Asylum, Alan Cooper. Sams. ISBN: 0-672-31649-8
  • About Face: The Essentials of User Interface Design, Alan Cooper. IDG Books. ISBN: 1-56884-322-4
  • The Improvement Guide, Langley, Nolan, Nolan, Normal, Provost. Jossey-Bass. ISBN: 0-7879-0257-8
  • HTML: The Complete Reference (Second Edition), Thomas A. Powell. Osborne. ISBN: 0-07-211977-2
  • Effective Techniques for Application Development w/VFP 6.0, Booth, Sawyer. Hentzenwerke. ISBN: 0-96550-937-0
  • What's New in Visual FoxPro 8.0, Granor, Hennig. Hentzenwerke. ISBN: 1-930919-40-9
  • CrysDev: A Developer's Guide to Integrating Crystal Reports, Craig Berntson. Hentzenwerke. ISBN: 1-930919-38-7
  • Advanced Object Oriented Programming w/VFP 6, Egger.  Hentzenwerke. ISBN: 0-96550-938-9
  • Client/Server Applications w/VFP & SQL Server, Urwiler, DeWitt, Ley, Koorhan. Hentzenwerke. ISBN: 1-930919-01-8
  • C# Unleashed, Joseph Mayo. Sams. ISBN: 0-672-321-22-X
  • Measuring and Managing Performance in Organizations, Robert D. Austin. Dorset House. ISBN: 0-932633-36-6
  • Windows 2000 Server Resource Kit (No CD), 8 books total
     

If anyone might be interested in this stuff (books or computer techno-rubble), drop me a line (I can take a pic. of the computer stuff). All of it free as long as you pick up the shipping cost. I hope I don't regret giving away some of this, these books have served me well <g>

 

Links:

http://www.freecycle.org


 
Categories: .NET | Other | VFP

December 4, 2007
@ 09:23 PM

While I'm working, I tend to open a LOT of windows (and leave them open). That way I'm not wasting time navigating around to the same places again and again. It's almost physically painful for me to watch other users open something like Explorer, spend the time navigating to a folder to do something like copy a file, then close the window (to satisfy some notion of keeping their desktop "Clean", I guess). Then, two minutes later, open Explorer again, navigate to the SAME folder, to do something else. I've found if I've spent the time opening some app., a website, etc. I'm very likely to need to have access to the same window a few more times within a fairly short period of time. In addition, there are a bunch of windows I leave open all the time. Things like one or more DOS prompts, maybe a few instances of Explore, Firefox w/a bunch of tabs open in each, SQL Management Studio, VFP, Visual Studio, Excel, Outlook, etc. Besides using up memory, there is very little downside (and my desktop at work and at home have 4GB, so I usually have a bit of memory to spare). I also don't reboot very often; sometimes weeks at a time if I can help it.

However, I still occasionally notice that things sometimes start to get flaky. I'll try right-clicking on a table in SQL Management studio to browse a table and the context-menu doesn't appear. Or I'll open IE and some of the menus are missing. Or Windows Explorer isn't "painting" correctly. Whatever. It seemed to be related to the number of programs open - not necessarily the amount of free memory. I'd did some digging and it seems to be related to the desktop heap. I found a great link which goes into detail about it:


http://blogs.msdn.com/ntdebugging/archive/2007/01/04/desktop-heap-overview.aspx


I ended up downloading the dheapmon tool mentioned and installing it. It has to be installed from the command prompt and requires access to the symbol libraries. I don't have them installed on my machine, so I ended up using the environment variable mentioned in the CHM file.


C:\>cd \kktools\dheapmon8.1\x86
C:\kktools\dheapmon8.1\x86>SET _NT_SYMBOL_PATH=symsrv*symsrv.dll*C:\Symbols*
http://msdl.microsoft.com/download/symbols
C:\kktools\dheapmon8.1\x86>dheapinst.exe
C:\kktools\dheapmon8.1\x86>dheapmon -l
C:\kktools\dheapmon8.1\x86>dheapmon


Desktop Heap Information Monitor Tool (Version 8.1.2925.0)
Copyright (c) Microsoft Corporation.  All rights reserved.
-------------------------------------------------------------
  Session ID:    0 Total Desktop: (  5824 KB -    8 desktops)
  WinStation\Desktop            Heap Size(KB)    Used Rate(%)
-------------------------------------------------------------
  WinSta0\Default                    3072             91.8
  WinSta0\Disconnect                   64              4.5
  WinSta0\Winlogon                    128             10.1
  Service-0x0-3e7$\Default            512             27.0
  Service-0x0-3e4$\Default            512             11.9
  Service-0x0-3e5$\Default            512              4.3
  SAWinSta\SADesktop                  512              0.5
  __X78B95_89_IW\__A8D9S1_42_ID       512              0.5
-------------------------------------------------------------
C:\kktools\dheapmon8.1\x86>


It looked like the WinSta0\Default was the issue; I'm at 91.8% usage. I followed the docs and it looked like I should modify the Windows registry key located here:
HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\SubSystems\

It was set to:

%SystemRoot%\system32\csrss.exe ObjectDirectory=\Windows SharedSection=1024,3072,512 Windows=On SubSystemType=Windows ServerDll=basesrv,1 ServerDll=winsrv:UserServerDllInitialization,3 ServerDll=winsrv:ConServerDllInitialization,2 ProfileControl=Off MaxRequestThreads=16

I changed it to:

%SystemRoot%\system32\csrss.exe ObjectDirectory=\Windows SharedSection=1024,4096,512 Windows=On SubSystemType=Windows ServerDll=basesrv,1 ServerDll=winsrv:UserServerDllInitialization,3 ServerDll=winsrv:ConServerDllInitialization,2 ProfileControl=Off MaxRequestThreads=16


(note that I changed the "3072" to "4096"). This should give me a bit more heap, so hopefully this will help. It looks like you have to reboot after making this kind of change, so it'll be a bit before I can tell whether it's really fixed the issue or not. I'm hopeful. If not, I'll probably try bumping it up a bit more.

Links
http://blogs.msdn.com/ntdebugging/archive/2007/01/04/desktop-heap-overview.aspx


 
Categories: Windows

December 1, 2007
@ 11:36 AM

I was forwarded this video described as, "The First Computer User and Tech Support". I'm sure it's hosted somewhere else, but I have no idea where it came from so I've uploaded it here. Hopefully the bandwith doesn't kill me <g>

Links

http://www.rcs-solutions.com/Misc/IT_Pro.wmv

Updated - Use this link instead (thanks for the link Rick):

http://www.youtube.com/watch?v=LRBIVRwvUeE


 
Categories: Other

November 28, 2007
@ 10:01 PM

I'm not sure when this was added (if it's just in VS 2008 or if it's been there since VS 2005), but I just noticed this while I was updating the website (I just added a download section). I created a new master page for the site, then updated the original home page with one that used the new master page. The master page is now home to the header, menu, and footer with a "hole" punched in the middle for my custom content. Then I added the download page and started adding files. You might not have noticed before, but the home page has a footer which moves with the browser; it basically sticks to the bottom by using a bit of CSS. This works well on the home page, and appeared to be OK while I was working on the download page. That is. up until the number of downloads forced the page to scroll. At that point the footer actually sat on top of the downloads listed, which isn't quite the effect I was hoping for. If I changed the footer style to float, it worked well for the download page but was pretty ugly for the home page (since it's a bit sparse the footer was like 1 inch below the header).

I played around with the idea of embedding a div tag in my home page that had relative heights to force the content back to where it belonged. That didn't work out too nicely, so I briefly thought about using JavaScript to handle this instead. That seemed like overkill, so I nixed that idea. If the footer was defined in my home page content section, I could just override the CSS style for that one page. However, it's in the master page. I could define two CSS files instead, but I really didn't like the idea of having to maintain two stylesheets. That's when I noticed a new section in my master page - a content holder for the head section of the page:

 MPContent

 

That made it really simple to just add an overriding style (with the same name as the one defined in my CSS file) into the home page content. I had to move the CSS link above the ContentPlaceHolder so that it was defined before my overriding style. Then I just added a <style> section inside of the header and I was good to go. This isn't earth shaking stuff, but it was a nice addition.


 
Categories: ASP.NET

November 28, 2007
@ 08:39 PM

I ran across this in the comments section over at Coding Horror:

"I'm bitter, angry and I hate you all. Isn't that proof that I've worked in the software development industry for a long time?"

 

Links

http://www.codinghorror.com


 
Categories: Other

November 19, 2007
@ 10:44 PM