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.

No comments: