Showing posts with label SEGOE UI. Show all posts
Showing posts with label SEGOE UI. Show all posts

2021-04-08

Segoe MDL2 Assets Icons in VFP9 with Gdi+

As discussed before in this blog, VFP can't display natively any character having its CHR() higher than 0xFF (decimal 255). 

There are several very interesting fonts that bring very cool and up to date icons that we could use in our apps, such as the SEGOE MDL2 ASSETS, used by Windows 10 all over.

The Unicodes can be obtained directly by the CharMap.EXE or all over the web. Here's an excellent starting point: https://docs.microsoft.com/en-us/windows/uwp/design/style/segoe-ui-symbol-font


The samples below will use GDI+ to save any desired character as an image, allowing us to use those cool images in our apps. They use the _GDIPLUS.VCX FFC classes, but is really very easy to adapt to GdiPlusX as well, if needed.

Adapt it to your needs!

Basically a function that retrieves a single unicode character and saves it as an image file. 

Usage:
To get the "Print" icon: 


EXTRACT A SINGLE ICON


lcFile = "Print.bmp"
lcUnicode = "e749"
lcFont = "SEGOE MDL2 ASSETS"
lnSize = 32 && Pixels
lnForeColor = RGB(0, 0, 255) && Black
lnBackColor = RGB(255, 255, 255) && White
=MakeImageFromUnicode(m.lcFile, lcUnicode, lcFont, lnSize, lnForeColor, lnBackColor)


Save the code Below as "MakeImageFromUnicode.prg":


