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 and Background.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 loads Background.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!

    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 – specifying msedge or chrome 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.
  • 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 file somePage.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 calling yourWebView.CoreWebView2.SetVirtualHostNameToFolderMapping().

    See also

  • 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!

    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 Emaroo.exe.config in the installation directory (usually C:\Program Files (x86)\Weigelt\Emaroo)
      • Set SearchForOldAdobeCCApplications option to 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 a ShapeRange, and that offers an Export() 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 the Slide.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 and ExportSlideWithoutBackground_Click.

  • 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.