Wednesday, January 24, 2007

Automatically Sizing ListView Columns

I use the Microsoft ListView ActiveX control a fair bit. It has several benefits over display-only grids, including multiple row selection and easy support for images. I usually try to avoid having a horizontal scroll bar if possible, so I size the ListView and its columns so the data nicely fits. However, one thing that messes that up is when a vertical scroll bar appears, which automatically happens when there are more rows than the ListView can display. In that case, if you've sized the columns so they exactly fit the width of the ListView, you get a horizontal scroll bar because the vertical scroll bar takes away some of the width of the ListView that was used by columns.

To deal with this, I decided it was better to initially size one of the columns larger than it needs to be to display its data (if possible), then make it narrower if a vertical scroll bar appears. The only problem: how do you know when the vertical scroll bar is visible? There isn't any property indicating that, so I decided to take a brute force method to figure it out.

The following code assumes the ListView is named oList and has two columns, the second of which will be resized after loading the list. There are a couple of "magic" numbers here: 1 is the height of a grid line in the ListView and 22 is the height of the column headers. The code determines whether a vertical scroll bar appears by calculating the height of each item (the height of the font plus the grid line), multiplying by the number of rows, and adding the height of the column headers. If that's greater than the height of the ListView, there's a vertical scroll bar, so the column width is adjusted, accounting for the width of the ListView, the width of the first column, the width of the ListView border, and the width of the vertical scroll bar.
with This.oList
llScroll = .ListItems.Count * ;
(fontmetric(1, .Object.Font.Name, .Object.Font.Size) + ;
fontmetric(5, .Object.Font.Name, .Object.Font.Size) + 1) + ;
22 > .Height
.ColumnHeaders.Item(2).Width = .Width - ;
.ColumnHeaders.Item(1).Width - sysmetric(4) - ;
iif(llScroll, sysmetric(7), 0)
endwith
Adjust this code as necessary if you have more than two columns or want to resize a different column or more than one column.

Thursday, January 11, 2007

Tag, I'm It

I've been tagged by Alex Feldstein, so it's my turn to tell five things about me that you may not know.

1. I'm lucky to be alive. A nasty combination of curiosity and clumsiness have been my downfall, literally, countless times. Here are a few:

  • When I was very young (three and younger), I nearly killed myself many times. I swallowed a penny, which my mother luckily poked down just as I passed out. I climbed onto a box which I stacked on a stool which I placed on a chair to get into my parent's liquor stash and had a couple of glugs of whiskey. I placed two nails in my mouth and played elephant, trying to poke my tusks into an electrical outlet. I wanted to iron shirts like my mom did, but forgot to take my shirt off first. The folks in the ER got to know me pretty well.

  • I've broken a number of bones, including my right humerus (which wasn't funny), left wrist, and the joint in my right thumb, all of which while doing somewhat dumb things.

  • I've had three concussions, one pretty serious (unconscious for several hours). The first two were playing football, the last only a few years ago while watersliding (OK, that one's kind of embarrassing).

  • While swimming at the bottom of a waterfall, I was pulled into a very wicked set of rapids. I emerged about 400 meters later with bruises that lasted four months.

2. I have a Master's degree, sort of. After graduating with a Bachelor of Science degree in Biochemistry, I joined the Biology department of the University of Dallas at Texas as a PhD candidate. However, after a year and a half studying molecular genetics, I came to the realization that most university professors (which I figured I'd be one day) were really just managers -- they manage graduate students who do the real science and spend most of their time filling out grant applications and attending meetings. Since I'd owned a computer for about four years at this point (1982), I decided to find a job in the computer field and that was the end of my academic career. However, I discovered some years later that I'd completed enough courses to qualify for a non-thesis Master of Science degree, but by that time, it was too late to apply.