FUNCTION MakeImageFromUnicode(tcFileName, tcUnicode, tcFontName, tnImgSize, tnForeColor, tnBackColor)
*!* tcUnicode allows up to 2 characters, that will be drawn one over the other
*!* Par1: Main Unicode
*!* Par2: Socondary Unicode
*!* Par3: Mode, where 0=Center, 1=TopLeft, 2=TopRight, 3=BottLeft, 4=BottRight
*!* Par4: Size of the 2nd character

	LOCAL lnChars, lnFactor, lnFontHeight, lnFontSize, lnHeight, lnLines, lnNewFontSize, lnWidth
	LOCAL lqUnicode
	LOCAL lcUnicode1, lcUnicode2, lnMode, lnSize2
	IF EMPTY(m.tcFileName) OR EMPTY(m.tcUnicode) OR EMPTY(m.tcFontName) OR EMPTY(m.tnImgSize)
		RETURN
	ENDIF

	m.lnFontSize = 48
	m.lnWidth	 = m.tnImgSize
	m.lnHeight	 = m.tnImgSize

	* Create a font object using the text object's settings.
	LOCAL loFont0 AS GpFont OF HOME() + "FFC/_GdiPlus.vcx"
	m.loFont0 = NEWOBJECT('gpFont', HOME() + 'FFC/_GdiPlus.vcx')
	m.loFont0.Create(m.tcFontName, m.lnFontSize, 0, 3) && 0 = Font Style

	LOCAL loGfx0 AS GpGraphics OF HOME() + "FFC/_GdiPlus.vcx"
	m.loGfx0 = NEWOBJECT('gpGraphics', home() + 'FFC\_GdiPlus.vcx')
	m.loGfx0.CreateFromHWnd(_screen.HWnd)
	m.lnChars = 0
	m.lnLines = 0

	LOCAL loSize AS gpSize OF HOME() + "FFC/_GdiPlus.vcx"
	m.loSize  = m.loGfx0.MeasureStringA("A", m.loFont0, , , @m.lnChars, @m.lnLines)
	* lnFontWidth = loSize.W
	m.lnFontHeight	= m.loSize.H
	m.lnFactor		= m.lnFontHeight / m.tnImgSize
	m.lnNewFontSize	= INT(m.lnFontSize / m.lnFactor)

	* Create a font object using the text object's settings.
	LOCAL loFont AS GpFont OF HOME() + "FFC/_GdiPlus.vcx"
	m.loFont = NEWOBJECT('gpFont', HOME() + 'FFC/_GdiPlus.vcx')
	m.loFont.Create(m.tcFontName, m.lnNewFontSize, 0, 3) && 0 = Font Style

	LOCAL loBMP AS GpBitmap OF HOME() + "FFC/_GdiPlus.vcx"
	m.loBMP = NEWOBJECT("gpBitmap", HOME() + "FFC/_GdiPlus.vcx")
	#DEFINE GdiPlus_PixelFormat_32BPPARGB        0x0026200a
	m.loBMP.Create(m.lnHeight, m.lnHeight, GdiPlus_PixelFormat_32BPPARGB)

	LOCAL loGfx AS GpGraphics OF HOME() + "FFC/_GdiPlus.vcx"
	m.loGfx = NEWOBJECT('gpGraphics', HOME() + 'FFC/_GdiPlus.vcx')
	m.loGfx.CreateFromImage(m.loBMP)

	* Setting the Backcolor
	LOCAL loBackColor AS GpColor OF HOME() + "FFC/_GdiPlus.vcx"
	IF EMPTY(m.tnBackColor)
		m.loBackColor = 0xFFFFFFFF && White background
	ELSE
		m.loBackColor		 = NEWOBJECT("gpColor", HOME() + 'FFC/_GdiPlus.vcx')
		m.loBackColor.FoxRGB = m.tnBackColor
	ENDIF
	m.loGfx.CLEAR(m.loBackColor) && Background

	* Create a rectangle
	LOCAL loRect AS GpRectangle OF HOME() + "FFC/_GdiPlus.vcx"
	m.loRect = NEWOBJECT("GPRectangle", HOME() + 'FFC/_GdiPlus.vcx', "", 0, 0, m.lnWidth, m.lnHeight)
	m.loRect.y = m.loRect.y + 1

	* Setting the Forecolor
	LOCAL loColor AS GpColor OF HOME() + "FFC/_GdiPlus.vcx"
	IF EMPTY(m.tnForeColor)
		m.tnForeColor = 0 && Black
	ENDIF
	m.loColor		 = NEWOBJECT("gpColor", HOME() + 'FFC/_GdiPlus.vcx')
	m.loColor.FoxRGB = m.tnForeColor

	LOCAL loBrush AS GpSolidBrush OF HOME() + "FFC/_GdiPlus.vcx"
	m.loBrush = NEWOBJECT("gpSolidBrush", HOME() + 'FFC/_GdiPlus.vcx', "", m.loColor)

	* The character need to be drawn at the center of the image object
	* Get a basic string format object
	* StringAlignment enumeration
	* Applies to GpStringFormat::Alignment, GpStringFormat::LineAlignment
	#DEFINE GDIPLUS_STRINGALIGNMENT_Near	0	&& in Left-To-Right locale, this is Left
	#DEFINE GDIPLUS_STRINGALIGNMENT_Center	1
	#DEFINE GDIPLUS_STRINGALIGNMENT_Far		2	&& in Left-To-Right locale, this is Right
	LOCAL loStringFormat AS gpStringFormat OF HOME() + "FFC/_GdiPlus.vcx"
	m.loStringFormat = NEWOBJECT("GpStringFormat", HOME() + "FFC/_GdiPlus.vcx")
	m.loStringFormat.Create()
	m.loStringFormat.Alignment	   = GDIPLUS_STRINGALIGNMENT_Center
	m.loStringFormat.LineAlignment = GDIPLUS_STRINGALIGNMENT_Center

	* Prepare the Unicode
	m.lcUnicode1 = GETWORDNUM(m.tcUnicode, 1, ",")
	m.lqUnicode	 = LEFT(BINTOC(EVALUATE("0x" + m.lcUnicode1), "4RS"), 2)

	* Draw the string
	m.loGfx.DrawStringW(m.lqUnicode, m.loFont, m.loRect, m.loStringFormat, m.loBrush)
	m.lcUnicode2	= GETWORDNUM(m.tcUnicode, 2, ",")

	IF NOT EMPTY(m.lcUnicode2)
		m.lqUnicode	= LEFT(BINTOC(EVALUATE("0x" + m.lcUnicode2), "4RS"), 2)
		m.lnMode	= VAL(GETWORDNUM(m.tcUnicode, 3, ","))
		m.lnSize2	= VAL(GETWORDNUM(m.tcUnicode, 4, ","))
		m.lnSize2	= EVL(m.lnSize2, 100)

		lnNewFontSize = CEILING(m.lnNewFontSize * (lnSize2/100))
		m.loFont.Create(m.tcFontName, m.lnNewFontSize, 0, 3) && 0 = Font Style
		m.loStringFormat.Alignment	   = GDIPLUS_STRINGALIGNMENT_Center
		m.loStringFormat.LineAlignment = GDIPLUS_STRINGALIGNMENT_Center

		m.loRect.w = INT(m.lnWidth  * (m.lnSize2 / 100))
		m.loRect.H = INT(m.lnHeight * (m.lnSize2 / 100))

		DO CASE
			CASE m.lnMode = 0 && No transformation, the 2nd image will be drawn over the original
				m.loRect.x = INT((m.lnWidth  - m.loRect.w) / 2)
				m.loRect.Y = INT((m.lnHeight - m.loRect.H) / 2)

			CASE m.lnMode = 1 && Top-Left
				m.loRect.x = 0
				m.loRect.Y = 0

			CASE m.lnMode = 2 && Top-Right
				m.loRect.x = m.lnWidth - m.loRect.w
				m.loRect.Y = 0

			CASE m.lnMode = 3 && Bottom-Left
				m.loRect.x = 0
				m.loRect.Y = m.lnHeight - m.loRect.H

			CASE m.lnMode = 4 && Bottom-Right
				m.loRect.x = m.lnWidth - m.loRect.w
				m.loRect.Y = m.lnHeight - m.loRect.H

			OTHERWISE
		ENDCASE
		m.loRect.y = m.loRect.y + 1
		m.loGfx.DrawStringW(m.lqUnicode, m.loFont, m.loRect, m.loStringFormat, m.loBrush)
	ENDIF

	* Save as image
	m.loBMP.SaveToFile(m.tcFileName, "image/bmp")

	RETURN
