Tag Archives: Properties

OpenInsight and High-DPI

With the increasing popularity of high-resolution monitors, one of the biggest usability problems today is the display size of text and UI controls, because they appear smaller as the screen resolution increases. The recommended advice to overcome this is to increase the DPI (dots-per-inch) setting of the system, thereby enlarging these elements and making them easier to see and read. If you’ve been using Windows Vista and above you’ve probably already seen this Control Panel applet that allows you to easily change your DPI settings:

DPI Control Panel Applet

Windows 7 DPI Control Panel Applet

However, unless an application is designed to be DPI-aware this can result in some unsatisfactory results, such as over-large fonts, clipped controls and blurry windows. This is because many older Windows applications assume a constant DPI (96) when setting font and size coordinates and they do not apply any scaling to these values, thereby resulting in the aforementioned problems.

(NB. The “magic number” of 96 that you’ll see throughout this post is due to the fact that at 96 DPI one logical pixel is equal to one screen pixel – this is the “100%” setting in the Control Panel applet shown above).

In an effort to accommodate these applications Microsoft have introduced a couple of OS features over the years:

  • On Windows XP the system fonts and some system UI elements are scaled up at runtime, but this leads to the common problem of text appearing larger and being clipped as the actual size of the bounding control is usually not scaled.
  • On Windows Vista and above a feature called “DPI-virtualization” automatically scales windows belonging to an application not marked as “DPI-aware” – in effect they are rendered at 96 DPI to an off-screen bitmap, resized, and then drawn to the screen, but this can result in some blurry windows due to pixel stretching.  OpenInsight 10 is marked as a DPI-aware application so will not be subjected to DPI-virtualization.

OpenInsight 10, High-DPI and automatic scaling.

OpenInsight 10 supports High-DPI by automatically scaling-up all GUI objects at runtime when created through the SYSTEM object’s CREATE method (formerly known as the “Utility CREATE service”). This affects the following two properties:

  • Size coordinates
  • Fonts

The actual scaling for coordinates is calculated by the following simple formula:

screenPixels = logicalPixels * ( currentDPI / 96 )

For example, if you create a control with a size of 200×100 and you are running at 144 DPI (i.e. 150% as per the Control Panel applet above) then the control will be created with an actual size of 300×150 pixels.

The font point size is similarly multiplied by the scaling factor (i.e. currentDPI / 96 ).

Supporting images under High-DPI

Another noticeable issue when running at high DPI settings are images, which are assumed to have been designed for 96 DPI and therefore have to be scaled up at runtime leading to a potential loss of quality due to the resize.  To help with this the tool-set has been extended to allow repository BITMAP entities to specify multiple image files when being defined. The first will be used for 96 DPI (100%), the second for up to 120 DPI (125%), the third for up to 144 DPI (150%) the fourth for up to 192 DPI (200%) and so on, with further images being defined at 48 DPI (50%) increments (for future-proofing). When a control is created at runtime the system picks the appropriate image size and scales it as needed (preferably down where possible) before applying any other transformations.

Note that this does NOT apply to images set at runtime in code via the BITMAP property.  In this case the developer is assumed to have selected the correct image file size regardless of the DPI setting.

Designing under High-DPI

If you design your forms when running under a High-DPI setting the Form Designer will save and compile all coordinate and font information as though you were developing at 96DPI, so the values will be scaled down appropriately.

Opting out of automatic scaling

Of course, we always try our best not to break existing applications so you can set an option in the RXI file to turn off the automatic DPI scaling if you wish (this option is exposed at runtime via the read-only SYSTEM DPISCALING property).

This same principle can also be applied to individual windows at design-time so you can use it selectively as needed (WINDOW objects also support the read-only DPISCALING property).

Further reading

If you want to find out more information on this topic please see the following link to Microsoft’s documentation on MSDN:

Writing High-DPI Win32 Applications

(Disclaimer: This article is based on preliminary information and may be subject to change in the final release version of OpenInsight 10).

The System Monitor – Part II

In a previous post we looked at some the enhancements to the version 10 System Monitor to make it a more user-friendly tool.  However, one of the features we didn’t mention was the addition of a Basic+ property API so you can interact with it from your own programs and tools if you wish.  This API is exposed via the new SYSTEMMONITOR object, which supports the following properties:

  • HANDLE
  • RESULTS
  • SIZE
  • TEXT
  • VISIBLE

And the following method:

  • RUN

HANDLE property

This property returns the window handle (HWND) of the System Monitor window.

RESULTS property

This property returns the contents of the results edit box in the System Monitor.

SIZE property

This property gets and sets the size and position of the System Monitor window.  It has the same format as the normal OpenInsight WINDOW SIZE property.

TEXT property

This property gets and sets the caption text of the System Monitor window.

VISIBLE property

