Monthly Archives: July 2019

Coloring your tabs with the ITEMSTYLE property

A new facility introduced in version 10 is the ability to set the styling information for the tabs in the TabControl using the new ITEMSTYLE and ITEMSTYLES properties, and in this post we’ll explain how to use them.

TabStates and ItemStyles

Each tab in a TabControl can be in one of the following states at runtime:

  • Normal (Unselected tab)
  • Hot (Mouse is over a Normal tab)
  • Disabled
  • Selected
  • Hot Selected (Mouse is over the selected tab)

And for each one of these states you can specify the following styling information for the tabs:

  • ForeColor
  • BackColorFrom
  • BackColorTo
  • Bold
  • Italic
  • Underline
  • Translucency
  • CloseButton ForeColor
  • CloseButton BackColor

To do this at run-time you can use one of the following properties:

  • The ITEMSTYLE property
  • The ITEMSTYLES property

and we’ll take a look at each of these in turn.

 

The ITEMSTYLE property

   prevStyle = Get_Property( ctrlEntID, "ITEMSTYLE", itemState )
   currStyle = Set_Property( ctrlEntID, "ITEMSTYLE", newStyle, itemState )

This property allows you to get or set the ITEMSTYLE for a single state.  The property itself is an @fm-delimited array of styling information like so:

    <1> ForeColor             (COLORREF)
    <2> BackColor From        (COLORREF)
    <3> BackColor To          (COLORREF)
    <4> Bold                  (1/0)
    <5> Italic                (1/0)
    <6> Underline             (1/0)
    <7> Translucency          (0-100)
    <8> CloseButton ForeColor (COLORREF)
    <9> CloseButton BackColor (COLORREF)

Equates for these array positions can be found in the PS_TABCONTROL_EQUATES insert record:

   equ TCIS_POS_FORECOLOR$           to 1 ; * // COLORREF
   equ TCIS_POS_BACKCOLOR_FROM$      to 2 ; * // COLORREF
   equ TCIS_POS_BACKCOLOR_TO$        to 3 ; * // COLORREF
   equ TCIS_POS_BOLD$                to 4 ; * // Boolean
   equ TCIS_POS_ITALIC$              to 5 ; * // Boolean
   equ TCIS_POS_UNDERLINE$           to 6 ; * // Boolean
   equ TCIS_POS_TRANSLUCENCY$        to 7 ; * // UInt (0-100)
   equ TCIS_POS_CLOSEBTNFORECOLOR$   to 8 ; * // COLORREF
   equ TCIS_POS_CLOSEBTNBACKCOLOR$   to 9 ; * // COLORREF

You must also use the index parameter with the Get_Property and Set_Property to specify the tab state that you are setting, which is an integer between 1 and 5:

   equ TCIS_NORMAL$                   to 1
   equ TCIS_HOT$                      to 2
   equ TCIS_DISABLED$                 to 3
   equ TCIS_SELECTED$                 to 4
   equ TCIS_HOTSELECTED$              to 5

Example: Setting the Hot and Hot Selected styles

   $insert colors
   $insert logical

   // Set the mouseover text to change to red 
   itemStyle = ""
   itemStyle<TCIS_POS_FORECOLOR$> = RED$
   
   Call Set_Property_Only( ctrlEntID, "ITEMSTYLE", |
                           itemStyle,              |
                           TCIS_HOT$ )

   // Set the mouseover text for a selected item to change to red
   // and bold
   itemStyle = ""
   itemStyle<TCIS_POS_FORECOLOR$> = RED$
   itemStyle<TCIS_POS_BOLD$>      = TRUE$
   
   Call Set_Property_Only( ctrlEntID, "ITEMSTYLE", |
                           itemStyle,              |
                           TCIS_HOTSELECTED$ )

 

The ITEMSTYLES property

   prevStyles = Get_Property( ctrlEntID, "ITEMSTYLES" ) 
   currStyles = Set_Property( ctrlEntID, "ITEMSTYLES", newStyles )

This property is very similar to the ITEMSTYLE property except that it allows you to get or set the styles for all states at once.

The property itself is an @fm/@vm delimited array: each state is delimited by @fm, and the styling information for each state is delimited by @vm.

   <1> ItemStyle for the Normal State
   <2> ItemStyle for the Hot State
   <3> ItemStyle for the Disabled State
   <4> ItemStyle for the Selected State
   <5> ItemStyle for the Hot Selected State

(You will note these map onto the “TCIS_” state equates shown above)