ENDFUNC 


The function also allows you to create new icons by merging two, in this case, the Printer and the Settings icon at the bottom right:

CUSTOMIZE YOUR ICONS


lcFile = "Print.bmp"
lcUnicode = "e749,e713,4,25"
lcFont = "SEGOE MDL2 ASSETS"
lnSize = 32 && Pixels
lnForeColor = RGB(0, 0, 128) && Dark Blue
lnBackColor = RGB(255, 255, 128) && Yellow
=MakeImageFromUnicode(m.lcFile, lcUnicode, lcFont, lnSize, lnForeColor, lnBackColor)


EXTRACTING ALL ICONS FROM A FONT

The above function can be adapted in order to extract all characters of a given font, using a loop.
Fonts usually have some codes that are not being used, so in the code below I used a simple trick to detect the empty font dimensions, and every time the same conditions are met in the loop, the unicode will be discarded.
Just run the code below to extract all icons from any given font, at the desired image size and colors. Adjust the initial variables to fit your needs!

* Setup the initial 5 variables
LOCAL lcFontName, lnImgSize, lnForeColor, lnBackColor, lcImageType
m.lcFontName  = "SEGOE MDL2 ASSETS"
m.lnImgSize	  = 64  && The desired bmp size in pixels
m.lnForeColor = RGB(0, 0, 0) && the ForeColor
m.lnBackColor = RGB(255, 255, 255) && the BackColor
m.lcImageType = "bmp" && available: bmp, jpg, gif, tif, png



* Let's start
LOCAL lcEmptyUnicode, lcFileName, lcHex, lcUnicode, lnChars, lnEmptyH, lnEmptyW, lnFactor
LOCAL lnFontHeight, lnFontSize, lnFontWidth, lnHeight, lnLines, lnNewFontSize, lnWidth, loSizeReal, n

m.lnFontSize  = 48
m.lnWidth	  = m.lnImgSize
m.lnHeight	  = m.lnImgSize
m.lcImageType = LOWER(EVL(m.lcImageType, "bmp"))

* Create a rectangle
LOCAL loRect AS GpRectangle OF HOME() + "FFC/_GdiPlus.vcx"
m.loRect   = NEWOBJECT("GPRectangle", HOME() + 'FFC/_GdiPlus.vcx', "", 0, 0, m.lnWidth, m.lnHeight)
m.loRect.y = m.loRect.y + 1

* The character need to be drawn at the center of the image object
* Get a basic string format object
* StringAlignment enumeration
* Applies to GpStringFormat::Alignment, GpStringFormat::LineAlignment
#DEFINE GDIPLUS_STRINGALIGNMENT_Near	0	&& in Left-To-Right locale, this is Left
#DEFINE GDIPLUS_STRINGALIGNMENT_Center	1
#DEFINE GDIPLUS_STRINGALIGNMENT_Far		2	&& in Left-To-Right locale, this is Right
LOCAL loStringFormat AS gpStringFormat OF HOME() + "FFC/_GdiPlus.vcx"
m.loStringFormat = NEWOBJECT("GpStringFormat", HOME() + "FFC/_GdiPlus.vcx")
m.loStringFormat.Create()
m.loStringFormat.Alignment	   = GDIPLUS_STRINGALIGNMENT_Center
m.loStringFormat.LineAlignment = GDIPLUS_STRINGALIGNMENT_Center