This property gets and sets the visibility of the System Monitor window.  It has the same format as the normal OpenInsight WINDOW VISIBLE property

RUN method

This method executes a system monitor command.

(Disclaimer: This article is based on preliminary information and may be subject to change in the final release version of OpenInsight 10).

The Image API

[NOTE: The information in this post has been superseded by the actual release version of OpenInsight 10, and developers should refer to the Image Object API documentation as found on the Documentation page of this site for more details]

As promised in our last post this time we’re going to cover the new properties we’ve added to the Presentation Server to support the enhanced image capability:

  • IMAGEALIGN
  • IMAGECOLORKEY
  • IMAGEFRAMECOUNT
  • IMAGEFRAMENUMBER
  • IMAGESIZE
  • IMAGESTYLE
  • IMAGETRANSLUCENCY

We have also added the following new method:

  • SETIMAGE

IMAGEALIGN property

This property specifies how a clipped or scaled image is aligned within a client area.  It can be one of the following values:

  • “0” Top-Left
  • “1” Top-Center
  • “2” Top-Right
  • “3” Middle-Left
  • “4” Centered
  • “5” Middle-Right
  • “6” Bottom-Left
  • “7” Bottom-Center
  • “8” Bottom-Right

Examples:

IMAGEALIGN 4 (Centered)

IMAGEALIGN 6 (Bottom-Left)

IMAGEALIGN 6 (Bottom-Left)

IMAGESTYLE property

This property specifies how the image is rendered onto the window’s client area.  The following property values are supported:

  • “0” Clip – the image is not resized and is simply rendered onto the client area according to the IMAGEALIGN property (Note that the IMAGEORIGIN property will override the image alignment).
  • “1” Stretch – the image is resized to cover the entire client area of the window.
  • “2” Tile – the image is tiled across the entire client area.
  • “3” Scale – the image is resized but it’s proportions are kept constant: e.g. if the image is taller than it is wide the image height will be resized to the height of the client area, and it’s width scaled to keep the same proportions.  It will also respect the IMAGEALIGN property.

Examples:

IMAGESTYLE 1 (Tiled)

IMAGESTYLE 1 (Tiled)

IMAGESTYLE 2 (Stretched)

IMAGESTYLE 2 (Stretched)

IMAGESTYLE 3 (Scaled), IMAGEALIGN 5 (Center-Right)

IMAGESTYLE 3 (Scaled), IMAGEALIGN 5 (Center-Right)

IMAGECOLORKEY property

This property specifies the color to use as the transparent color when rendering the image as described in this post.  It basically replaces the current (and undocumented) IMAGETRANSPARENT and TRANSPARENTCOLOR properties, both of which have been deprecated with this release.

This property should be a valid RGB color value or one of the following special values:

  • “-1” Use the color of the top left pixel as the color-key.
  • “-2” Use the color of the top-right pixel as the color-key.
  • “-3” Use the color of the bottom-left pixel as the color-key.
  • “-4” Use the color of the bottom-right pixel as the color-key.
  • “-5” Do not use any color-keying.

IMAGEFRAMECOUNT property

Some image formats such a GIF and TIFF files can contain more than one image, held in series of frames.  This read-only property returns the number of frames in the image file.  Note that this is not the same as the IMAGECOUNT property, which applies to a single frame only.

Example:

Animated GIF with 12 frames

Animated GIF with 12 frames

IMAGEFRAMENUMBER property

This property gets or sets the current display frame for the image and could be used with a TIMER event to display an animated GIF file for example.  Note that this property is not the same as the IMAGENUMBER property which applies to a single frame only.

Examples:

Animated GIF with IMAGEFRAMENUMBER of 2

Animated GIF with IMAGEFRAMENUMBER of 2

Animated GIF with IMAGEFRAMENUMBER of 10

Animated GIF with IMAGEFRAMENUMBER of 10

IMAGESIZE property

This read-only property returns a dynamic array containing the size of the image in pixels:

<1> Width
<2> Height

Note that for a multi-frame image format it returns the size of a single frame, not all the frames combined.

IMAGETRANSLUCENCY property

This property specifies the transparency of the entire image as it is rendered onto the window. It is based on simple percentage amount, “0″ being fully opaque and “100″ being fully transparent (and therefore not visible).

Example:

IMAGETRANSLUCENCY of 70 with IMAGEORIGIN of 90,60

IMAGETRANSLUCENCY of 70 with IMAGEORIGIN of 90,60

SETIMAGE method

This method supersedes the existing IMAGE property and allows a image to be set by passing the raw image data rather than by passing a file or resource name as per the BITMAP property.  The OpenInsight property interface is text-based and does not support passing binary data with embedded null characters, whereas the method interface does, hence the reason for this change.

Other image-related properties

