Articulo original: Segoe MDL2 Assets Icons in VFP9 with Gdi+
http://vfpimaging.blogspot.com/2021/04/segoe-mdl2-assets-icons-in-vfp9-with-gdi.html
Autor: Cesar Ch.
Traducido por: Luis María Guayán
Como se discutió anteriormente en este blog, VFP no puede mostrar de forma nativa ningún carácter que tenga su CHR() mayor que 0xFF (decimal 255).
Hay varias fuentes muy interesantes que traen íconos muy interesantes y actualizados que podríamos usar en nuestras aplicaciones, como SEGOE MDL2 ASSETS, utilizado por Windows 10 en todas partes.
Los Unicodes se pueden obtener directamente a través de CharMap.EXE o en toda la web. Aquí hay un excelente punto de partida: https://docs.microsoft.com/en-us/windows/uwp/design/style/segoe-ui-symbol-font
Los ejemplos a continuación usan GDI+ para guardar cualquier carácter deseado como una imagen, lo que nos permitirá usar esas imágenes geniales en nuestras aplicaciones. Usan las clases _GDIPLUS.VCX FFC, pero también es muy fácil de adaptar a GdiPlusX, si es necesario.
¡Adáptalo a tus necesidades!
Básicamente, una función que recupera un solo carácter Unicode y lo guarda como un archivo de imagen.
Uso:
Para obtener el icono "Imprimir":
EXTRAIGA UN ÚNICO ICONO
lcFile = "Imprimir.bmp" lcUnicode = "e749" lcFont = "ACTIVOS SEGOE MDL2" lnSize = 32 && píxeles lnForeColor = RGB (0, 0, 255) && Negro lnBackColor = RGB (255, 255, 255) && Blanco = MakeImageFromUnicode (m.lcFile, lcUnicode, lcFont, lnSize, lnForeColor, lnBackColor)
Guarde el siguiente código como "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
La función también le permite crear nuevos íconos fusionando dos, en este caso, el ícono de Impresora y Configuración en la parte inferior derecha:
PERSONALIZA TUS ICONOS
* 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
EXTRACCIÓN DE TODOS LOS ICONOS DE UNA FUENTE
La función anterior se puede adaptar para extraer todos los caracteres de una fuente determinada, utilizando un bucle.
Las fuentes suelen tener algunos códigos que no se utilizan, por lo que en el siguiente código utilicé un truco simple para detectar las dimensiones vacías de la fuente, y cada vez que se cumplan las mismas condiciones en el bucle, se descartará el Unicode.
Simplemente ejecute el siguiente código para extraer todos los íconos de cualquier fuente determinada, con el tamaño y los colores de imagen deseados. ¡Ajuste las variables iniciales para que se adapten a sus necesidades!
* 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) IF m.loSizeReal.W == m.pnEmptyW AND m.loSizeReal.H == m.pnEmptyH LOOP ENDIF 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
IMPORTANTE
No olvide que todas las fuentes tienen licencia. Eso significa que primero debe verificar si está autorizado a distribuir las imágenes generadas. Asegúrese de leer el EULA y ver qué puede o no puede hacer con ellos, ¿de acuerdo?
VEA TAMBIEN
Muy bueno...
ResponderBorrarEn el primer ejemplo cambiar nombre de la fuente "ACTIVOS SEGOE MDL2" por "SEGOE MDL2 ASSETS"