* Create a font object using the text object's settings.
LOCAL loFont0 AS GpFont OF HOME() + "FFC/_GdiPlus.vcx"
m.loFont0 = NEWOBJECT('gpFont', HOME() + 'FFC/_GdiPlus.vcx')
m.loFont0.Create(m.lcFontName, m.lnFontSize, 0, 3) && 0 = Font Style

LOCAL loGfx0 AS GpGraphics OF HOME() + "FFC/_GdiPlus.vcx"
m.loGfx0 = NEWOBJECT('gpGraphics', home() + 'FFC\_GdiPlus.vcx')
m.loGfx0.CreateFromHWnd(_screen.HWnd)

LOCAL loSize AS gpSize OF HOME() + "FFC/_GdiPlus.vcx"
m.lnChars	   = 0
m.lnLines	   = 0
m.loSize	   = m.loGfx0.MeasureStringA("A", m.loFont0, , , @m.lnChars, @m.lnLines)
m.lnFontWidth  = m.loSize.W
m.lnFontHeight = m.loSize.H

m.lnFactor		= m.lnFontHeight / m.lnImgSize
m.lnNewFontSize	= INT(m.lnFontSize / m.lnFactor)

* Create a font object using the text object's settings.
LOCAL loFont AS GpFont OF HOME() + "FFC/_GdiPlus.vcx"
m.loFont = NEWOBJECT('gpFont', HOME() + 'FFC/_GdiPlus.vcx')
m.loFont.Create(m.lcFontName, m.lnNewFontSize, 0, 3) && 0 = Font Style

* Get the measure of the empty character, that will be used to avoid saving it several times
m.lcEmptyUnicode = CHR(0) + CHR(0)
LOCAL loSizeEmpty AS gpSize OF HOME() + "FFC/_GdiPlus.vcx"
m.loSizeEmpty = m.loGfx0.MeasureStringW(m.lcEmptyUnicode, m.loFont, m.loRect, m.loStringFormat, @m.lnChars, @m.lnLines)
m.lnEmptyW	  = m.loSizeEmpty.W
m.lnEmptyH	  = m.loSizeEmpty.H

LOCAL loBMP AS GpBitmap OF HOME() + "FFC/_GdiPlus.vcx"
m.loBMP = NEWOBJECT("gpBitmap", HOME() + "FFC/_GdiPlus.vcx")
#DEFINE GdiPlus_PixelFormat_32BPPARGB        0x0026200a
m.loBMP.Create(m.lnHeight, m.lnHeight, GdiPlus_PixelFormat_32BPPARGB)

LOCAL loGfx AS GpGraphics OF HOME() + "FFC/_GdiPlus.vcx"
m.loGfx = NEWOBJECT('gpGraphics', HOME() + 'FFC/_GdiPlus.vcx')
m.loGfx.CreateFromImage(m.loBMP)

* Setting the Backcolor
LOCAL loBackColor AS GpColor OF HOME() + "FFC/_GdiPlus.vcx"
IF EMPTY(m.lnBackColor)
   m.loBackColor = 0xFFFFFFFF && White background
ELSE
   m.loBackColor		 = NEWOBJECT("gpColor", HOME() + 'FFC/_GdiPlus.vcx')
   m.loBackColor.FoxRGB = m.lnBackColor
ENDIF

* Setting the Forecolor
LOCAL loColor AS GpColor OF HOME() + "FFC/_GdiPlus.vcx"
IF EMPTY(m.lnForeColor)
   m.lnForeColor = 0 && Black
ENDIF
m.loColor		 = NEWOBJECT("gpColor", HOME() + 'FFC/_GdiPlus.vcx')
m.loColor.FoxRGB = m.lnForeColor

LOCAL loBrush AS GpSolidBrush OF HOME() + "FFC/_GdiPlus.vcx"
m.loBrush = NEWOBJECT("gpSolidBrush", HOME() + 'FFC/_GdiPlus.vcx', "", m.loColor)


