Foxite.COM Community Weblog

Foxite.COM Community Weblog - free weblog service for the Visual FoxPro Community.
Welcome to Foxite.COM Community Weblog Sign in | Join | Help
in
Home Blogs Forum Photos Forum Archives

Neil Tonkin



  • Adding UITypeEditors to Visual FoxPro

    Okay, so we not really going to host .NET in VFP but we can pinch some concepts from thier PropertyGrid.

     

    In my last entry we began to discuss the integration of the Extreme Property Grid ActiveX control into our FoxPro applications. I want to focus on supplementing the behaviour of the default data type support built into the grids fields. To recap, the following is typical of the code required to add a node and value to the control.

     

    #DEFINE xtpGridThemeDefault       0     

    #DEFINE xtpGridThemeNativeWinXP   1     

    #DEFINE xtpGridThemeOffice2003    2     

    #DEFINE xtpGridThemeCool          3     

    #DEFINE xtpGridThemeSimple        4     

    #DEFINE xtpGridThemeDelphi        5     

     

    #DEFINE PropertyItemString        0      && String Item

    #DEFINE PropertyItemNumber        1      && Number Item

    #DEFINE PropertyItemBool          2      && Bool Item

    #DEFINE PropertyItemColor         3      && Color Item

    #DEFINE PropertyItemFont          4      && Font Item

    #DEFINE PropertyItemDouble        5      && Double Item

    #DEFINE PropertyItemDate          6      && Date Item

    #DEFINE PropertyItemPicture       7      && Picture Item

     

    with ThisForm.olePropertyGrid

       *!* Display the toolbar.

       .ToolBarVisible = .T.

     

       *!* Display the help pane and set its initial size

       *!* in pixels.

       .HelpVisible = .T.

       .HelpHeight = 78

      

       *!* Set the grid splitter proportion as a percentage.

       .SplitterPos = 0.35

      

       *!* Set the visual theme.

       .VisualTheme = 0

     

       *!* Clear the categories collection.

       .Categories.Clear()

     

       *!* Add a new category and make sure it is expanded.

       loSection = .AddCategory("System Paths")

       loSection.Expanded = .T.

      

       *!* This is the desription that will appear in the

       *!* help pane.

       loSection.Description = "System paths test category"

     

       *!* Add a read-only string property called Driver with its value

       *!* taken from a field in the odbcconnections table.

       loPropertyItem = loSection.AddChildItem(PropertyItemString, ;

                                               "System Files",     ;

                                               "c:\systemfiles\")

      

       loPropertyItem.Tag = 1000

     

       *!* This is the description that will appear in the

       *!* help pane.

       loPropertyItem.Description = "Select a new path."

    endwith

     

    Okay, so we have the ability to manually enter a path and by assigning a unique integer tag to the node we can validate its contents in the ValueChanged event.

     

    Now wouldn’t it be better to supplement this behaviour with some form of UI asset that allows us to invoke a directory selector. Well the Property Grid control allows us to do this by assigning one of the following PropertyItemFlags to the node:-

     

    #DEFINE ItemHasEdit               1      && Item has an edit control

    #DEFINE ItemHasExpandButton 2      && Item has an expand button

    #DEFINE ItemHasComboButton        4      && Item has a combo button

     

    We want to add an expand button to the property grid node, this will give us a small button that displays three ellipses which can be used to display our custom dialog for directory selection.

     

    Add the following code to your node creation process remember to include the three flag definitions above.

     

    loPropertyItem.Flags = ItemHasExpandButton

     

    When you run the form you should be presented with something that looks like the following gallery image.

     

    http://weblogs.foxite.com/neiltonkin/gallery/image/22.aspx

     

    If you press the expand button you will see that it doesn’t really do anything, this is because we need to inject some code to respond to the InplaceButtonDown event.

     

    *** ActiveX Control Event ***

    LPARAMETERS item

     

    LOCAL lcNewPath

     

    lcNewPath = ""

     

    if item.Tag = 1000

       lcNewPath = getdir("c:\", "New Path", "Select a new path", 64)

          

       if NOT empty(lcNewPath)

          item.Value = lcNewPath

       endif

    endif

     

    Once again you can see we use the nodes Tag property to identify the source of the button press and then by using FoxPro’s getdir() function we allow the user to visually select a new path.

     

    You are not limited to the built in FoxPro functions, you can create your own dialogs for editing any type of information in any way you see fit. This gives you similar functionality to Visual Studio which supports more complex data type enumeration and selection through its UITypeEditor classes. For example, you could build an equivalent to Visual Studio’s RegexTypeEditor so that the end-user can select how their postcodes are masked and validated.

     

  • Introduction to the VFP PropertyGrid

    One of the nice things about Visual Studio .NET is that with each release we get more and more great user interface components, and what’s even better is that with .NET you can use most of these directly in your applications. Take the PropertyGrid control, this provides a user interface for browsing the properties of an object and is used everywhere in Visual Studio by Microsoft which is a tribute to its out-of-the-box functionality. Now we all know that Visual FoxPro is a great product but it does tend to get left behind in the user-interface assets department which can be a bit frustrating. Even with VFP 9 which includes some fantastic enhancements such as dockable forms, control anchoring etc. it still requires some assistance to give it the latest-greatest look.

     

    If we go back to the .NET PropertyGrid example I am sure there are dozens of instances you can think of where this control would have solved lots of problems in your FoxPro user interfaces. By design the control is hierarchical, sharing a lot of common ground with the classic Win32 TreeView, the PropertyGrid takes that one step further by allowing you to categorise your data in a hierarchy or show it flattened and sorted. Data entry can be controlled through pre-defined selection lists or by the use of more specialised popup editors such as a directory browser or font selector. So how can we bring this control to our VFP applications? Well there are still a lot of component vendors out there writing high quality ActiveX components which integrate well into Visual FoxPro, one such vendor is CodeJock Software who offer the reasonably priced Xtreme Property Grid that can be incorporated directly into your FoxPro applications.

     

    http://www.codejock.com/products/propertygrid/activex/

     

    All the Fox diehards will be happy to see Visual FoxPro listed on there and they even provide a Visual FoxPro example for educational purposes. Using the component is easy and if you have ever done any work with the TreeView ActiveX then this will be very familiar territory. The client area of the component contains 3 key elements.

     

    1. Toolbar
    2. Hierarchical Grid
    3. Help Pane

     

    If you go over to the gallery portion of this blog you can see a screen shot of one of our Microsoft Navision utilities with a pre-loaded instance of the property grid control.

     

    http://weblogs.foxite.com/neiltonkin/gallery/image/18.aspx

     

    The Toolbar contains two buttons that when clicked will change between the two views; this can be toggled on or off using the ToolBarVisible property. When setting up the remainder of the control there are a number of key tasks you need to do including setting the height of the help pane in pixels and also the ratio of the split in the grid between node prompts and the associated data.

     

    with ThisForm.olePropertyGrid

       *!* Display the toolbar.

       .ToolBarVisible = .T.

     

       *!* Display the help pane and set its initial size

       *!* in pixels.

       .HelpVisible = .T.

       .HelpHeight = 78

      

       *!* Set the grid splitter proportion as a percentage.

       .SplitterPos = 0.35

      

       *!* Set the visual theme.

       .VisualTheme = 0

    endwith

     

     

    The control also allows you to select one or more Visual Styles or Themes by setting the VisualTheme property to one of the following enumerations.

     

    #DEFINE xtpGridThemeDefault       0     

    #DEFINE xtpGridThemeNativeWinXP   1     

    #DEFINE xtpGridThemeOffice2003    2     

    #DEFINE xtpGridThemeCool          3     

    #DEFINE xtpGridThemeSimple        4     

    #DEFINE xtpGridThemeDelphi        5     

     

    A good tip for getting these values from the type library is to use the Object Browser that comes with Visual FoxPro. Load the OCX control into the Browser and expand the Enums node then drag and drop the desired enumeration (in our case the XTPPropertyGridVisualTheme node) into the command window or any code editor will produce the definitions above.

     

    Loading the control is quite straight forward; you need to work out in advance the categories for your properties or drive its construction from data – it’s entirely up to you.

     

    with ThisForm.oleProperties

       *!* Clear the categories collection.

       .Categories.Clear()

     

       *!* Add a new category and make sure it is expanded.

       loSection = .AddCategory("(Identity)")

       loSection.Expanded = .T.

      

       *!* This is the desription that will appear in the

       *!* help pane.

       loSection.Description = "Connection Type"

    endwith

     

    Before you can add properties to our new section through the loSection reference you must get the PropertyItemType enumeration from the type library, this is used to define the type of data that will be maintained and can be one of the following.

     

    #DEFINE PropertyItemString        0      && String Item

    #DEFINE PropertyItemNumber        1      && Number Item

    #DEFINE PropertyItemBool          2      && Bool Item

    #DEFINE PropertyItemColor         3      && Color Item

    #DEFINE PropertyItemFont          4      && Font Item

    #DEFINE PropertyItemDouble        5      && Double Item

    #DEFINE PropertyItemDate          6      && Date Item

    #DEFINE PropertyItemPicture       7      && Picture Item

     

    As you can see there is default support for the most common types including complex data types such as pictures/images.

     

    with ThisForm.olePropertyGrid

       *!* Add a read-only string property called Driver with its value

       *!* taken from a field in the odbcconnections table.

       loPropertyItem = loSection.AddChildItem(PropertyItemString, ;

                                               "Driver",           ;

                                               alltrim(odbcconnections.driver))

       loPropertyItem.ReadOnly = .T.

      

       *!* This is the description that will appear in the

       *!* help pane.

       loPropertyItem.Description = "The ODBC driver used as the " + ;

                                    "basis for the connection."

    endwith

     

    Now the cool thing about the PropertyGrid controls object hierarchy is that once we have a reference to our new property we can call its AddChildItem method to add a sub/child property in a hierarchical fashion beneath it in exactly the same manner as above.

     

    http://weblogs.foxite.com/neiltonkin/gallery/image/20.aspx

     

    In the previous example we made our property read-only but more often than not you will need to know when a user has changed a value of one or more of your properties. To do this you need to assign a tag to your property item and then place code in the controls ValueChanged event. The Tag property is not like the one exposed by the TreeView, it’s a long/numeric value not a string which if you did what I initially did which is NOT to RTFM then you get errors.

     

    loPropertyItem.Tag = 1000

     

    Now put some code into the ValueChanged event to handle the user changing the property content.

     

    *** ActiveX Control Event ***

    LPARAMETERS item

     

    if item.Tag = 1000

       MessageBox(item.Value)

    endif

     

    One of the things that can happen when loading a lot of information into the grid is flickering of the scroll bar. We can stop this happening using an old trick involving the LockWindowUpdate Platform API function.

     

    declare short LockWindowUpdate in WIN32API integer hWnd

    = LockWindowUpdate(ThisForm. olePropertyGrid.hWnd)

     

    Calling this before you start loading the control with properties can stop this annoying update artefact but remember to issue the corresponding unlock or your control will not update itself.

     

    = LockWindowUpdate(0)

     

    Hopefully this will help you with the basics of this control; in my next entry I will show you how to define your own editors for tasks like directory selection.

     

This Blog

Post Calendar

<January 2009>
SuMoTuWeThFrSa
28293031123
45678910
11121314151617
18192021222324
25262728293031
1234567

Archives

Syndication