Roland Weigelt
Born to Code
-
The Search for a Proportional Font for Developers (Revisited for VS Code)
Back in 2016, in my article “The Search for a Proportional Font for Developers”, I wrote about trying out various fonts as a replacement for Segoe UI, a sans-serif font which once had, but then lost serifs for the uppercase “i”. In the end I settled on Ebrima, which (according to Wikipedia) “is an OpenType font designed to support African writing systems.” And: “Its Latin alphabet is based on the Segoe font.” The design of the Latin alphabet is based on the Segoe UI font from before Windows 8, i.e., it still has the serifs for the uppercase “i”.
There is an issue, though: The backtick character in Ebrima has a special behavior that most likely has its roots in the original purpose of the font but does not work well for displaying source code. Which turned out to be a problem when I started to work more with TypeScript/JavaScript in addition to my usual C# development.
Look at this example, first shown using the Consolas font:
(The font size is larger than usual for demonstration purposes)
And now in Ebrima:
Note that the backticks are barely visible.
Here is the example in Segoe UI:
The backticks are now visible, but uppercase “i” and lowercase “L” are hard to distinguish (even more so at my usual font size).
Stylistic sets to the rescue
When Segoe UI was updated for Windows 8, the original designs of the modified glyphs were moved to the SS01 OpenType stylistic set instead of removing them altogether. Which means that they can be brought back – if you know how.
The “regular” Visual Studio does not let you activate stylistic sets (not exactly a surprise, we cannot even have italics in the editor out-of-the-box). But Visual Studio Code does.
In the font settings UI, under “Font Ligatures”, press the “Edit in settings.json” link:
Next, add the following setting for
editor.fontLigatures
(note the double and single quotes):{ ...
"editor.fontLigatures": "'ss01'", ... }This is the result:
Nice!
Now if only the WPF-based, “big” Visual Studio (which I use for my C# development) would be a bit more flexible when it comes to fonts…
-
Using PowerPoint as a WYSIWIG Editor for HTML Templates (Proof of Concept in C#, Update)
In my previous blog post I described a proof-of-concept for creating an HTML template from a PowerPoint slide. After using this in a digital signage software for the local basketball club for a while, it has turned out that there is room for improvement. I have updated the demo project on GitHub accordingly.
Fixed: Do not close an already running PowerPoint application
The cleanup steps in the original code were a bit overeager, affecting an already running PowerPoint instance. In the worst case, unsaved documents were closed without a warning.
How to create just one HTML file per slide
The initial proof-of-concept created two files for each slide (HTML and PNG), with the HTML file using the PNG as the background image. By encoding the PNG as base64 and using a data URL, it is possible to have just one HTML file for each slide. The code in the demo project now creates a second HTML file (
HTMLPage2.html
) to demonstrate this. The downside is a larger file size, but the ease-of-use in file operations outweighs this in many scenarios.Links
-
Using PowerPoint as a WYSIWIG Editor for HTML Templates (Proof of Concept in C#)
The digital signage software that I develop for the local basketball club now supports HTML templates. I use this feature, e.g., for the introduction of the players on the video screens in the arena. For each player, I just enter the player’s data like name, jersey number, position, weight and height – which is then inserted dynamically into the template.
The software also supports importing PowerPoint slides as static images. PowerPoint plays an important role for many screens used at the home game, not least as it is one of the easiest ways for non-technical people without a design background to create content. And even though I feel very comfortable using Photoshop or Illustrator – if I quickly need to create a screen during the most stressful phase of home game, PowerPoint is my tool of choice.
One day, when I hand-coded a particularly simple HTML template for announcing the number of spectators, I spent a lot of time positioning the number next to a sponsor’s logo. That got me thinking: What if I could create templates like this in PowerPoint? All it would take would be some kind of marker text (e.g.
{{Number}}
) and a way to translate a PowerPoint slide to HTML.What about PowerPoint?
Unfortunately, Microsoft removed the feature to export slides as HTML years ago. Third-party solutions do exist, but for my purposes, the libraries are prohibitively expensive. So, I had to find my own solution.
As a single developer, on a limited (time) budget, the first thing to do in such a case is to decide which problems not to solve:
- I do not need to take care of different screen sizes; the width and height of the target display is fixed.
- The HTML is not intended to be edited later, i.e., it does not have to be “pretty”. This means that
div
tags with absolute positions are fine.
In fact, I do not even need a full-blown PowerPoint to HTML conversion. I can “fake” the HTML conversion by
- creating a PNG image of everything on the slide except the dynamic parts, and
- translate the shapes containing dynamic texts into div tags that are styled to match the shape style on the slide.
For reading and analyzing the PowerPoint file, I use the (COM-based) Office automation API instead of the more modern Open XML SDK, because the API also allows me to create PNG files from the slides.
The code
I have published some proof-of-concept code on https://github.com/RWeigelt/PowerPointSlideHtmlLayoutDemo, written in C#/.NET 6.
The project includes the PowerPoint file
Example.pptx
that contains various markers for insertion points inside- normal shapes,
- grouped shapes,
- placeholder shapes (i.e., the editable shapes placed on the slide master), and
- table cells.
When you run the project, it creates two files in your “Pictures” folder,
HtmlPage.html
andBackground.png
.HTMLPage.html
The HTML file contains the insertion point shapes, translated to
div
tags:(shown without background image, border added for illustration only)
Background.png
The background image contains all content that is not an insertion point (e.g., images, static texts).
Combined
When you open
HtmlPage.html
in a web browser, its CSS loadsBackground.png
as a background image.The result looks like this:
Where to go from here
This demo code is obviously just a start. While it does consider fonts, texts sizes and styles as well as alignment, it does not cover all design and layout capabilities.
Depending on your requirements, you may want to look into supporting text effects (e.g., shadow or glow should be possible in CSS) and transformations like shape rotation. You also may choose a different syntax for the insertion points.
The code is licensed under the “BSD Zero Clause License”, so you can use it without limitations and do not even have to credit me. I do not have plans to develop this into a general-purpose library; further development will be very specific to the needs of my digital signage software. If you take this idea and create something from it that may be of interest to others, drop me a line and I will link to your website or GitHub repository.
-
Emaroo 4.9.0 - Support for Visual Studio Code 1.64
Emaroo is a free utility for browsing most recently used (MRU) file lists of programs like Visual Studio, VS Code, Word, Excel, PowerPoint, Photoshop, Illustrator and more. Quickly open files, jump to their folder in Windows Explorer, copy them (and their path) to the clipboard - or run your own tools on files and folders with custom actions!
- Download Emaroo on www.roland-weigelt.de/emaroo
About this Release
- Updated: Support for Visual Studio Code 1.64 (changes regarding most recently used folders/workspaces). Previous versions of Visual Studio Code are still supported.
-
How to Create a PNG File from a Web Page in C#
Both Google Chrome and Microsoft Edge provide a feature for creating a PNG file from the currently visible viewport. For this, you start the browser executable in “headless mode”, i.e., without the UI (command line argument
--headless
), and provide the path of the output file (—screenshot=<path>
).Using this from C# code is straightforward:
void HtmlToPng(string source, string outputFilePath) { var arguments = $"--headless --disable-gpu --default-background-color=00000000 --window-size=1920,1080 --hide-scrollbars --screenshot=\"{outputFilePath}\" \"{source}\""; var process = new System.Diagnostics.Process(); process.StartInfo.FileName = "msedge"; // or "chrome" process.StartInfo.Arguments = arguments; process.StartInfo.UseShellExecute = true; process.Start(); }
Examples:
HtmlToPng("https://www.example.com", @"C:\example\output.png");
HtmlToPng(@"C:\example\input.html", @"C:\example\output.png");
(For complete code, download the demo project on GitHub)
Details
- By starting the process with
UseShellExcute = true
, we do not have to care about the exact location of the Edge (or Chrome) executable – specifyingmsedge
orchrome
is sufficient. --disable-gpu
is taken from the Google docs (we don’t need a GPU for what is basically one frame).--default-background-color
specifies the background color to use if the page itself has no background set. The color is a hex value in the format AARRGGBB (AA = alpha).00000000
means transparent;0
also works, but could be confused with “black” when reading the code later.--window-size
specifies the size of the area available for the webpage to render. The created PNG file will only show this area.- The
--hide-scrollbars
takes care of scrollbars that may appear if the page needs more space than available.
- By starting the process with
-
Using a Video Device with getUserMedia in WebView2 in a Kiosk Scenario (Update)
Back in July I wrote about my experiments with using a video capture device on a web page loaded into the WebView2 component. Since then, WebView2 has received a few updates. I am not sure when or how things have changed (or which version exactly I was using back then), but the workaround I described for using
getUserMedia()
without HTTPS no longer worked when I revisited this topic recently.While switching to HTTPS is my goal in the long run, I encountered problems with certificates that look like they could be solved by WebView2 feedback item #624, so I shelved the work on this for my application for now. Fortunately, there is a way to “fake” HTTPS in WebView2 that is good enough to meet the requirements for
getUserMedia()
.The
CoreWebView2.SetVirtualHostNameToFolderMapping()
function allows you to map a server name to a local folder. This way navigating to e.g.https://someServer/somePage.html
will load the local filesomePage.html
contained in that folder. If the server part and the display part of your application run on different computers, you will obviously have transfer the files e.g. to a temporary folder.The Microsoft documentation contains everything you need to know, so I will not go into further detail here. As usual, when working with WebView2, make sure
yourWebView.EnsureCoreWebView2Async()
has been executed before callingyourWebView.CoreWebView2.SetVirtualHostNameToFolderMapping()
.See also
- ”Get started with WebView2 in WPF” – step by step tutorial in the Microsoft documentation.
- Web search for “webcam video getUserMedia” – useful resources for using video devices in JavaScript.
- Using a Video Device with getUserMedia in WebView2 in a Kiosk Scenario – my previous blog post on this topic, containing information on how to handle the request for permission to use the camera.
-
Emaroo 4.8.0 - Support for Visual Studio 2022 / Adobe CC 2022
Emaroo is a free utility for browsing most recently used (MRU) file lists of programs like Visual Studio, VS Code, Word, Excel, PowerPoint, Photoshop, Illustrator and more. Quickly open files, jump to their folder in Windows Explorer, copy them (and their path) to the clipboard - or run your own tools on files and folders with custom actions!
- Download Emaroo on www.roland-weigelt.de/emaroo
About this Release
- Added: Support for Visual Studio 2022.
-
Added: Support for Photoshop / Illustrator / InDesign CC 2022.
-
Changed: Emaroo no longer looks for Adobe CC versions prior to 2020 by default. This does not affect support for CS6 versions.
If you still need support for older CC versions, you can enable it as follows:
- Close Emaroo
- Start Notepad as Administrator
-
Open the file
in the installation directory (usuallyEmaroo.exe.config
)C:\Program Files (x86)\Weigelt\Emaroo
-
Set
option toSearchForOldAdobeCCApplications
True
- Save the config file and start Emaroo.
-
How to Create a PNG File with Transparent Background from a Powerpoint Slide in C#
Exporting a PowerPoint slide to a PNG file of a specific size (e.g. 1920x1080 pixels) is easy:
var powerPoint = new Microsoft.Office.Interop.PowerPoint.Application(); var presentation = powerPoint.Presentations.Open("Input.pptx", MsoTriState.msoFalse, MsoTriState.msoFalse, MsoTriState.msoFalse); var slide = presentation.Slides[1]; // one-based! slide.Export("Output.png", "PNG", 1920, 1080);
(For complete code, download the demo project on GitHub)
This will create a PNG file that looks like what you see on screen (minus animations, of course).
So, for instance, something like this:
But what if we only want the foreground? Like this:
(Border added for illustration only)
In this case, we need to export the shapes of the slide, not the slide itself. We can ask the
Shapes
collection for aShapeRange
, and that offers anExport()
method (while that method is not well-documented and it seems like it is deprecated / for internal use only, it works for me and I do not see an alternative at this time).Because the shapes do not cover the whole slide, we need to add a transparent rectangle that has the width and height of the slide. The required information is available in the
PageSetup
object.This is the code for exporting a PNG file with a size of 1920x1080 pixels:
var shapes = slide.Shapes; var pageSetup = presentation.PageSetup; var rectangle = shapes.AddShape(MsoAutoShapeType.msoShapeRectangle, 0, 0, pageSetup.SlideWidth, pageSetup.SlideHeight); rectangle.Fill.Visible = MsoTriState.msoFalse; rectangle.Line.Visible = MsoTriState.msoFalse; var range = shapes.Range(); range.Export( "Output.png", PpShapeFormat.ppShapeFormatPNG, (int)(1920 * 72 / 96), (int)(1080 * 72 / 96), PpExportMode.ppScaleXY);
You will notice that the
ShapeRange.Export()
method expects different values for the width and height than theSlide.Export()
method. The number of pixels has to be multiplied by 72 and divided by 96 to get the desired result.The 72 is the number of points in an inch. The 96 left me wondering whether it has to be adjusted in some scenarios, but this does not seem to be the case:
- PowerPoint’s default resolution for image exports is 96 dots per inch. This default can be changed via a registry setting (see the Microsoft documentation for more details), but that does not influence the
ShapeRange.Export()
method. - My main monitor is set at 100% scaling (= “96 DPI”). I tested with other monitors / different settings, whether the scaling has to be taken into account (that is why the window of the demo program shows the monitor’s DPI setting). Again, no influence.
About the Demo Project
The demo is a WPF/C#/.NET 5 project that includes a PPTX file with a single slide. I tried to make the code as simple as possible, which results in this minimal UI:
When you press one of the buttons, a PNG file (“SlideWithBackground.png” or “SlideWithoutBackground.png”) will be written to your “Pictures” directory. Accordingly, the interesting parts of the code can be found in
ExportSlideWithBackground_Click
andExportSlideWithoutBackground_Click
. - PowerPoint’s default resolution for image exports is 96 dots per inch. This default can be changed via a registry setting (see the Microsoft documentation for more details), but that does not influence the
-
Confirmations in User Interfaces: Explicit vs. Implicit
Confirmations are a tricky subject in user interface design. As a UI designer, you want to avoid them, but you cannot always implement an undo/redo system. As users, we do not want to be nagged constantly, but if an action has serious consequences and something goes wrong, we angrily ask why there was no confirmation.
In addition to interrupting the flow of our work, confirmations can also introduce a tiny bit of stress. Confirming too fast and losing work is not fun. Even if the action was not permanent and, e.g., files can be brought back from the recycle bin, there is some kind of hassle involved. So, you do want to be sure about what you confirm.
In theory, when you directly look at something and trigger an action, a generic question like “Do you want to do this?” should be sufficient. The context of your action determines what “this” means (I cannot help myself thinking of an old JavaScript joke, but I digress).
In practice though, in a world full of distractions, sometimes when you see a dialog like this…
…, you may notice that your eye wanders back to the selection of the “item”.
This is why a dialog that explicitly tells you the name is a better solution:
But what about deleting multiple files? Depending on how large the number is, a dialog cannot show all names. The following dialog stops at ten files:
This is far from being perfect. And of course, one could think of a dialog with a scrolling list that allows you to view all files. For certain projects this may important enough to invest the necessary budget. On the other hand, the dialog shown above simply works by concatenating one large string and putting it into a standard dialog. This is a pragmatic solution that does its job well in many cases. Even though you are not told the names of the “3 additional files”, chances are that it is easier for you to remember them by looking at the ten names you can read. This may be less the case as the number of “additional files” grows, but anything is better than just a number like in this dialog.
Confirmation dialogs should contain enough information to work without looking at the rest of the user interface. When you design the dialog, imagine that the user must leave the room for a short moment and comes back to the computer (just a moment, not a lunch break). Make sure he or she can make then an informed decision.
-
A Stupid Little TypeScript Mistake (Part 2)
After my blog post in June, here is another tale from a C# developer getting his feet wet with TypeScript.
TypeScript’s type checking makes my life so much easier, but it does not catch everything. Recently I forgot an important part of a for-loop. Here is a stripped-down example:
var items=["item0", "item1", "item2"]; for (var n=0;items.length;n++) { // ... }
The code compiles, but runs into an endless loop – the “n<” is missing in the condition.
If I write similar code in C#…
var items=new[] {"item0", "item1", "item2"}; for (var n=0;items.Length;n++) { // ... }
… the compiler tells me what I did wrong:
Cannot implicitly convert type 'int' to 'bool'
Ok, another (TypeScript) lesson learned.