The following current image-related properties remain the same:

  • BITMAP
  • IMAGECOUNT
  • IMAGENUMBER
  • IMAGEOFFSET
  • IMAGEORIGIN

Deprecated properties

The following properties have been deprecated or removed in OpenInsight 10:

  • IMAGE – this property has been superseded by the SETIMAGE method.  It is now a synonym for the BITMAP property.
  • IMAGECLIP – this property has been superseded by the IMAGESTYLE property.
  • IMAGETRANSPARENT – this property has been superseded by the IMAGECOLORKEY property.
  • TRANSPARENTCOLOR – this property has been superseded by the IMAGECOLORKEY property.

(Disclaimer: This article is based on preliminary information and may be subject to change in the final release version of OpenInsight 10).

Subject to change…

Those of you reading to the end of the posts in this blog may have noticed a small disclaimer we put at the bottom of each article explaining that things might change between now and the final release.  This post is just a small example of that in action as we’ve recently renamed a couple of properties in the interests of clarity and usability:

  • The WINDOW TRANSPARENCY property has been renamed to TRANSLUCENCY
  • The WINDOW APPUSERMODELID property has been renamed to TASKBARID (along with it’s switch in the RXI file)

More news as it happens …

(Disclaimer: This article is based on preliminary information and may be subject to change in the final release version of OpenInsight 10).

Taskbar Integration – The TASKBARID property

In a previous post on the RXI files we mentioned the taskBarID switch that could be applied when launching the Presentation Server to un-group instances of the same executable on the Windows Taskbar.  This same principle can also be applied to top-level application windows so they can have their own icon on the taskbar rather than being grouped together with other application windows owned by the same instance.

To support this feature OpenInsight 10 provides a new WINDOW property called TASKBARID, which should contains a unique value that differentiates the window from other windows running on the desktop.

For example, a fairly easy way to set a unique value would be to combine the window ID and handle like so:

taskBarID = @window : "." : get_Property( @window, "HANDLE" )
call set_Property( @window, "TASKBARID", taskBarID )

Here is an example of a window with a blank TASKBAR property – notice that it is grouped with the System Monitor window as they both belong to the same instance of OpenInsight:

TASKBARID not set

TASKBARID not set

Here is the same window with the TASKBARID set to “TEST” – the OpenInsight 10 window icon is now visible on the TaskBar:

TASKBARID set to “TEST”

TASKBARID set to “TEST”

Note that you can also give multiple windows the same TASKBARID if you wish to control how they are grouped together.

[Edit: 01 Feb 13 – property renamed to TASKBARID]

(Disclaimer: This article is based on preliminary information and may be subject to change in the final release version of OpenInsight 10).

Special FX – The SHOW and HIDE methods

These two new methods allow you to show or hide a form along with a simple fading or sliding animation.  Each method takes a single parameter which specifies the type of animation to apply:

Effect Value Description
-1 or null Use the default effect value as set in the Form Designer
0 No effect
1 Fade Effect (cannot be used with MDI Child forms)
2 Slide Down
3 Slide Up
4 Slide Right
5 Slide Left
6 Slide Down and Right
7 Slide Down and Left
8 Slide Up and Right
9 Slide Up and Left

E.g. For a “pop-up toast” style notification dialog you could use the following effects:

exec_Method( @window, "SHOW", 3 ); Slide open from bottom to top
exec_Method( @window, "HIDE", 2 ); Slide closed from top to bottom

[Edit: 24 Apr 13 – Call_Method renamed to Exec_Method]

(Disclaimer: This article is based on preliminary information and may be subject to change in the final release version of OpenInsight 10).

 

Special FX – The TRANSLUCENCY property

This new property applies to all top-level windows and dialog boxes (but not MDI child windows) and allows you to set the translucency of a form based on a simple percentage amount, “0” being fully opaque and “100” being fully transparent.

Form with TRANSLUCENCY of 20

Form with TRANSLUCENCY of 20

Form with a TRANSLUCENCY of 50

Form with a TRANSLUCENCY of 50

FORM with a TRANSLUCENCY of 80

FORM with a TRANSLUCENCY of 80

Check out the excellent PAINT.NET application for a good example of using this effect where supporting modeless dialog boxes are rendered translucent when not active.

[Edit: 01 Feb 13 – property renamed to TRANSLUCENCY from TRANSPARENCY]

(Disclaimer: This article is based on preliminary information and may be subject to change in the final release version of OpenInsight 10).

Special FX – Aero Glass

One of the new capabilities added to OpenInsight 10 forms is Aero Glass support, a feature that Microsoft introduced with Windows Vista and unfortunately removed in Windows 8 (in the interests of disclosure your author is not a great fan of the “improvements” to the desktop in Windows 8). Still, Windows 7 remains extremely popular and will be around for many years to come so it makes sense to provide an Aero Glass interface for developers who wish to use it.

