Wednesday, December 30, 2009

DateTimes Through OLEDB in VFP

Rob Eisler wrote an interesting blog post about an issue he ran into dealing with certain DateTime values stored in SQL Server accessed in VFP through OLEDB.

Tuesday, December 29, 2009

Axialis Software Sale

I regularly use Axialis Software’s IconWorkshop to create icons and other images. Good news: it (and other Axialis products) are on sale for half-price until the end of the year. That makes IconWorkshop just $34.95!

Friday, December 18, 2009

OEM Agreement with Dydacomp

Here’s a link for a press release about an OEM agreement Stonefield Software and Dydacomp recently signed:

Monday, November 09, 2009

Executable Signing with Inno Setup

As I discussed a couple of years ago, code signing your executables is important for a variety of reasons. Our installation creation tool of choice is Inno Setup and version 5.2.4 released in March 2009 made it easier to sign the setup executable through the new Signtool directive in the [Setup] section.

This directive works like this (assuming you already have a digital certificate):

  • Run the Inno Setup UI and choose Configure Sign Tools in the Tools menu.
  • Create a new “sign tool” by clicking Add and specifying a name and the command line to execute your signing application. For example, I created one called “Standard” with the following command line to call Microsoft’s SIGNTOOL.EXE:

"C:\Program Files\Microsoft Visual Studio 8\SDK\v2.0\Bin\signtool.exe" sign /f CertPath\mycert.pfx /p MyPassword

where CertPath\mycert.pfx is the name and location of the PFX file and MyPassword is the password.

  • In the [Setup] section of your Inno Setup script (ISS) file, add the following:

SignTool=Standard /d $qStonefield Query Installer$q $f

Specify the name of your “sign tool” in place of “Standard” and a descriptive name for your setup program in place of “Stonefield Query Installer.” $q is an Inno Setup constant representing a quote and $f is a constant containing the name and path of the setup EXE created by Inno Setup.

Now, every time you build your setup using the Inno Setup UI, your setup executable is automatically signed.

However, I also like to build setups as part of a build process, so I call the Inno Setup compiler via the command line. Once I added the SignTool directive in my ISS files, my command line builds failed.

Here’s the solution: you need to add the same “sign tool” definition you did to the UI to the command line. For example:

"C:\Program Files\Inno Setup 5\iscc" "/sStandard=C:\Program Files\Microsoft Visual Studio 8\SDK\v2.0\Bin\signtool.exe sign /f CertPath\mycert.pfx /p MyPassword $p" sfquery.iss

Now, whether I build using the UI or through a build process, my setup executable is always signed.

Friday, November 06, 2009

Previewing PDF Attachments in Outlook 2007

One thing that’s always annoyed me about Outlook is that there’s no built-in previewer for PDF attachments on emails. I always had to double-click the attachment to write it out to a temporary file and then open the application (Adobe Reader or whatever) to view it.

If necessity is the mother of invention, annoyance is the mother of Google (or Bing or whatever) searches. Tim Heuer’s Foxit PDF Preview Handler sounded pretty good, so after installing Foxit (ya gotta love a tool with “Fox” in its name), I installed Tim’s previewer and voila, PDF preview in Outlook. Thanks, Tim!

Monday, October 26, 2009

Dates for Southwest Fox 2010 Announced

At the closing session for Southwest Fox 2009, we announced the dates for Southwest Fox 2010: October 14-17, 2010. Planning for next year’s conference started before Southwest Fox 2009 had even commenced.


Friday, October 23, 2009

Southwest Fox 2009, Day 3

I slept in slightly (6:30 a.m.), which was good after several days of sleep deprivation. I went to do my second Stonefield Query vendor session but no one showed up (Duh! It’s 8:30 in the morning on the last day of the conference), so I went to Menachem Bazian’s session on open source tools. He presented quite a few tools I wasn’t familiar with but want to check out, including SugarCRM.

Next I went to Jim Nelson’s PEM Editor session. I mostly went because I mentored Jim (not that he needed my help) and worked with him a bit on PEM Editor. However, even though I’ve been using it for almost a year, I learned several things I didn’t know. More importantly, I saw how Jim uses some features I did know about but hadn’t used much, and now I really see how they were intended to be used.


In the last timeslot of the conference, I repeated my GDIPlusX session. I must admit I was watching the door to see if a crowd suddenly formed but it was uneventful.

Mike Feltman and Alan Stevens livened up the last day by doing their sessions wearing kilts. Certainly not something you see at the average conference! Alan’s dad said he liked Alan’s red “dress”.


We wound up the official part of the conference with the closing session, including announcing the dates for Southwest Fox 2010 (October 14-17) and drawing prizes. Here’s Tamar presenting an Amazon Kindle, courtesy of Sybase:

Southwest Fox 2009 017

After cleaning up for an hour or so, we met with the Arizona Golf Resort staff for a post-conference debriefing (not the Feltman-Stevens kind). We thanked them for all their hard work and especially how they really partnered with us to help fit what we wanted into our budget. We pointed out a few things they can improve, but they were all minor things.

After a brief rest, I went to the Feltman’s suite for the speaker dinner. Rather than going to a restaurant this year, we took the suggestion of several speakers and had a BBQ (the Arizona Golf Resort provides a couple of Weber grills between groups of rooms, at least in our area). We had NY strips (chicken for those who wanted), sweet potatoes, mixed veggies, salad, and peach crisp. This was definitely the way to go; it was much less formal and a lot more fun (although Therese and Tamar had to spend some time preparing things). About 8:00, other attendees started showing up and the party kicked into high gear. Kevin Ragsdale kept a group of us amused for an hour, doing impressions and hilarious riffs. Mike Feltman figures he should be our keynote speaker for next year. I finally called it a night at about 2:30.

As I said at the closing session, this was easily the most fun Southwest Fox, or conference of any kind, ever. Everyone seemed to be energetic and full of fun, and the camaraderie was off the charts! As I mentioned in an earlier post, I really think Twitter had a lot to do with it. Like CompuServe of old, Twitter is a place for the conversation to carry on year-round. Thanks to Twitter, people I’d only briefly met at previous conferences (or hadn’t met at all!) seemed like old friends. I’m happy to see that several new people joined the conversation right after the conference ended; more new friends!

Thanks to everyone who came to Southwest Fox and made it a truly outstanding event: speakers, attendees, Arizona Golf Resort staff, exhibitors. I’d especially like to thank:

  • Therese Schummer and Marshal Granor, who made it possible for Rick, Tamar, and I to see more sessions than ever, and took a large burden off our shoulders.
  • My partners Rick and Tamar for organizing this conference so it ran as smooth as glass.
  • Mike and Toni Feltman for opening their room to everyone and creating a memorable night-after-night party.

See you all next year!