FOR m.n = 0xe001 TO 0xf8b3 && the last available found in charmap
   m.lcHex		 = TRANSFORM(m.n, "@0")
   m.lcHex		 = STRTRAN(m.lcHex, "0x0000", "")
   m.lcFileName = FORCEEXT(m.lcHex, m.lcImageType)

   * Prepare the Unicode
   m.lcUnicode	 = LEFT(BINTOC(EVALUATE("0x" + m.lcHex), "4RS"), 2)

   m.loSizeReal = m.loGfx0.MeasureStringW(m.lcUnicode, m.loFont, m.loRect, m.loStringFormat, @m.lnChars, @m.lnLines)

   m.loGfx.CLEAR(m.loBackColor) && Background

   * Draw the string
   m.loGfx.DrawStringW(m.lcUnicode, m.loFont, m.loRect, m.loStringFormat, m.loBrush)

   * Save as image
   m.loBMP.SaveToFile(m.lcFileName, "image/" + m.lcImageType)
ENDFOR

* Clear GDI+ objects
m.loRect         = NULL
m.loStringFormat = NULL
m.loColor        = NULL
m.loBackColor    = NULL
m.loBrush        = NULL
m.loSize         = NULL
m.loSizeEmpty    = NULL
m.loGfx0         = NULL
m.loGfx          = NULL
m.loBMP          = NULL
m.loFont0        = NULL
m.loFont         = NULL

RETURN

 

IMPORTANT

Don't forget that all fonts have a license. That means that you need to check first if you are allowed to distribute the images generated. Make sure to read the EULA, and see what you can or cannot do with them, ok?


SEE ALSO

Unicode button icons in Visual FoxPro
Unicode Controls in Visual FoxPro - A new faster and efficient aproach
Unicode Button Icons in Visual FoxPro

2020-11-23

Unicode Controls in Visual FoxPro - A new faster and efficient aproach

As a continuation of my last post - Unicode Button Icons in Visual FoxPro, I decided to keep trying different solutions to bring Unicodes to our controls - specially as button icons.

The most natural option would be to use real Windows Buttons like the sample we have in VFPX - https://vfpimaging.blogspot.com/2020/11/unicode-button-icons-in-visual-foxpro.html

But this brings the con that we would have to make several changes in our legacy forms in order to adapt all codes related to the Click event, and others.

So, I decided to try a hybrid solution - "Draw" a "Static" Win32 control - similar to our VFP Label control over regular CommandButtons and Labels. These "Static" Win controls allow Unicodes, and would allow us to keep all our legacy codes as they are. 

So here's FOXYOBJECTS - a custom VFP class that can be tossed in our forms, and will "Convert" all buttons and labels that have contents between the <UC> </UC> tags to unicodes, just like the previous post. This time about 4-5 times faster than GradObjects, with the same result.

If you didn't read the previous post, my goal is to bring some cool icons, the same we see all over in WIN10 UI, specially those from SEGOE MDL2 ASSETS, like shown in the CharMap below:



The usage of this new class is really very simple:

  • Open the FoxyObjects project
  • Toss an instance of FoxyObjects to your form
  • Set your command button FontName property to "SEGOE MDL2 ASSETS" or any other that you desire.
  • Set the caption property of the button to accept unicodes, by introducing the unicodes between the <UC> </UC> tags, for instance:
          greek <UC>03b5 03b9 03c1 03ae 03bd 03b7</UC> - This will show the word "Peace" in greek characters, in any regular font, like Arial, Tahoma, Segoe UI, etc
          To get the Printer icon from the SEGOE MDL2 ASSETS, set the commandbutton font to it, and add the following to its caption property: "<UC>E749</UC>"


FoxyObjects brings some few properties, that will be applied to all CommandButton and Label controls that are on the same object level of the FoxyObjects level. For instance, if you want FoxyObjects to apply changes to some selected objects, you can insert them into a container, and add an instance of the class to it. This way, the rest of the objects will not be affected.

By default, it will apply changes only to objects that have the <UC> tag in their captions.



  • BackColor - Numeric, specifies the background color used to display text and graphics in an object.
  • DisabledForeColor - Numeric, specifies the color used to display text when the object is disabled.
  • ForeColor - Numeric, specifies the color used to display text.
  • MouseOverForeColor - Numeric, specifies the color the object text (and icon) will turn into when the mouse will be over the specified object. If you don't want this effect, store the value -1
  • lBindAll - Logical, determines that all objects will be affected, even if they don't have the <UC> in the caption. That means that you can change the caption at runtime, and the unicodes will be respected 
  • lBindLabels - Logical, determines that both CommandButtons and Labels will be affected
  • lBindResize - Logical, determines that whenever any control is resized or moved the label mask will be updated as well.
  • lBindVisible - Logical, determines that whenever any control is hidden or visible label mask will be updated as well.