Aero Glass is exposed via the following properties:

  • GLASSMARGINS
  • GLASSFRAME
  • GLASSDRAG

The GLASSMARGINS property

This property is a simple @fm-delimited dynamic array of margin values that specify the areas on the form that should be rendered using the glass effect.  Basically everything between the edge of a form and it’s appropriate margin value is rendered as glass.

<1> Left Margin
<2> Right Margin
<3> Top Margin
<4> Bottom Margin

RevX_Aero_Glass

Note that setting the margins to “-1” forces the entire client area of the form to be rendered as glass instead.

RevX_Aero_Glass_Sheet

The GLASSFRAME property

This is a boolean property (1/0) that enables or disables the Aero Glass effect for a form.  The GLASSMARGINS property must have been set before this property can be used to enable glass rendering.

The GLASSDRAG property

This is a boolean property (1/0) that specifies if the glass areas of a form can be used for dragging (normally only the form caption area can be used for this).

What happens when Aero Glass is not available?

Of course it’s entirely possible that your application may have to run in an environment where Aero Glass is not available, such as running under the Aero Basic theme or on Windows XP.  In these circumstances the OS would “give up” and your form would be rendered with a normal client area like so:

RevX_Aero_No_Glass

As you can see there’s no hint of the glass margins, so this will probably make your glass-based UI layout unsatisfactory.  In this case we’ve gone one step further and implemented a “Fake Glass” effect (much like Windows Explorer does under Aero Basic):

RevX_Aero_Fake_Glass

Fake Glass under Aero Basic

Fake Glass under Windows XP

Fake Glass under Windows XP

Of course, as Microsoft removed Aero Glass in Windows 8 they actually supply their own replacement, which simply paints the solid frame colors into the “glass” margins like so:

Win8_Glass

Fake Glass under Windows 8

(Disclaimer: This article is based on preliminary information and may be subject to change in the final release version of OpenInsight 10).

The Reflection API

From a tool-developers point of view one of the weaker areas in the Presentation Server has always been the lack of a “reflection API”, i.e. a way to discover what properties, methods and events an object actually supports at runtime.  This in turn has led to creating manual lists and records of object attributes, bringing with it with the inherent difficulty of keeping this information up-to-date as new features are added.

Primarily designed with the new PS-based Form Designer in mind, this shortcoming has been addressed in version 10 with the addition of the following new methods to the SYSTEM object:

  • REFLECTPROPERTIES
  • REFLECTMETHODS
  • REFLECTEVENTS

Each of these methods takes a single argument which is the type of object to query:

e.g.

buttonProperties = exec_Method( "SYSTEM", "REFLECTPROPERTIES", "PUSHBUTTON" )
buttonMethods    = exec_Method( "SYSTEM", "REFLECTMETHODS", "PUSHBUTTON")
buttonEvents     = exec_Method( "SYSTEM", "REFLECTEVENTS", "PUSHBUTTON" )

Each method in turn returns a dynamic array of information describing the requested attribute type:

  • REFLECTPROPERTIES returns the name of each property and the type of the data it represents.  It also identifies the context that the property is valid for (Devtime/Runtime/Get/Set).
  • REFLECTMETHODS returns the name of each method, along with a list of arguments the method accepts and the type of data each argument should contain.
  • REFLECTEVENTS returns the name of each event the object type can raise along with the names and data types of arguments passed to an event handler.

Note that when these methods return the type of data for a property or argument there are some cases where only a broad hint is given – Basic+ is an untyped language so it is not really feasible to accurately describe some types using a simple set of flags – e.g. in the case where an argument is a complex dynamic array containing a variety of other core data types such a strings and numbers.

Whilst aimed mainly at developers who write development tools for OpenInsight, this API may still be of interest for those of you who like to write your own diagnostic and debugging tools – when a new property, method or event is added to the Presentation Server it is clearly exposed thereby reducing the likelihood of it remaining hidden and undocumented.

[Edit: 09 Jun 22 – Corrected method names (removed underscores)]

[Edit: 24 Apr 13 – Call_Method renamed to Exec_Method]

(Disclaimer: This article is based on preliminary information and may be subject to change in the final release version of OpenInsight 10).

The new STYLE_N property

If you’ve ever had to work with the STYLE or STYLE_EX properties in OpenInsight you’ve probably had to write some gnarly code like this to get around the strange way it returns a string containing a C-style hex representation such as “0x8234ABDB”:

style = iconv( get_Property( object, "STYLE" )[3,8], "MX" )

We’ll probably never know the reason the original authors of OpenInsight decided to implement the property like this, but with version 10 we’ve provided a pair of new properties called “STYLE_N” and “STYLE_EX_N” that return the numeric (decimal) representation of a control’s style directly thereby saving the need for the extra parsing.