For each one of these states the ItemStyle information is an @vm delimited array using the same structure as for the ITEMSTYLE property, i.e:

   <0,1> ForeColor             (COLORREF)
   <0,2> BackColor From        (COLORREF) 
   <0,3> BackColor To          (COLORREF) 
   <0,4> Bold                  (1/0) 
   <0,5> Italic                (1/0) 
   <0,6> Underline             (1/0) 
   <0,7> Translucency          (0-100) 
   <0,8> CloseButton ForeColor (COLORREF) 
   <0,9> CloseButton BackColor (COLORREF)

So you can use the “TCIS_POS_” equates shown above as well.

Example: Setting the Hot and Hot Selected styles using ITEMSTYLES

   $insert colors
   $insert logical

   itemStyles = Get_Property( ctrlEntID, "ITEMSTYLES" )

   // Set the mouseover text to change to red 
   itemStyles<TCIS_HOT$, TCIS_POS_FORECOLOR$> = RED$
   
   // Set the mouseover text for a selected item to change to red 
   // and bold
   itemStyles<TCIS_HOTSELECTED$,TCIS_POS_FORECOLOR$> = RED$
   itemStyles<TCIS_HOTSELECTED$,TCIS_POS_BOLD$>      = TRUE$
   
   Call Set_Property_Only( ctrlEntID, "ITEMSTYLES", itemStyles )

 

Setting ItemStyles in the Form Designer

Item styling for the tab control can also be specified at design time by using the “ItemStyles” property that is available when you select the tab control in the form designer.  When you click the button for this property you will see an ItemStyles editor dialog that lets you specify the styling information:

TabControl ItemStyles Editor

(Note that in the current release (10.0.6) you will not see this applied to the design control – this will be fixed in an upcoming release)

Tracking the SAVEWARN property

As veteran OpenInsight programmers know, the system uses a simple boolean flag (exposed as the SAVEWARN property) to determine if the contents of a data-bound form have changed.  This flag can be updated in several ways, the most common being:

  • From the LOSTFOCUS event of a control.
  • From the POSCHANGED, INSERTROW and DELETEROW events of an EDITTABLE control.
  • From setting a control’s DEFPROP property.
  • From the CLOSE event of a form when the control with focus is inspected to see if it has changed.

It is checked during the CLEAR and CLOSE events to see if it has been set and an “Unsaved Changes” warning issued to the user if so.  Most of the time this system works quite well, but (as anyone who has spent several years working with OI systems knows) sometimes it gets triggered when you least expect it, and you’re left with no clue as to why.

To help with this situation the next version of OpenInsight introduces SAVEWARN tracking, so you can see which parts of the system update the SAVEWARN property and when they actually do it. In previous versions the system updated the SAVEWARN flag directly (it’s a simple variable in the “window common area”) but this has been changed to use the Set_Property function so it can be monitored effectively from a single point.

To track SAVEWARN you have two choices:

  • Use the SYSMSG event
  • Use the System Monitor

 

Using the SYSMSG event to track SAVEWARN

Every time SAVEWARN is set a standard SYSMSG event is raised with a SAVEWARNINFO code; the system itself does nothing with this message, but it’s there for you to use if you wish.  This option is probably more suited for run-time tracing as it’s something you could add to your applications easily if you needed to.

The PS_EQUATES insert record defines the SAVEWARNINFO message number that you can intercept:

equ SYSMSG_SAVEWARNINFO$ to 21  ; // Save warn has been changed - null msg

The Auxiliary parameter passed to the  SYSMSG event contains information that describes why the SAVEWARN property was changed.

 

Using the System Monitor to track SAVEWARN

The SetDebugger() function has been updated to support a new method called “SAVEWARN” that enables SAVEWARN tracking so that changes are displayed in the System Monitor.  This option is probably more suited to development use rather than run-time.

From the System Monitor execute:

setdebugger savewarn 1

to turn on tracing, and:

setdebugger savewarn 0

to turn it off.

E.g:

SAVEWARN tracing in the System Monitor

SAVEWARN tracing in the System Monitor

Setting the SAVEWARN property

If you wish to set SAVEWARN yourself you may use the “index” parameter to pass a description for the change, so this can be picked up in any tracing scenario like so:

Call Set_Property_Only( @Window, "SAVEWARN", TRUE$, "From My Stuff" )

This description is then passed in the Auxiliary parameter of the  SYSMSG event as noted above.

 

Hopefully you will find this facility useful if you ever suffer from problems with SAVEWARN in the future.