Southwest Fox 2009, Day 2

Once again, I was up early but really fired up: today was F1 racing day, something Rick, Cathy, and I have been trashing talking each other over for the past year.

After breakfast, I presented my GDIPlusX session. This was a fun session to do. I started by going over the basics of GDIPlusX: how to draw, using colors, drawing text and images, etc. Then I dug into practical uses, including measuring strings accurately, creating gradient images, and implement a “lightbox” effect Bernard Bout blogged about. Almost all of the examples I showed came from production code I use in Stonefield Query.


Next was my Stonefield Query vendor session. Interestingly, all of the people who showed up were customers or already familiar with Stonefield Query, so rather than doing the usual demo, I covered the same things we discussed at Friday night’s developer meeting. One of the cool new features I showed is “application views”. The problem with most reporting solutions is that they show a database-centric view of the data in an application. Even with nice descriptive names for tables and fields, it still isn’t a natural view of the data for the user. With application views, you can mold the data dictionary so it’s organized exactly like the data entry forms in your application, making it much easier for the user to find exactly which items they want to report on.

I was going to see Alan Steven’s OOP session but started chatting outside with Cathy and Toni (and others who happened by from time to time) and ended up spending the entire session there. That’s one of the nice things about a conference: if you don’t feel like going to a session, you can meet new people, chat with friends, and discuss new solutions to problems.

Lunch was build your own hamburgers with either meat patties or portobello mushrooms. Like some others, I actually went for both, which was a very tasty combination.

After lunch, I went to see Jody Meyer’s Office Automation session. Jody is one of our first-time speakers so I wanted to see how she did, plus learn more about Office Automation. One of my developers, Trevor Mansuy, was also in this session and had lots of questions for Jody, as he’s currently working on a couple of new features for Stonefield Query involving Excel.

Southwest Fox 2009 005

Next up was Christof’s Excelporting session. Christof did his usual excellent job and was even funnier than usual. Creating Excel documents by outputting XML is not only incredibly fast but doesn’t require a license for Excel. Unfortunately, and this was totally not his fault, the three hours of sleep I was getting for the past several nights finally caught up to me and I dozed off several times. Steve Bodnar was quite impressed with the various angles I managed to twist myself into without actually falling off my chair! Thank goodness Christof’s white paper and samples are on the conference CD so I can see what I missed.

The last timeslot of the day was the repeat of my VPC session. Shortly after I started, more people started filing into the room. I mentioned that there were open seats near the front, but they seemed content to stand at the back. Then more people came in. Then more. And even more. By this point, there were at least 40 people standing at the back of the room and a lot just outside the room. I knew something was up but had no idea what was going on. Suddenly, Craig Boyd screamed out and the attack began: I was hit by HUNDREDS of darts from the 40 or so Nerf guns these people hid behind their backs. The attack lasted a minute or so, then Craig yelled “Pull back” and they all filed out, leaving me to stand in a pile of darts. If you want to watch for yourself, at least three people recorded it and put it on YouTube:

Talking to Craig later, this was apparently revenge for my thinking about messing with him on Friday. Let me get this straight: you want to get revenge for something I thought about pretending to do? In the words of the immortal Bugs Bunny, “of course you realize this means war”. You should come to Southwest Fox 2010 just to see what I have planned for Craig!

Rick, Therese, Christof, Emerson, and I were going to meet several others for sushi but couldn’t find the restaurant, so we found a sushi place close to the hotel and settled in there. Wow, was it good! Excellent sushi and large portions.

Finally, the moment we’d been waiting for: racing at the F1 Race Factory. More than 20 people showed up for this year’s event. Rick and I suspected Jody, Toni, and Cathy had something planned: Jody carried a large bag into the building and wouldn’t show us what was in it. Rick and I figured there was a conspiracy against us, with Jody and Toni acting as blockers so Cathy could zoom by. However, what they really planned was WAY cooler:


The Pink Ladies and Danny Zuko ride again!

Unfortunately, it didn’t help Cathy: Paul Mrozowski finished first, I was second, Rick was third, and Cathy was 99th or something like that (it doesn’t really matter once you’re that far down <gd&r>).

Not as many people were in the second race, and it was a lot more wild (at least for me). I spun out a couple of times and was black-flagged for taking Dave Hanna into a wall. However, it was great fun and we’ll definitely be back next year.

We got back to the Arizona Golf Resort about 11:30 and proceeded to the Feltman’s suite for another evening of socializing. I called it a night at about 1:00 because I had an 8:30 session.

Southwest Fox 2009, Day 1

I woke up at 5:30 a.m. Friday (pretty much standard for me at conferences), so I did a little email and then went to the conference center to set up room signs, test projectors, and have breakfast.

I then headed to Jim Nelson’s FoxCharts session. Jim started by showing an overview of what you can do with FoxCharts, then went over the basics of creating charts, building example upon example. He went through the majority of the properties and methods to show how easy it is to customize a chart. Finally, he showed a very cool Visual Chart Designer (VCD) he created that acts not just as a builder for developers but a simple tool allowing users to customize their charts visually. VCD isn’t part of the FoxCharts VFPX project yet but it will be soon.


Next I went to Craig Boyd’s Virtual Earth session. Craig showed the basics of Virtual Earth (now called Bing Maps) and discussed the API. Then he showed a wrapper he created for VFP developers making it very easy to incorporate mapping into your own applications. Apparently, this is the most complete wrapper available in any language: he exposes more properties and methods than even .Net developers have. One cool technique he showed is how to use JSON to serialize a VFP object and pass it to JavaScript, something I haven’t seen done before.


Part way through Craig’s session, he excused himself to refresh his water glass. I told him I’d do it for him and took his glass into the hallway to refill it. As I was coming back into the room, an evil idea hit me: since he was the only one facing the back of the room, I could do something to mess with him and no one else would be the wiser. I decided to pretend to, ahem, relieve myself in his glass. Unfortunately, I couldn’t catch his eye as he was in his usual Boyd demo zone (if you’ve seen Craig speak, you know what I’m talking about), so I just took it back up to the front. After the session, I told Craig what I’d thought about doing and he thought it would have been really funny. Little did I know this would come back to bite me on Saturday!

The next timeslot was my session on Microsoft Virtual PC. I showed how to install VFP, how to create a “base” virtual machine with the operating system of your choice, how to create “working” VMs, and how to manage your VMs. I then went through a variety of uses for VMs, including testing installs for missing dependencies, testing applications in different environment (such as Windows regional settings different than your usual ones), demos and presentations, installing beta versions of applications or operating systems, and so on.


Lunch was deli-style: make your own sandwiches, potato salad, etc. Very tasty and interesting conversation. One thing we forgot to do was draw for prizes; Tamar remembered after lunch. Oh well, more prizes for the dinner party.