The Unicodes can be obtained directly by the CharMap.EXE or all over the web. Here's an excellent starting point: https://docs.microsoft.com/en-us/windows/uwp/design/style/segoe-ui-symbol-font


The SEGOE MDL2 ASSETS font comes with Win10, but it is not allowed to be distributed to other OS'. This is not a big deal, because Tahoma also brings several options to us, and we can always work with some of the free fonts available on the web, such as "Material.io". They bring tons of modern and beautiful icons for free. It's really worth a visit - https://material.io/resources/icons/?style=outline


SPECIAL THANKS to Mustapha Bihmuten from Morocco and Leandro Walfrans from Brazil for testing the Pre-Alpha version of the class and for bringing valuable suggestions



 FoxyObjects v0.4 Download 


See Also:
Drawing Unicode Texts with GDI+
Unicode Button Icons in Visual FoxPro
Unicode character search by compart.com
Material icons

2020-11-15

Unicode button icons in Visual FoxPro

A big difficulty foxers have is to update their user interfaces. Since we lost MS support, we need to do almost all UI changes by our own. The Win10 UI today is based in monochrome icons - the ones from the SEGOE UI family - SEGOE UI SYMBOL and SEGOE MDL2 ASSETS. These are true type fonts, that bring tons of icons - the ones that we see all over in Win10.



Unfortunately we can't access those icons directly in VFP, because they use a range higher than the CHR(255) supported by VFP. We still have some options:

1 - Use an ACTIVE-X that supports unicodes

2 - Use "Real Window buttons", that support unicodes - https://github.com/VFPX/Win32API/blob/master/samples/sample_274.md

3 - Get some help from GDI+ - gdiplus.dll and do the drawings for us.


The 3rd option is really nice, but demands a lot, really a lot of work. Fortunately, I did almost all the hard work before, back in 2005, in the GradObjects class, that originally was created to bring gradient backgrounds and buttons to our forms. It recreated every button from the form, and redrawn it to an image file, allowing cool gradient, mouse over and disabled effects.

Having this, I just needed to adapt it, leaving the almost abandoned gradients behind, adding support to unicodes and some adaptations for the mouse over effects.


Here's an updated version of the good and old GRADOBJECTS class, that was intended to generate gradient buttons and backgrounds to our forms back in 2005, in the WinXP times. It's still the same GradObjects, but with some new properties and features. 


The usage is really very simple:

  • Open the GradObjects project
  • Create a form, add some buttons
  • Toss an instance of Gradobjects to your form
  • Set your command button FontName property to "SEGOE MDL2 ASSETS" or any other that you desire.
  • Set the caption property of the button to accept unicodes, by introducing the unicodes between the <UC> </UC> tags, for instance:
          greek <UC>03b5 03b9 03c1 03ae 03bd 03b7</UC> - This will show the word "Peace" in greek characters, in any regular font, like Arial, Tahoma, Segoe UI, etc
          To get the Printer icon from the SEGOE MDL2 ASSETS, set the commandbutton font to it, and add the following to its caption property: "<UC>E749</UC>"


The default "GradObjects" properties will bring you a gradient look, but all you need is to change just 5:

  • BackColor1: Numeric, the RGB of the backcolor
  • BackColor2: Set it to .F. (false), because we don't need gradients here, do we?
  • CaptionForeColor: Numeric, the RGB of the forecolor
  • GradientMode: 0 - We don't need gradients!
  • SelBackColor: Numeric, the RGB of the backcolor when a button is focused or mouse over it
  • SelForeColor: Numeric, the RGB of the forecolor when a button is focused or mouse over it

That's it!

The Unicodes can be obtained directly by the CharMap.EXE or all over the web. Here's an excellent starting point: https://docs.microsoft.com/en-us/windows/uwp/design/style/segoe-ui-symbol-font


For a more detailed information, please refer to the original post for GradObjects: http://vfpimaging.blogspot.com/2006/07/gradient-objects-with-gdi-revisited_48.html



The "GradObjects" object will transform all CommandButtons, Graphical OptionButtons from the same parent object. Use containers, if you need different effects (or none) to some individual controls in your forms.

Start playing with the sample form "TESTUNICODEBTNS.SCX"

 Unicode Buttons Download 


See Also:
Drawing Unicode Texts with GDI+