3. I love sports. I loved football in elementary school, playing every day, even during blizzards in the winter. I also swam a lot, and took diving classes. I started wrestling in high school and liked it, although I wasn't very good (if you've ever met me, you know upper body strength isn't a forte). I continued playing a lot of football (not organized -- I tried it once and didn't care for the brutal mentality of my coach). I ran cross-country and track (400 m, 4x100 m, and 4x400 m) in 12th grade and was fairly successful (3rd in the city in the 400 and set city records in the 4x100 and 4x400). In college, I started scuba diving (which I haven't done since then), played a lot of floor hockey (which I was also good at, thanks to being fast), and played football a couple of times a week. After college, I took up cross-country skiing, which I did for a few years. Currently, I play racquetball twice a week (I took it up twenty years ago this year) and golf about a dozen times in the summer. I took a snowboarding lesson last weekend with my son and loved it, so I'm expecting to add that to my regular list of sports.

4. I don't like hockey. OK, that's not completely true -- I watch one game a year or so. I'm one of the only able-bodied Canadian males who never played ice hockey. Even Calvin Hsia plays hockey and he's from Hawaii! It comes down to the fact that I can hardly skate. It seems completely anti-Canadian, but it just wasn't something I got into as a kid.

5. I was a disco king. I was in the Canadian Reserves (a communications squadron) during college in the late 70s and we had dances once a month or so. My girlfriend at the time wanted to do the disco thing, so we practiced a lot in her living room. We got pretty good and won a couple of dance contests. Fortunately, there are no pictures of me in my white suit (that I'm aware of), but I'm not afraid to admit that I still like disco music to this day.

OK, here are the people I'm tagging:

John Koziol
Ted Roche
Craig Boyd
Ken Levy
Cesar Chalom

Monday, November 27, 2006

New Web Site

We switched Web and email servers on the weekend. While our old provider gave great service, we outgrew their capabilities. We also wanted to move to a DotNetNuke-based Web site because DNN allows you to create great-looking Web sites with a fraction of the effort required to create one from scratch. We haven't done a DNN version of www.stonefield.com yet, just www.stonefieldquery.com. One of the best features of our new site is a support forums area; check it out if you're a Stonefield Query user.

Thanks to Jeff Zinnert, who did most of the work on the new site, Al Williams of Lucky Dog Systems who did the initial setup and design, and our former provider, Tim Thibault, who helped with the switch-over.

Updated Favorites for IntelliSense

Michael Hawksworth sent a couple of enhancement requests (including code; ya gotta love that!) for the Favorites for IntelliSense (FFI) Builder that deals with handling duplicate or substring names better. I've posted an update on the Technical papers page of www.stonefield.com.

Wednesday, November 22, 2006

New Files on White Papers and Source Code Page

I posted a couple of new files on the White Papers and Source Code page of the Stonefield Web site.

The first is an updated version of the My namespace that ships with the October 2006 CTP version of Sedna. It fixes a couple of bugs in My and includes a sample form demonstrating some of the uses of My.

The second is a compilation of articles originally published in the August and November 2005 issues of FoxTalk describing how to add IntelliSense to runtime applications and how to control IntelliSense so it only shows the properties, events, and methods you're interested in seeing, providing a lot more control over IntelliSense than you normally get (a feature I call "Favorites for IntelliSense").

Rick Strahl Saves the Day

Stonefield Query uses an online activation mechanism so a customer can activate their software without having to contact us for an activation code. When they purchase the software, we assign them a serial number and update a database on our Web site. They install and run Stonefield Query, type in the serial number, and click the Online button. This calls a West Wind Web Connection application on our Web site that returns an activation code. The code on the client site is similar to this:

loHTTP = newobject('wwIPStuff', 'wwIPStuff.vcx')
loHTTP.Connect('www.SomeURL.com')
loHTTP.AddPostKey('SomeKey', 'ValueForKey')
lcPage = 'wc.dll?SomeProcess'
lcHTML = ''
lnLen = 0
try
lnResult = loHTTP.HTTPGetEx(lcPage, @lcHTML, @lnLen)
catch to loException
lnResult = -1
endtry

This works great. However, I got a bug report from one of our support staff the other day. They updated to Internet Explorer 7 and suddenly online activation stopped working. The error message displayed was "invalid handle."

I dreaded having to track this down. First, I had to install IE 7, which I've been putting off doing for a variety of reasons. Second, I'd have to dig into stuff that I'm not really familiar with--the wwIPStuff code and possibly a DLL--to figure out why this is failing. (And why would installing an updated version of an application, albeit one closely tied into Windows, change the behavior of a system DLL anyway?)

However, I remember reading a message on the West Wind Message Board (a great resource even if you don't use any West Wind tools) from a week or so ago stating that the HTTP code in wwIPStuff was deprecated and that wwHTTP should be used instead. I hadn't any reason to revisit any of my code using wwIPStuff because it just worked. So, after installing IE 7, I changed one line of code:

loHTTP = newobject('wwHTTP', 'wwHTTP.prg')

I crossed my fingers and tried the online activation. Problem solved! Since my copy of West Wind Client Tools is a couple of years old (yeah, I know I should update it), clearly pre-dating IE 7, I'm not sure why this worked better than wwIPStuff. In researching the problem later, I found an entry in Rick Strahl's blog that described the problem and the fact that he doesn't know why wwIPStuff fails either. Although I read his blog regularly, clearly I'd missed the significance of this one. Thanks again, Rick, for a great product!

Thursday, October 26, 2006

Southwest Fox 2006, Part 3

I started the last day of the conference by repeating my IntelliSense session, then went to hear Rick Schummer present Fishing with a ProjectHook. Although I've worked with ProjectHooks since VFP 6, Rick showed some really cool uses for them, so I picked up several tips from his session.

The conference wound up with several drawing for prizes and a farewell to everyone. About 20 of us went for lunch in the hotel. I ate too much pizza, so I went to the exercise room to wear some of it off, then had a short nap and watched the Oakland Raiders and Arizona Cardinals (actually, it was the other way around; the game was kind of dull so I nodded off). After a few drinks in the hotel bar with a good sized group of VFPers, Tamar Granor, Craig Berntson, Rob Eisler, and I went to the ASU area for some very tasty Greek food.

Rob and I stayed an extra day to see the Grand Canyon, which neither of us had seen before. Joining us on the tour was Tore Bleken from Norway, who'd been there three times before. This time, he took a helicopter tour in addition to the regular tour and said it was well worth it. Rob and I spent an hour hiking along the South Rim, then did some shopping. It was a long day (they picked us up at 6:30 am and dropped us off at 8:00 pm), over 500 miles of travel, but well worth it -- I definitely want to go back to do some hiking and white water rafting. Tore and I had a very nice dinner at the hotel restaurant (Rob wasn't hungry after a stop at Burger King on the return trip, which I passed on).

Final impressions: what a great conference! The topics were different from the usual fare, especially Christof's sessions, and I made tons of notes of ideas to implement. The speakers all did a great job, and I can't wait until next year's conference.

Southwest Fox 2006, Part 2

I started Saturday morning with Bo Durban's Using GDI+ with VFP session, which focused on the amazing VFPX GDI+ project he and Craig Boyd have been working on. He showed how easy it is to use GDI+ to do any type of drawing on any type of Windows canvas (window, report, printer, etc.), including rectangles, ellipses, pie slices, polygons, and paths of any shape. Very cool session!

Next I presented my Adding IntelliSense to Your Application session. As I blogged about when I presented this in Prague, it's kind of an esoteric topic, since not everyone needs to provide IntelliSense to their users. However, I was pleasantly surprised at how much feedback I got on this session, and how much interest there was in my Favorites for IntelliSense class, which gives you control over how IntelliSense works and what it displays for a particular class.

I missed the next session as I caught up on email and chatted with other developers. However, I'm sorry I missed Mike Feltman's Where Do You Want To Go Today session, which I had originally planned to see; from the comments of those who attended, it was a great session.

After lunch (make your own sandwiches from a buffet), I attended Nancy Folsom's session From Procedure Toward Component. This was a refactoring session similar to the one she did at GLGDW. I really liked the way she presented it, showing one step of a refactoring at a time and going over the code changes at each step. This approach made a somewhat abstract topic very concrete.

The last session of the day was Toni Feltman presenting Using Version Control with VFP. She started the session with a clarification: yes, she is pregnant, not just getting bigger. She then proceeded to show the basics of Visual SourceSafe 6.0, an outdated version she chose on purpose because it's one that many VFP developers already have (it came with Visual Studio 6, as did VFP 6). She showed how it integrates with VFP and discussed the pros and cons of integration. Finally, she showed Visual SourceSafe 2005 and discussed the features of several other popular source control packages.

After a break, we had a speaker and vendor dinner at the conference center. Craig Berntson and Cathy Pountney showed us all up by dressing up (they looked like they were going to a prom). Cathy admitted she'd never seen Monty Python, so Craig tried to convince her by acting out several skits, but was unsuccessful (not surprising if you were there to watch!).

Sunday, October 22, 2006

Southwest Fox 2006, Part 1

After a very early start (5:30 am flight), I arrived here in Phoenix mid-afternoon for the Southwest Fox 2006 conference. Several people told me that Rick Schummer and Craig Boyd were panicking because I hadn't shown up yet, and we were due to deliver the keynote at 7 pm, and hadn't really gone through our presentation yet. Fortunately, we got together about 6:30 and briefly went over what we were planning to show, then spent the rest of the time setting up and fighting with the projector.

I think the keynote went well. Craig started off with a funny story about a hair-raising drive through the canyons of Phoenix (which somehow I've never seen) with me at the wheel. We then showed a Fox Software video from about 1990 showing the then newest version, FoxPro 1.0. Moving on to the recently released CTP of SP2 and Sedna, Craig showed some of the cool reporting enhancements in SP2, I showed My and the new Upsizing Wizard, Rick showed the Data Explorer enhancements he's been working on and discussed NET4COM, and Craig showed some of the things he's created in the Vista Toolkit. We had planned to show some demos of VFPX projects, but since I promised attendees that "shorter keynote = earlier beer", we figured we'd better wind up. However, Ken Levy then got up and announced that I was awarded the 2006 FoxPro Community Lifetime Achievement Award. I was completely surprised and blown away by this!

Friday morning, I had a tough decision to make: attend Rick Borup's Automating the Build session or Christof Wollenhaupt's Security Cookbook session. I knew Rick always creates great white papers, so I decided to see Christof's session because I knew it would be pretty important. Actually, like most of the other attendees, it scared the crap out of me. Christof showed how easy it is to extract the source code from a VFP EXE, even one that had been locked down with Refox. He discussed some of the ways hackers can get access to applications and discussed ways to secure an application. I took about a page of notes from that session!

Next, I presented Installing Applications with Inno Setup. I've been using Inno Setup for several years now and love it. One of the early slides was titled "Why I Hate Windows Installer". Some of the reasons I gave are the large file sizes, incredibly slow performance, problems with installation of ActiveX controls, proprietary database, and the fact that sometimes Windows Installer seems to have a mind of its own when it comes to deciding what files to install. I showed how fast Inno loads, how easy it is to create an Inno setup script (which is just a text file), and the flexibility it gives you in configuring the setup executable. I also showed how you can change the appearance and behavior of the setup using scripting.

I then attended Craig Berntson's Agile Software Development. This session was a nice introduction to the topic, covering things like the principles of agile development, why agile vs. traditional development methods, different types of agile, such as Scrum, and some books worth reading on the topic.

After lunch, I repeated my Inno Setup session, then attended Christof's Crashing VFP and Preventing Crashes session. Once again, Christof showed us internals of VFP that most people aren't aware of. For example, he created a trigger on a table and in the trigger code, did a SUSPEND. This left VFP in data session 0, the so-called "system" data session, and he showed the types of things that appear in that data session. He also showed the types of things that cause VFP to crash, such as dangling object references caused by not nulling references to one object stored in another when the second object is destroyed, and how to avoid those types of problems.

I finished the day with Bo Durban's Creating Custom Report Controls. Bo showed the basics of ReportListeners, then moved on to show some cool uses, including displaying negative numbers with parentheses so the decimals line up and there aren't extra spaces. He then spent time going over new features in SP2, including how easy it is to add you own pages to the Properties dialogs in the Report Builder. I took a lot of notes in this session!

After a few minutes to freshen up, 17 of us went to the F1 Race Factory for some karts racing (other folks went to a local casino). There had been some trash talking before the race, such as Steve Hanlon stating that because he drove a Mini Cooper that he was a force to be reckoned with, Craig challenging Cathy Pountney, who's been around cars and racing her whole life, and even me, who came in third at kart racing in Germany last year behind only Rick Strahl and Jeff Zinnert, neither of whom were here. The race was a blast, but at 10 minutes not nearly long enough. The winner isn't decided by who finishes first but by the fastest lap time, and Cathy was the winner over Rick Schummer by 0.03 seconds. I came in third, largely because I spun out a couple of times while driving a little more aggressively than I should have. This was definitely the most fun activity you can have at a conference!

Wednesday, October 18, 2006

Off to Southwest Fox

I'm headed to Phoenix tomorrow for the third annual Southwest Fox conference. If previous years are any indication, this will be a great conference. All the sessions sound really interesting, but the ones I'm most looking forward to seeing are:

  • Automating the Build by Rick Borup: Rick's sessions are always very detailed and thought-provoking, and this one sounds like a dandy.

  • Creating Custom Report Controls and Customizing the Report Designer by Bo Durban: long title not withstanding :), I haven't heard Bo speak before and this is a topic near and dear to my heart.

  • The Security Cookbook and Crashing VFP and Preventing Crashes by Christof Wollenhaupt: I've known Christof a long time but haven't heard him speak before, and given that his knowledge of the internals of VFP is probably deeper than anyone outside Microsoft, these are must-see sessions.

  • From Procedure to Component by Nancy Folsom: Nancy's session on refactoring at GLGDW earlier this year (which I believe she's also doing a version of here) was great, and this one sounds like it'll be very interesting as well.