After lunch, I sat in on Cathy Pountney’s back-to-back reporting sessions. As usual, Cathy showed very cool techniques, including how to automatically shrink fonts so text fits in the allotted space, how to force page breaks, and adding text and graphic watermarks.

One of the really interesting things about this year’s Southwest Fox was how many people were on Twitter, tweeting about the sessions they were in. At one point, I was sitting beside Mike Roof of Matrix Imaging and he started laughing. When I leaned over to see what was so funny, he pointed at a tweet Steve Bodnar had just posted about me being on my hands and knees in Cathy’s session (I was plugging in a power bar which had become unplugged). That started some funny back-and-forth comments and even spilled into some “real time” jocularity. I think Twitter is directly responsible for what really feels to me like a strengthening of the VFP community of late. If you aren’t on Twitter, it’s time for you to join the conversation!

One change we made in the schedule this year was to set aside a “normal” timeslot for bonus sessions, rather than always having them in the evening when people want to socialize. The two sessions at 5:15 were “Show Us Your Apps” and “VFPX Users Meeting”. I sat in about half of the SUYA session, watching Dave Tucker demo KnowItAll, a very interesting, Microsoft OneNote-like application that every Southwest Fox attendee got for free, Paul Mrozowski show his very interesting calendar control, and John Henn show his Web store software. I then moved over to catch the second half of the VFPX session. The VFPX session was streamed live, so you can still watch it even if you weren’t at Southwest Fox.

Like last year, Friday evening featured a dinner party. This year it was Italian: delicious pasta and chicken dishes. After dinner, we drew names for door prizes, including t-shirts from Red Gate and SnagIt and Camtasia from TechSmith. Servoy donated a gift basket, including a license to their software, and it was presented by one of their staff doing a very funny Borat impression.

After dinner, it was time for more bonus sessions. I hosted a Stonefield Query developer meeting, in which I went over features we added in version 3.3 (released earlier this year), showed new features planned for 4.0 (due next year), and discussed wish list items with developers using our software.

By the time we wound up, it was almost 10 p.m. That makes for a very long day, but it wasn’t over yet. Quite a few people went to the Feltman’s suite to socialize and party until the wee hours. After lots of great discussions, more than a couple of beers, and tons of laughs, I headed to my room about 2:00 a.m.

Tuesday, October 20, 2009

Southwest Fox 2009: Pre-Conference

On Tuesday, October 13, Rick, his wife Therese, Tamar, her husband Marshal, and I arrived in beautiful sunny Phoenix to start preparing for Southwest Fox. The weather was a pleasant change from home, where it had snowed throughout the Canadian Thanksgiving weekend. We ran some errands, such as picking up the shirts and conference bags, water, and other supplies. We had a great dinner at the Cheesecake Factory and called it an early evening, as most of us had been up since well before sunrise (2:30 a.m. Phoenix time in my case). I slept a much needed eight hours.

We spent Wednesday meeting with hotel staff, assembling binders and bags, and doing other prep work. This year, we decided to do things a little differently: rather than assembling a bag when an attendee comes to the registration table, we did them before hand, including shirt and name badge. This made a huge different at registration time: it was easily handled by one person, whereas in previous years we needed at least two or even three when it got busy. We were done by about 3:00 so I caught up on some emails until dinner time. That evening, I got to meet the Ceil Silver Ambassador, Emerson Santon Reed from Brazil. I was thrilled to meet him and found him to be very nice and really excited to be at Southwest Fox. A good-sized group, including Tamar, Marshal, Rick, Therese, Barbara Peisch, Dan Freeman, and Emerson, went to P.F. Chang’s for a really good dinner.

I got up early Thursday (as I did pretty much every day) to help finalize registration, then for the first time ever, attended a pre-conference session since we didn’t need everyone at the registration table. I saw Walt’s excellent session on SourceGear Vault, as did Trevor Mansuy and Chris Wolf, who both work for me. We’re really fired up now and plan on implementing Vault soon.

After a tasty Mexican lunch, I spent the afternoon at the registration table. It’s always fun doing that because you can meet up with old friends and put faces to the names of new people. Afterward, several of us went for dinner (BBQ ribs and chicken) at the hotel.

At 7:00, we started the keynote session. After introducing the speakers, thanking sponsors and others who helped, covering conference logistics, and awarding Cesar Chalom the 2009 VFPX Administrators Award, Sara Ford began her keynote on CodePlex. You can watch the entire keynote at Afterward, we held a reception in the trade show area so attendees had a chance to talk to the exhibitors.

After the reception, a group of people went to the hotel bar while others congregated in the “Mike and Toni Feltman Party Suite,” which was to become a very popular place over the next few days.

VFPX Administrator’s Outstanding Service Award

