Result dialog (ShowResult)

Created: 2026-07-11 · Updated: 2026-07-11

A snippet can show a freely designed result dialog at the end of its run — with a title, icon, formatted text (bold, colored, line breaks, links) and configurable buttons. Ideal for reporting how many elements were processed, or listing any errors clearly.

Instead of MessageBox

Use ppptools.ShowResult(...) / ppptools.ResultDialog(...) instead of a raw MessageBox. The dialog is sanctioned (no security prompt) and can display formatted text.


Two ways

1) Short form — ShowResult

ppptools.ShowResult("Done",
    $"<b>{n}</b> elements replaced.<br><color=#137333>All good.</color>",
    "OK");

ShowResult(title, markup, buttons = "OK", kind = "info")buttons is pipe-separated ("Yes|No"), kindinfo · warn · error · success. Returns the clicked button label.

2) Builder — assemble dynamically

var dlg = ppptools.ResultDialog("Done");
dlg.Kind("success");
dlg.Heading("Summary");
dlg.Line($"{n} elements replaced.", bold: true, color: "#137333");
dlg.Bullet("Detail A");
dlg.Link("Learn more", "https://ppptools.help.happy-pc.ch");
string clicked = dlg.Buttons("OK").Show();

Builder methods: Kind · Heading · Line(text, bold, color) · Bold · Bullet · Link(text, url) · Html(rawMarkup) · Buttons(...) · Show().


Formatting (HTML subset)

Tag Effect
<b>…</b> bold
<i>…</i> italic
<u>…</u> underline
<br> line break
<h>…</h> heading (bold, larger)
<color=#RRGGBB>…</color> text color
<size=NN>…</size> font size (pt)
<a href="url">…</a> clickable link (opens the website)

With a lot of text the dialog grows to a maximum height and then shows a scrollbar.


Full example — report hits & errors

The search-and-format snippet counts hits, collects per-shape errors, and reports both at the end:

// @param string SearchString  "Search term"                      tooltip="Enter search term"
// @param bool   AllSlides      "All slides?"                      tooltip="Across all slides?"
// @param bool   CaseSensitive  "Match case?"                      tooltip="o ≠ O, type ≠ Type"
// @param bool   ChangeFont     "Change font?"                     default="true"
// @param font   FormatFont     "Format (font)"                    default="Calibri,18,Bold"
// @param bool   ChangeColor    "Change color?"                    default="false"
// @param color  FormatColor    "Color"                            default="#FF0000"
// @button Run

string searchString  = Params.GetString("SearchString", "");
bool   allSlides     = Params.GetBool("AllSlides", false);
bool   caseSensitive = Params.GetBool("CaseSensitive", false);
bool   changeFont    = Params.GetBool("ChangeFont", true);
bool   changeColor   = Params.GetBool("ChangeColor", false);
System.Drawing.Font  fmt      = Params.GetFont("FormatFont");
System.Drawing.Color fmtColor = Params.GetColor("FormatColor");

MsoTriState matchCase = caseSensitive ? MsoTriState.msoTrue : MsoTriState.msoFalse;

int replaced      = 0;
int shapesTouched = 0;
var errors = new System.Collections.Generic.List<string>();

void FormatShapes(System.Collections.Generic.List<dynamic> shapes)
{
    foreach (dynamic oShape in shapes)
    {
        try
        {
            if ((int)oShape.HasTextFrame != (int)MsoTriState.msoTrue) continue;
            dynamic tr = oShape.TextFrame.TextRange;

            dynamic found = tr.Find(searchString, 0, matchCase, MsoTriState.msoFalse);
            bool touched = false;
            while (found != null)
            {
                if (changeFont)
                {
                    found.Font.Name      = fmt.Name;
                    found.Font.Size      = fmt.SizeInPoints;
                    found.Font.Bold      = fmt.Bold      ? MsoTriState.msoTrue : MsoTriState.msoFalse;
                    found.Font.Italic    = fmt.Italic    ? MsoTriState.msoTrue : MsoTriState.msoFalse;
                    found.Font.Underline = fmt.Underline ? MsoTriState.msoTrue : MsoTriState.msoFalse;
                }
                if (changeColor)
                    found.Font.Color.RGB = System.Drawing.ColorTranslator.ToOle(fmtColor);

                replaced++;
                touched = true;
                int after = found.Start + found.Length - 1;
                found = tr.Find(searchString, after, matchCase, MsoTriState.msoFalse);
            }
            if (touched) shapesTouched++;
        }
        catch (System.Exception ex)
        {
            string nm = "";
            try { nm = (string)oShape.Name; } catch { }
            errors.Add($"Shape \"{nm}\": {ex.Message}");
        }
    }
}

if (string.IsNullOrWhiteSpace(searchString))
{
    ppptools.ShowResult("Replace text",
        "<color=#C00000><b>No search term given.</b></color>", "OK", "warn");
}
else
{
    if (allSlides)
        for (int s = 1; s <= ppptools.SlideCount; s++)
            FormatShapes(ppptools.GetAllShapes(ppptools.GetSlide(s)));
    else
        FormatShapes(ppptools.GetAllShapes());

    var dlg = ppptools.ResultDialog("Replace text");
    dlg.Kind(errors.Count == 0 ? (replaced > 0 ? "success" : "info") : "warn");
    dlg.Heading("Search & Format");
    dlg.Line($"Search term: \"{searchString}\"");
    dlg.Line("");
    dlg.Line($"{replaced} hits formatted in {shapesTouched} shape(s).",
             bold: true, color: replaced > 0 ? "#137333" : "#666666");

    if (errors.Count > 0)
    {
        dlg.Line("");
        dlg.Line($"{errors.Count} errors:", bold: true, color: "#C00000");
        foreach (var e in errors) dlg.Bullet(e, color: "#C00000");
    }
    dlg.Show();
}

Free online objects: automatic promo block

For objects from the free online library, a short hint/promo block is automatically shown at the top of the result dialog (server-configured, per language). If the snippet shows no dialog of its own, the block appears as a standalone hint. Snippet authors don't need to do anything.

For admins

The text is maintained centrally on the library server (promo.json, markup as above, field enabled to toggle it) — changeable without an add-in update.