At the keynote presentation for Southwest Fox 2009, the administrators of VFPX (Craig Boyd, Rick Schummer, and I) presented Cesar Chalom with the 2009 VFPX Administrator’s Outstanding Service Award (you can watch the presentation at Cesar is well-deserving of this award due to his work on the GDIPlusX and FoxCharts projects, both of which were covered in sessions at this year’s conference. Unfortunately, Cesar couldn’t make it to Southwest Fox this year, so the Ceil Silver Ambassador, Emerson Santon Reed, accepted it on his behalf and will present it to Cesar when he returns to Brazil.

Wednesday, October 07, 2009

Southwest Fox 2009 is Next Week!

We’re only a little more than week from the start of Southwest Fox (actually, less for Rick, Tamar, and I because we get there on Tuesday). I’m really pumped up about the conference: great sessions, great people, great weather (anything’s better than the 35F or 2C it is here right now) … what more could you ask for? I’m going to be busy: two sessions presented twice, plus a session demoing Stonefield Query presented twice, plus a Stonefield Query Developers meeting. I guess I better try to catch up on my sleep now!

Thursday, October 01, 2009

MVP for 2009-2010

I am once again honored to be named a Microsoft Most Valuable Professional (MVP). Congratulations to other award recipients; see for a complete list of VFP MVPs.


Tuesday, September 29, 2009

Handy Free Screen Ruler Utility

Spadix Software has a free screen ruler utility that makes it easy to measure the sizes of things on your screen: This solves the problem of deciding a form needs to be bigger, resizing it at runtime, and then trying to figure out what the new size is. I usually brought up the Debugger and typed something like “_screen.activeform.width” into the Watch window, but this is a lot easier.

Thursday, September 24, 2009

Sizing a ListView to Avoid Scrolling

I prefer to avoid horizontal scrollbars if possible. A horizontal scrollbar automatically appears in a ListView ActiveX control if the columns are sized too wide for the width of the ListView. I like to size the columns so they exactly fit within the width of the ListView. However, if the ListView’s Anchor property is set to resize the control when the user resizes the form, at some point a vertical scrollbar appears if the ListView is sized too short for the rows displayed. Since the scrollbar takes up some of the width of the ListView, a horizontal scrollbar also appears.

The trick is to detect when the vertical scrollbar appears and adjust the width of the columns so they fit within the remaining width. The following code, which goes in the Resize event of the form or container the ListView is in, handles that. This code assumes there’s only two columns and the second column should be resized. Adjust the code as necessary to use different columns

with This.oListView

* See if the ListView has a vertical scrollbar.

#define WS_HSCROLL 0x100000
#define WS_VSCROLL 0x200000
#define GWL_STYLE -16
declare integer GetWindowLong in Win32API integer hwnd, integer nIndex
llScroll = bitand(GetWindowLong(.hWnd, GWL_STYLE), WS_VSCROLL) <> 0

* Set the width of the second column.

lnWidth = .Width - .ColumnHeaders.Item(1).Width - sysmetric(4) - ;
iif(llScroll, sysmetric(7), 0) + 4
&& 4 is a fudge factor for width
.ColumnHeaders.Item(2).Width = max(lnWidth, 0)

Tuesday, September 22, 2009

.NET Tools Survey

Just fill in this quick 10 minute survey about .NET tools and you could win one of five $100 vouchers to spend with Amazon. Take the survey here:

Thursday, September 10, 2009

Southwest Fox “Recession Buster” Deals

Due to the condition of the global economy, we're seeing a drop in registrations for Southwest Fox 2009 this year. So we have a couple of special "recession buster" deals we hope will encourage a few more people to sign up for the best Visual FoxPro conference in North America.

Deal #1: "Organizers: please share my deal!"

If you already registered and paid for the conference and you know someone who wants to register, you can give them the same deal you got when you registered. If you want to come to the conference and you know someone who got in at the Super Saver ($620) or the Early-bird ($695) registration, you can sign up for the same price they did. Sharing is caring!

Deal #2: Southwest Fox "Pair Programmer" deal

Have one or more FoxPro friends who are considering coming to Southwest Fox? Sign up together and take $50 off each of the registrations.

No matter what deal you take, we will give you your first pre-conference session for free!

There's only one catch. You have to take advantage of this deal by 11:59 PM September 30, 2009 Eastern time. We have to make some serious commitments on October 1 for various expenses we have for the conference. See the Registration page for more details.

Friday, September 04, 2009

Southwest Fox 2009 Keynote

For the first time, this year’s edition of Southwest Fox will have a real keynote speaker. Sara Ford, Program Manager for CodePlex at Microsoft, is doing a presentation called “Towards a Stronger Open Source Ecosystem on” As you likely know, VFPX, the premier VFP community site, is hosted on CodePlex. For more details, see the Southwest Fox Blog.

I’ve met Sara several times and let me tell you, she is a character. She’s also very interested in VFPX. She gave us several tips early on about how to better organize VFPX (VFPX is unusual for CodePlex in that it’s a collection of many projects rather than just a single one) and even made a tweak to CodePlex to help VFPX work better.

Between the line-up of speakers, top-notch sessions, great networking opportunities, a chance to talk face-to-face with exhibitors about their products, and now having Sara deliver the keynote, Southwest Fox 2009 is shaping up to be even better than last year. See you next month in Arizona!

Wednesday, August 26, 2009

More on TreeViews and GDIPlusX

In my blog post Disabling a TreeView Control, I showed some code that visually disables a TreeView. It doesn’t really do that; instead, it uses GDIPlusX to take a snapshot of the TreeView, converts the snapshot to have a “disabled” appearance, hides the TreeView, and displays the snapshot in its place.

I just found another use for this technique. Suppose you want a VFP control to temporarily appear on top of a TreeView control. As you’re likely aware, the TreeView is an ActiveX control, and although it doesn’t visually appear this way, ActiveX controls display in their own window. As a result, any VFP control occupying the same space of a TreeView appears behind the TreeView, regardless of ZOrder.

Here’s an example. I’m adding a new feature to Stonefield Query that allows the developer to display fields organized by screen/form rather than by table. The idea is to make it easier for the user to find the fields they’re interested in because the fields map directly to what the user sees in their application. In this case, the Accounts Receivable module has three sub-modules: A/R Customers, A/R Setup, and A/R Transactions. A/R Customers has four forms: Customer Groups, National Accounts, Customers, and Ship-To Locations. The user chooses the desired form from a drop-down control (the SFComboTree control discussed in my article in the September 2009 issue of FoxRockX) and a TreeView control displays a list of the pages in that form and the fields on each page in a hierarchical view.


Notice the problem in this screen shot? The border around the dropped down SFComboTree disappears where it overlaps the available fields TreeView control. The drop-down part is a Shape surrounding another TreeView. While the dropped-down TreeView overlaps the fields TreeView as expected (an ActiveX control can overlap another ActiveX control), the Shape disappears behind the fields TreeView.

Fortunately, there’s an easy solution for this: use the same lightbox technique I discussed earlier but this time don’t make the image appear disabled: just take a snapshot of the TreeView, hide the TreeView, and place the snapshot where the TreeView is. Here’s the result:


The border for the dropped-down control now appears because the TreeView is temporarily hidden and what you see underneath is a snapshot of the TreeView.

The code is even simpler than the lightbox code because it doesn’t have to change colors. This is the code used when the SFComboTree is dropped down:

with This.Parent
loTree = .oTree
lnWidth = loTree.Width
lnHeight = loTree.Height
with .imgLightBox
.Top = loTree.Top
.Left = loTree.Left
.Width = lnWidth
.Height = lnHeight
loBmp = _screen.System.Drawing.Bitmap.FromScreen(.imgLightBox)
with .imgLightBox
.PictureVal = loBmp.GetPictureValFromHBitmap()
.Visible = .T.
loTree.Visible = .F.

The more I use GDIPlusX, the more I love it! My GDIPlusX session at Southwest Fox 2009 will cover other interesting uses for GDIPlusX. I’m also doing that session and an introduction to GDIPlusX session at the 2009 German DevCon. Hope to see you there.

Tuesday, August 25, 2009

Southwest Fox 2009 Early-Bird Deadline Next Week

Southwest Fox is only seven weeks away. This year’s conference has an incredible line-up of speakers and sessions. Not to pick favorites, but I’m especially looking forward to Christof’s Excelporting session, Paul’s Lucene.NET presentation, Jim’s sessions on PEM Editor and FoxCharts, and both of Cathy’s sessions. I’d also really like to see Toni’s session on Subversion and Walt’s session on Vault (especially after seeing his video), but they’re both pre-conference sessions and Thursday is registration day. As an organizer, I’m pretty busy that day.

If you haven’t registered yet, be sure to do so before September 1 to save $50 on your registration fee. If you’ve been to Southwest Fox before, you know what a great training and networking opportunity it is. If you haven’t, read what attendees from past years have said. In addition to the usual perks, this year you’ll get a chance to meet and hang out with the Ceil Silver Ambassador from Brazil.

Thursday, August 20, 2009

Disabling a TreeView Control

In my post “Setting the Background Color of a TreeView Control”, I presented some code that sets the background color of a TreeView to make it appear disabled. However, a reader named Alberto pointed out that after running that code, indented nodes have an ugly white background in front of them. I played with this a bit but couldn’t come up with a way to fix it.

Fortunately, there’s another solution: using a “lightbox”. Bernard Bout blogged about using the VFPX GDIPluxX project to create an image with a darker representation of a form and overlaying the form with the image to make the entire form appear disabled. I adapted his code to do the same thing with a TreeView control. Pass this code up to four parameters:

  • A reference to the form the TreeView is on.
  • A reference to the TreeView itself.
  • .T. to enable the TreeView or .F. to disable it
  • Optionally, an RGB value to use as the disabled color. If this isn’t passed, grey—RGB(240, 240, 240)—is used. This parameter isn’t used if the third parameter is .T.

This code creates an image object, takes a snapshot of the TreeView contents, makes the snapshot darker so it appears disabled, and uses the snapshot as the picture for the image. Note that a VFP control can’t cover an ActiveX control, so the code hides the TreeView. Of course, to the user, it looks like the TreeView is still there but disabled because the image is placed exactly where the TreeView is and contains a picture that looks just like a disabled version of the TreeView.

This code requires System.APP, which comes with GDIPlusX.

lparameters toForm, ;
toTreeView, ;
tlEnable, ;
local llImage, ;
lnWidth, ;
lnHeight, ;
lnColor, ;
lnFactor, ;
lnRed, ;
lnGreen, ;
lnBlue, ;
loClrMatrix, ;
loBmp, ;
loGfx, ;

* See if the specified form has a LightBox image.

llImage = pemstatus(toForm, 'imgLightBox', 5)
do case

* It does and we're supposed to enable the TreeView, so hide the image and
* redisplay the TreeView.

case tlEnable and llImage
toForm.imgLightBox.Visible = .F.
toForm.imgLightBox.PictureVal = ''
toTreeView.Visible = .T.

* We're supposed to disable the TreeView, so ensure GDIPlusX libraries are
* open and create the image if necessary.

case not tlEnable
if not llImage
toForm.AddObject('imgLightBox', 'Image')
endif not llImage

* Size the image as necessary.

lnWidth = toTreeView.Width
lnHeight = toTreeView.Height
with toForm.imgLightBox
.Top = toTreeView.Top
.Left = toTreeView.Left
.Width = lnWidth
.Height = lnHeight

* If we weren't passed a color to use, use grey.

if vartype(tnColor) = 'N'
lnColor = tnColor
lnColor = rgb(240, 240, 240)
endif vartype(tnColor) = 'N'

* Get the colors we'll need.

lnFactor = 0.90 && 0 = Dark 1 = Bright
lnRed = bitand(lnColor, 0x000000FF) / 255 * lnFactor
lnGreen = bitrshift(bitand(lnColor, 0x0000FF00), 8) / 255 * lnFactor
lnBlue = bitrshift(bitand(lnColor, 0x00FF0000), 16) / 255 * lnFactor

* Create a BMP of the desired color and use it as the picture for the image.

with _Screen.System.Drawing as xfcSystem of Source\System.PRG
loClrMatrix = .Imaging.ColorMatrix.New( ;
lnRed, 0, 0, 0, 0, ;
0, lnGreen, 0, 0, 0, ;
0, 0, lnBlue, 0, 0, ;
0, 0, 0, 1, 0, ;
0, 0, 0, 0, 1)
loBmp = .Bitmap.FromScreen(toForm.imgLightBox)
loGfx = .Graphics.FromImage(loBmp)
loGfx.FillRectangle(.SolidBrush.New(.Color.FromARGB(10, 0, 0, 0)), ;
0, 0, lnWidth, lnHeight)
with toForm.imgLightBox
.PictureVal = loBmp.GetPictureValFromHBitmap()
.Visible = .T.
toTreeView.Visible = .F.

Friday, August 14, 2009

New VFP Blogger

Welcome to the blogosphere, Matt Slay.

Tuesday, August 11, 2009

Outlook 2007 RSS Feeds Not Refreshing

I’ve had this happen several times over the past couple of years: suddenly, Outlook no longer refreshes RSS feeds. The only solution I’d found to make it start re-reading the feeds was to select each one and click Send/Receive (or press F9). When you have more than 100 feeds, that’s time-consuming and painful.

Fortunately, Alun Jones found a faster (but still lame) way: just select each feed and it’ll refresh next time send/receive occurs. Hopefully MS will fix this.

Tuesday, August 04, 2009

Stonefield in the News Again

Grant Buckler of SoftwareCEO wrote an extensive article on Stonefield Software that was published today. It’s very well written and does a nice job of presenting business tips we’ve learned over the years.

Friday, July 24, 2009

Microsoft Virtual PC Video

I’m doing a session at Southwest Fox 2009 titled “Microsoft Virtual PC for VFP Developers.” VPC is one of the indispensible tools every developer ought to use (or if not VPC, one of its competitors such as VMWare), and yet many haven’t embraced it. Hopefully, this session will convince you to start using it immediately.

I created a short (5 minute) teaser video showing part of my session: how VPC is useful to test application installers to make sure all dependencies are included. Attendees of Southwest Fox will receive a complete white paper on installing, configuring, and using VPC. See you there!

Thursday, July 23, 2009

Stonefield in National News

The Financial Post, a national newspaper in Canada, reprinted the article from our local newspaper profiling Stonefield Software.

Monday, July 13, 2009

Stonefield in the News

Stonefield was featured in the Business section of Saturday's local paper. They got a few things wrong:

  • My title is actually Chief Technology Officer, not Chief Information Officer.
  • I wish our sales were $5 million per year!
  • We don't sell 220,000 units per year; we have 177,000 users in total.

Still, it's nice to get some PR.

Friday, June 26, 2009

Southwest Fox Super-Saver Deadline Approaching

June 30 is the deadline to save $125 and get a free half-day pre-conference session for Southwest Fox 2009. Registrations are already at last year’s numbers, so be sure to join us in sunny Arizona in October to hear the brightest VFP developers on the planet speak about our favorite development environment. See you there!

Register now



Racing Again

This past Saturday, the Regina YMCA once again held the event I look forward to all year: Echo Challenge. Our team, Thunder, competed in 2007 and 2008, and with three original members and three new ones, we were up to the challenge.

For the second year in a row, my Wednesday evening ride before Echo Challenge was marred by a bike crash. This time, it was on the cool-down part of my ride around beautiful Wascana Lake. As I came around a corner, a woman on another bike going the opposite direction was in my lane, coming right for me (she wanted to turn left but didn’t check for traffic first). We both tried to veer out of the way, but ended up side-swiping each other and down we went. My left wrist hit her bike, smashing my watch, spraining my wrist, and leaving a watch-shaped bruise. We both made sure the other was OK, and I continued on my way home. A couple of hours later, my right knee tightened up. By morning, I could barely walk because I could neither bend nor straighten my leg. Stretching and ice helped, but I figured Echo was no go this year, which really bummed me out. Fortunately, with lots of stretching, the knee loosened up a fair bit over the next couple of days, so I was able to ride after all.

Saturday started out cool and a little rainy, but by mid-morning, it was beautiful: about 24C (75F), cloudy, and some wind. I had a chance to meet our new team members, including our swimmer who’s only 12 (but a member of a local swim team).

The swim event was first: 750 m in the cold lake waters. That has to be the toughest leg, but Jamie did great, finishing in 13:34, good enough for 11th of 18 teams and almost nine minutes faster than last year’s swimmer. He tagged Lisa, our hill runner, who finished in 5:15 (placing her 10th) despite struggling with a sudden flare-up of asthma.

Here’s a photo of Nick and I waiting for the cycling leg to start. You can see the lake and the hills where the cycling route goes in the background.

Echo Challenge 2009 001

Lisa tagged me and off I went. Although my knee was a little stiff, I managed a speed of about 45 kph (28 mph) for the 1.5 km to the start of the hills. I passed seven other cyclists, all in their twenties, and went down the final hill at over 50 kph (31 mph). However, I was significantly slower than last year: this year’s cycling leg was longer, but my time over the hill part of the race was 21:11 vs. 16:29 last year. Part of it was the knee, part was a head-wind we didn’t have last year, but the major part was I wasn’t in as good shape as I was last year. Here’s a shot of me at a relatively flat part of the hill section:

Echo Challenge 2009 005

I ended up finishing 8th, which was pretty disappointing. However, there were a lot of new faces in the race this year, many of whom are serious athletes, and I was the second oldest cyclist, so I guess I shouldn’t feel too bad.

Here’s a shot of Nick and I at the end of the race:

Echo Challenge 2009 006

I tagged Bob, who finished the 7 km run in 34:30, 1:30 faster than last year, 16th of the 18. Finally, Mike and Adrian finished with the 1.6 km canoe event. Their time of 32:33 was two minutes faster than last year, putting them in 17th.

Overall, we finished 17th out of 18 teams, not as good as last year, but it’s for a good cause. Unfortunately, donations were down this year, but hopefully we can get more teams out next year and get donations back up again.

Congratulations to the YMCA staff and volunteers for putting on a well-organized and fun event once again. I’m already dreaming of next year’s event!

Friday, June 05, 2009

Free SnagIt 7 Today Only

As posted on Digital Inspiration (a blog I highly recommend), until 5 P.M. Eastern today (June 5, 2009) only, you can get a free copy of SnagIt 7 (which is a couple of versions old) from TechSmith. This is a cool offer if you don’t already own SnagIt, a tool I find indispensible for creating screen shots for documentation and other purposes.

Thursday, May 07, 2009

Stonefield Query 3.3 Video

We posted a 25-minute video showing some of the new features in Stonefield Query version 3.3.

Monday, May 04, 2009

Stonefield Query SDK Version 3.3 Released

We released version 3.3 of the Stonefield Query SDK today. Other versions, such as for Sage Accpac ERP, Sage Pro, ACT!, and so on will be released over the next few weeks; watch our blog for release information.

The list of new and enhanced features in version 3.3 is extensive; see the online versions of the end-user help and SDK help for complete details. Here are the major new features.

Report Designer

  • The new Formula Editor allows you to create your own formulas without using the Advanced Report Designer or customizing the data dictionary.
  • The new Show percentage of total option in the Format page of the Field Properties dialog automatically adds a new column to the report showing the percentage that the field is of the subtotal in detail lines, of the next level of grouping in subgroup footers, and of the grand total for group footers.
  • Turn on the new Show totals in group headers option in Step 5 of the Quick Report Wizard and the Options page of the Reports Explorer to display group totals in the group header rather than the group footer.
  • Stonefield Query now supports Crystal Reports reports. You can add them to Stonefield Query using the External Report Wizard.
  • The Preview window is no longer modal, meaning you can open multiple instances. Also, the new Preview reports in tabbed pages setting in the Options dialog allows you to determine whether different preview windows are used when you run more than one report or whether the reports appear as different tabs in the same preview window.
  • There are several new output options available. You can specify that a timestamp is added to the file created to prevent overwriting existing files, that the file emailed to someone shouldn't be deleted after the email is sent, and what filename to use for the emailed file.
  • Previous versions of Stonefield Query create a report as a PDF file when emailing the report to someone. You can now specify the type of file used as an attachment.
  • You can now specify that each group in a report should be output to a separate file or email and that the email address should come from a field in the report itself. This can be used, for example, to email invoices to customers; the report is grouped by customer name and includes the customer's email address, so each customer's records are emailed to them.
  • You can now sort fields in database order or alphabetical order in Step 2 of the report wizards.
  • You can now tell Stonefield Query to display in the Tables drop-down list only those tables related to tables already appearing in the selected list.
  • Reports are now stored as export files with an SFX extension in a folder structure that exactly matches the folders in the Reports Explorer.
  • The new Send summary queries to database engine setting in the Options dialog allows you to specify whether Stonefield Query or the database engine does data summarization. This may significantly improve the performance of certain types of reports.
  • The new Run report with no records option in Step 5 of the report wizards and the Options page in the Reports Explorer allows you to run a report when there are no records that match your conditions.


  • The data dictionary now supports versioning. This is useful if tables and fields were added to or removed from the database between versions and you have some users using an older version and some using a newer version but they're all using the latest version of your customized Stonefield Query. To prevent users from selecting tables and fields that may not exist in their version of the database, you can specify the version number for each table and field that doesn't exist in all versions.
  • Stonefield Query now supports scripting in VB.Net and C#.
  • Like us, you may have a blog or news feed describing changes to your application. However, most users don't read blogs. So, Stonefield Query now includes a built-in news reader. If you fill in the URL for News Feeds configuration setting with the URL for an RSS feed, the news reader is available to your users.
  • The Create Help Files function in the Configuration Utility now runs Stonefield Query and automates the generation of all customized screen shots, so there's no need to do that manually any more. That can save you a considerable amount of time.
  • You can now refresh a single database rather than all databases if you wish by selecting the Refresh Database function from the Objects or shortcut menus.
  • The new Number of Days for Demo Version configuration setting allows you to create a shorter demo period than the default 30 days if you wish.
  • The code window opened when you right-click the code for a script and choose Zoom now supports find capability. Right-click in the code window and choose Find from the shortcut menu. Also, when you choose Build Expression from the shortcut menu, the Stonefield Query Expression Builder is now used.
  • A new Test button in the database properties page of the Configuration Utility allows you to test that the connection settings are correct.

Friday, May 01, 2009

Southwest Fox Sessions and Speakers Announced

We announced the speaker and session lineup for Southwest Fox 2009 today. This year was the hardest yet selecting from the list of proposals because we had a record number of submissions. Once again, there are great topics such as using Visual Earth in VFP applications, implementing MySQL, getting the most out of FoxCharts, and adding full-text search to your applications.

Registration is now open, so be sure to sign up today for a fun three days in Phoenix in October. Take advantage of the “Southwest Fox Stimulus Plan”: if you register before July 1, you save $125 and get a free half-day pre-conference session, a $99 value. With sessions on Web development, source control, and refactoring legacy code, the hard part will be picking which one to attend.

We also offer an early-bird special: register before September 1 and save $50.

We're looking forward to seeing you in October!

Thursday, April 23, 2009

Stonefield Software Inks Australian Distribution Deal with Sage

Stonefield Software has signed a distribution deal with Sage Business Solutions to expand the distribution of our popular database reporting software, Stonefield Query, to the Australian, NZ and Pacific Island Market. The new agreement builds on our dramatic growth as the premier end-user focused database reporting software solution in the U.S. and Canada, and expands into the Australian and New Zealand region with a prospective market share of tens of thousands of Sage Software users.

For details, see our press release page or press release itself.

Monday, April 20, 2009

2009 Ceil Silver Ambassador

We are pleased to announce that César Chalom has been selected as the 2009 Ceil Silver Ambassador. He will attend Southwest Fox 2009 and represent the Brazilian VFP community.

César, a software developer from São Paulo, Brazil, has worked with Visual FoxPro since 2003, and is an active member of the Brazilian VFP community. He has attended the Brazilian VFP conference since 2004 and presented sessions at the conference in 2006 and 2008. He is well known to the global VFP community for his contributions to several VFPX community projects, including GDIPlusX and FoxCharts. His blog is an excellent source of technical material on GDIPlusX and other VFP topics.

We are very excited that César can attend Southwest Fox 2009 and know that many attendees are looking forward to meeting him in person.

Wednesday, April 01, 2009

Controlling DisplayCount in ComboBoxes

The DisplayCount property of the ComboBox class controls how many items the user sees when the ComboBox is dropped down. Normally this is a fixed value, so even though there may be plenty of room to display more items, the user can only see so many and has to scroll to see more.

I like to set DisplayCount dynamically based on how much room there is between the ComboBox's position and the bottom of the screen. I used the following code in the DropDown method of my base ComboBox class to handle this:

* Set DisplayCount to an appropriate value based on how much room there is
* below the form.

local lnHeight
lnHeight = iif(Thisform.ShowWindow = 2 or ;
(pemstatus(Thisform, 'Desktop', 5) and Thisform.Desktop), sysmetric(2), ;
This.DisplayCount = max(ceiling((lnHeight - Thisform.Top - ;
objtoclient(This, 1))/This.Height), 7)

Tuesday, March 31, 2009

Check Your Bank Statements!

Here's a cautionary tale about banks that happened to us recently:

Monday, March 16, 2009

Encrypting VFP Tables Using Advantage Database Server

J. D. Mullin blogged about a new video he posted showing how to encrypt VFP tables using Advantage Database Server (ADS). This is the latest in a series of videos on using ADS with VFP tables.

Thursday, March 12, 2009

Southwest Fox Session Proposals Due Next Week

Just a reminder that session proposals for Southwest Fox 2009 are due on Monday, March 16. We are always looking for new speakers, so if you have some interesting ideas, submit your proposals by Monday.

Thursday, March 05, 2009

Servoy Webinar for VFP Developers

Servoy is presenting a free Webinar discussing their product for VFP developers on March 26, 2009 at 10 am PST.

VFP DDEX Provider Updated

As Craig Berntson notes, Microsoft released an updated VFP DDEX Provider yesterday. The original, part of Sedna, had an expired license key so it wouldn't work if you installed it after March 2008. The new version is also a little easier to install, as there are fewer steps. I posted the new version of VFPX on the DDEX for VFP page.

Monday, March 02, 2009

Easier URL for VFPX

Sara Ford blogged Friday that all VFPX projects are now accessible using their name as a subdomain. This makes the URL for VFPX the nice and short

Replacement for SYS(2014)

SYS(2014) is a great little function that helps make your applications portable. Since it returns the relative path of a file to a specific folder, you can use it on an absolute file name (such as one returned from GETFILE()) and store the relative rather than absolute path.

However, one thing that's always bugged me about SYS(2014) is that it returns the path in upper-case. If you want to display the path to the user, they'll wonder why the path is upper-cased in your program but in a different case on disk.

Fortunately, there's a simple Windows API function you can call that does the same thing as SYS(2014) but respects the case. Here's an example of how to use that function:

(UPDATE: Walt Krzystek pointed out that GetRelativePath returned a blank string if the two paths are on different drives. Also, I neglected to trim trailing spaces from the return value.)

function GetRelativePath(tcTo, tcFrom)

#define MAX_PATH 260

declare integer PathRelativePathTo in shlwapi.dll ;
string @out, string @from, integer fromattrib, ;
string @to, integer toattrib
lcPath = space(MAX_PATH)
lcFrom = iif(vartype(tcFrom) = 'C', tcFrom, ;
sys(5) + curdir()) + chr(0)
lnFromAttrib = iif(directory(lcFrom), FILE_ATTRIBUTE_DIRECTORY, ;
lcTo = iif(vartype(tcTo) = 'C', tcTo, ;
sys(5) + curdir()) + chr(0)
lnToAttrib = iif(directory(lcTo), FILE_ATTRIBUTE_DIRECTORY, ;
PathRelativePathTo(@lcPath, @lcFrom, lnFromAttrib, @lcTo, lnToAttrib)
lcPath = alltrim(strtran(lcPath, chr(0), ' '))
if empty(lcPath)
lcPath = tcTo
endif empty(lcPath)
return lcPath

Sunday, March 01, 2009

Cleaning up _MemberData

The MemberData Editor, the replacement New Property/Method dialog, and the fantastic new PEM Editor all make it easy to get VFP to display the desired case for your custom properties and methods in IntelliSense and the Properties window rather than the lame lower-case it normally uses. The secret is _MemberData, a custom property added to a form or class that contains XML providing additional information about members, such as display case, whether they appear in the Favorites tab of the Properties window, and scripts to execute when you double-click properties in the Properties window.

One of the problems with _MemberData, though, is that it's limited to 8K. If you've ever worked with XML, you know it's very wordy and it doesn't take long to blow through the 8K limit. This is especially a problem with subclasses: not only do they contain the _MemberData XML for their own custom members, they also contain the XML for all parent class members. The deeper you go in a class hierarchy, the longer the XML gets and the closer you get to the 8K limit.

However, a little known fact about _MemberData is that it's cumulative: VFP internally combines the XML from the current class and all parent classes. Even if you blank _MemberData in a subclass, your members still display in the proper case. So, one way to keep that 8K limit at bay is to strip everything but the XML for the members added in the current class from _MemberData.

That would be a tedious chore to do manually. Fortunately, a couple of new features in version 4.0 of PEM Editor (currently in development) make this a breeze. The Cleanse MemberData function in the shortcut menu does this explicitly, but PEM Editor also does this automatically when you add a new member to a class.

If you can't wait for PEM Editor 4.0, I've uploaded a small PRG that does the same thing (in fact, it's the same code as in PEM Editor 4.0) to the Technical Papers page of the Stonefield Web site. To use it, open a class or form, then DO MDCleaner.PRG. Just to be safe, please back up your form or class first.

Tuesday, February 24, 2009

Southwest Fox Call for Speakers

Today we released the Call for Speakers for Southwest Fox 2009. Anyone interested in presenting should visit, read the Call for Speakers document, and download the proposal submission application. Session proposals are due by March 16.

We're adding a track this year called Technology for the VFP Developer. It'll cover things other than VFP that make life easier for FoxPro developers, like source control and virtual machines. Of course, we still plan to offer a good selection of topics in core VFP development, extending VFP, using VFP with other technologies, and of course, VFPX.

If you think you have something to say to the VFP community, please submit session proposals, even if you've never spoken at a conference before. Our community is strengthened when more people take an active role. Do be aware that speaking at a conference is a serious commitment. Even for experienced speakers, preparing a new session takes 40-80 hours. Doing it well at the conference calls for several rehearsals beforehand, too. So make sure you can commit the necessary time--the Call for Speakers lays out all the deadlines.

We're looking forward to seeing what you all come up with. Reading through the proposals we receive each year is really exciting, and choosing among them is always a challenge.

Tuesday, February 10, 2009

Using Tables Over 2GB in VFP

J.D. Mullin posted a video showing how to use Advantage Database Server to access DBF files that are over 2 GB in size, something you can't do if you access the table natively in VFP.

Friday, January 16, 2009

Playing with Windows 7

I've been playing with Windows 7 for about a week now. Like Andrew MacNeill, I installed it on a Virtual PC and also like Andrew, I got a BSOD when I tried to install Virtual Machine Additions (and in fact had to restore Windows 7 to a previous restore point to get it to work again). Fortunately, I remembered GIYF ("Google is your friend") and quickly found that Virtual PC SP1 was needed for Windows 7. After upgrading to SP1, I had no problems installing Virtual Machine Additions (which VPC can be a PITA to deal with if you don't).

I have a few other glitches right now, but they are all "Windows 7 on VPC" issues rather than Windows 7 issues:

  • No Aero Glass or related features (like the new Aero Peek). Come to think of it, I don't get Aero Glass when running Vista in a VPC either.
  • No sound.
  • Dragging a file from my main system to the VPC window gives an error. Copying a file from a shared folder on my main system to the VPC also has problems.

There are lots of cool things about Windows 7; Tim Sneath has blogged about some of them. The new taskbar and the concept of libraries will likely take some getting used to, but so far it feels like Vista with more fit-and-finish things taken care of.

Wednesday, January 14, 2009

PEM Editor is a Must-Have Tool

Jim Nelson has done a ton of work on the PEM Editor, the new name for the former Edit Property/Method replacement dialog project on VFPX that Marcia Akins originally created. He's made this into an incredible tool that I used about a hundred times a day. It completely replaces the native Edit Property/Method, New Property, and New Method dialogs, and in fact can even replace the Properties and Document View windows to some extent. Because it's modeless, resizable, and dockable, you never have to close it if you don't want to. Its customizable color coding and filtering abilities make working with forms and classes a lot easier. This is simply one of those must-have tools.

If you haven't already installed it, do yourself a favor and download it today. Installing it is as simple as DO PEMEditor.APP. From then on, you'll wonder what you ever did without it.


Changing the Color and Orientation of Images

Recently, I needed to change the color of an image. I have a container that includes an image and depending on the user's color choices, the container's background color might change. That means certain colors in the image must also change so the image blends in with the container properly, and rather than creating a number of images with pre-defined colors, I wanted to change the colors programmatically. One other wrinkle: because the orientation of the container might also change under some circumstances, I also wanted to rotate the image.

Fortunately, the VFPX GDIPlusX project makes this a snap and thanks to a recent blog posting by Cesar, it didn't take too long to figure out what to do. The following code reads the color of the upper left pixel in the image whose file name is in the lcImageFile variable and converts that color to the one specified in This.BackColor. It also rotates the image if it's wide and short but the container is narrow and tall. It then writes the new image directly to the PictureVal property of the imgImage object so there's no additional disk I/O.

* Create the GDIPlusX objects if necessary.

if type('_screen.System.Name') <> 'O'
do System.APP
endif type('_screen.System.Name') <> 'O'
with _screen.System.Drawing

* Load the image.

loBmp = .Bitmap.FromFile(lcImageFile)

* Get the color of the upper left pixel.

loColor = loBmp.GetPixel(0, 0)

* Create a color map and tell it to convert from the color of
* the pixel to our background color.

loColorMap = .Imaging.ColorMap.New()
loColorMap.OldColor = loColor
loColorMap.NewColor = .Color.FromRGB(This.BackColor)

* Create an attributes object and make it use the color map.

loAttr = .Imaging.ImageAttributes.New()

* Create a new image and draw the old image onto it using the new
* color mapping.

loDestBmp = .Bitmap.New(loBmp.Width, loBmp.Height, ;
loGfx = .Graphics.FromImage(loDestBmp)
loRect = loBmp.GetBounds()
loGfx.DrawImage(loBmp, loRect, loRect, .GraphicsUnit.Pixel, loAttr)

* Flip the image if its orientation doesn't match ours.

if This.Width > This.Height and loBmp.Height > loBmp.Width
endif This.Height > This.Width ...

* Write the image directly to the PictureVal property of our image
* object.

loDestBmp.Save(This.imgImage, .Imaging.ImageFormat.Bmp)