<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>General &#8211; Xojo Programming Blog</title>
	<atom:link href="https://blog.xojo.com/category/uncategorized/feed/" rel="self" type="application/rss+xml" />
	<link>https://blog.xojo.com</link>
	<description>Blog about the Xojo programming language and IDE</description>
	<lastBuildDate>Thu, 29 Oct 2026 17:03:14 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.9.11</generator>
	<item>
		<title>DesktopTable Cell Popover</title>
		<link>https://blog.xojo.com/2026/10/29/desktop-table-cell-popover/</link>
		
		<dc:creator><![CDATA[Wayne Golding]]></dc:creator>
		<pubDate>Thu, 29 Oct 2026 16:37:33 +0000</pubDate>
				<category><![CDATA[Desktop]]></category>
		<category><![CDATA[General]]></category>
		<category><![CDATA[DesktopTable]]></category>
		<category><![CDATA[Xojo Programming Language]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=16743</guid>

					<description><![CDATA[In this post, I&#8217;ll show you how to anchor a popover to a specific DesktopTable cell using CellBoundsAt so you can display full cell text&#8230;]]></description>
										<content:encoded><![CDATA[
<p>In this post, I&#8217;ll show you how to anchor a popover to a specific DesktopTable cell using CellBoundsAt so you can display full cell text (even when the cell can&#8217;t fit it) with correct positioning across macOS and Windows.</p>



<p>Popovers anchor to a control, not a location, which has been somewhat tricky to do in the past. DesktopTable has a CellBoundsAt method which returns a Rect containing the selected cell&#8217;s geometry and position relative to the table control’s location on its parent. This allows us to anchor the popover container to an individual cell.</p>



<figure class="wp-block-image size-full"><img fetchpriority="high" decoding="async" width="890" height="626" src="https://blog.xojo.com/wp-content/uploads/2026/10/image.png" alt="" class="wp-image-16744" srcset="https://blog.xojo.com/wp-content/uploads/2026/10/image.png 890w, https://blog.xojo.com/wp-content/uploads/2026/10/image-300x211.png 300w, https://blog.xojo.com/wp-content/uploads/2026/10/image-768x540.png 768w" sizes="(max-width: 890px) 100vw, 890px" /></figure>



<p>This is useful when you need to show the full contents of a cell whose displayed area can’t fit the underlying data.</p>



<p>In this example, the popover container is intentionally simple &#8211; it is a TextArea sized to fill the container.&nbsp; The container is named PopOverContainer. The Window includes a property named AnchorControl As DesktopRectangle that we&#8217;ll use as the popover&#8217;s anchor.</p>



<p>In the Window Opening event, we initialize the anchor rectangle:</p>



<pre class="wp-block-code"><code>Sub Opening() Handles Opening
&nbsp; AnchorControl = New DesktopRectangle
&nbsp; Window1.AddControl(AnchorControl)
&nbsp; AnchorControl.BorderThickness = 0.0
&nbsp; AnchorControl.FillColor = &amp;c000000FF ' Transparent on MacOS, Window background color on Windows

End Sub</code></pre>



<p>This initializes the rectangle that we will anchor the popover to.</p>



<p>Lastly the CellPressed Event Hanlder:</p>



<pre class="wp-block-code"><code>Function CellPressed(row As Integer, column As Integer, x As Integer, y As Integer) Handles CellPressed as Boolean
&nbsp; #Pragma Unused x
&nbsp; #Pragma Unused y
&nbsp; If column &lt;&gt; 1 Then ' We only want the popover to show on Column 1
&nbsp; &nbsp; Return False
&nbsp; End If
&nbsp;&nbsp;
  // Move the Anchor control to the selected cell position.
&nbsp; AnchorControl.Left = me.CellBoundsAt(row, column).Left + me.Left
&nbsp; AnchorControl.Top = me.CellBoundsAt(row, column).Top + me.Top + me.CellBoundsAt(row, column).Height ' I want the popover to anchor to the bottom of the control
&nbsp; AnchorControl.Width = me.CellBoundsAt(row, column).Width
&nbsp; AnchorControl.Height = If(TargetWindows, 0, 1) ' Windows can handle 0 height, MacOS doesn't &nbsp;

  // Now that we have an anchor point at the correct location we can popover

&nbsp; Var poc As New PopOverContainer

&nbsp; poc.TextArea1.Text = me.CellTextAt(row, column)

&nbsp; poc.ShowPopover(AnchorControl, DesktopContainer.DisplaySides.Bottom)
  Return True
End Function</code></pre>



<h3 class="wp-block-heading">Cross-platform Adjustments </h3>



<p>Some adjustments will need to be made for the different ways targets handle transparency.&nbsp; Windows doesn’t visually render transparent controls in the same way macOS does, and macOS may require the anchor control to occupy a space.&nbsp; By setting the anchor height appropriately, we can ensure the popover is positioned correctly on both platforms. </p>



<p><a href="https://blog.xojo.com/wp-content/uploads/2026/10/Table-Cell-Pop-over.xojo_binary_project.zip">Download the project</a>.</p>



<p><em>Wayne Golding has been a Xojo developer since 2005 and is a Xojo MVP. He operates the IT Company <a href="http://www.axisdirect.nz">Axis Direct Ltd </a>which primarily develops applications using Xojo that integrate with Xero www.xero.com. Wayne’s hobby is robotics where he uses Xojo to build applications for his Raspberry Pi, often implementing IoT for remote control.</em></p>



<ul class="wp-block-social-links has-normal-icon-size is-content-justification-center is-layout-flex wp-container-core-social-links-is-layout-16018d1d wp-block-social-links-is-layout-flex"><li class="wp-social-link wp-social-link-facebook  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.facebook.com/goxojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M12 2C6.5 2 2 6.5 2 12c0 5 3.7 9.1 8.4 9.9v-7H7.9V12h2.5V9.8c0-2.5 1.5-3.9 3.8-3.9 1.1 0 2.2.2 2.2.2v2.5h-1.3c-1.2 0-1.6.8-1.6 1.6V12h2.8l-.4 2.9h-2.3v7C18.3 21.1 22 17 22 12c0-5.5-4.5-10-10-10z"></path></svg><span class="wp-block-social-link-label screen-reader-text">Facebook</span></a></li>

<li class="wp-social-link wp-social-link-x  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://x.com/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M13.982 10.622 20.54 3h-1.554l-5.693 6.618L8.745 3H3.5l6.876 10.007L3.5 21h1.554l6.012-6.989L15.868 21h5.245l-7.131-10.378Zm-2.128 2.474-.697-.997-5.543-7.93H8l4.474 6.4.697.996 5.815 8.318h-2.387l-4.745-6.787Z" /></svg><span class="wp-block-social-link-label screen-reader-text">X</span></a></li>

<li class="wp-social-link wp-social-link-linkedin  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.linkedin.com/company/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M19.7,3H4.3C3.582,3,3,3.582,3,4.3v15.4C3,20.418,3.582,21,4.3,21h15.4c0.718,0,1.3-0.582,1.3-1.3V4.3 C21,3.582,20.418,3,19.7,3z M8.339,18.338H5.667v-8.59h2.672V18.338z M7.004,8.574c-0.857,0-1.549-0.694-1.549-1.548 c0-0.855,0.691-1.548,1.549-1.548c0.854,0,1.547,0.694,1.547,1.548C8.551,7.881,7.858,8.574,7.004,8.574z M18.339,18.338h-2.669 v-4.177c0-0.996-0.017-2.278-1.387-2.278c-1.389,0-1.601,1.086-1.601,2.206v4.249h-2.667v-8.59h2.559v1.174h0.037 c0.356-0.675,1.227-1.387,2.526-1.387c2.703,0,3.203,1.779,3.203,4.092V18.338z"></path></svg><span class="wp-block-social-link-label screen-reader-text">LinkedIn</span></a></li>

<li class="wp-social-link wp-social-link-github  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://github.com/topics/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M12,2C6.477,2,2,6.477,2,12c0,4.419,2.865,8.166,6.839,9.489c0.5,0.09,0.682-0.218,0.682-0.484 c0-0.236-0.009-0.866-0.014-1.699c-2.782,0.602-3.369-1.34-3.369-1.34c-0.455-1.157-1.11-1.465-1.11-1.465 c-0.909-0.62,0.069-0.608,0.069-0.608c1.004,0.071,1.532,1.03,1.532,1.03c0.891,1.529,2.341,1.089,2.91,0.833 c0.091-0.647,0.349-1.086,0.635-1.337c-2.22-0.251-4.555-1.111-4.555-4.943c0-1.091,0.39-1.984,1.03-2.682 C6.546,8.54,6.202,7.524,6.746,6.148c0,0,0.84-0.269,2.75,1.025C10.295,6.95,11.15,6.84,12,6.836 c0.85,0.004,1.705,0.114,2.504,0.336c1.909-1.294,2.748-1.025,2.748-1.025c0.546,1.376,0.202,2.394,0.1,2.646 c0.64,0.699,1.026,1.591,1.026,2.682c0,3.841-2.337,4.687-4.565,4.935c0.359,0.307,0.679,0.917,0.679,1.852 c0,1.335-0.012,2.415-0.012,2.741c0,0.269,0.18,0.579,0.688,0.481C19.138,20.161,22,16.416,22,12C22,6.477,17.523,2,12,2z"></path></svg><span class="wp-block-social-link-label screen-reader-text">GitHub</span></a></li>

<li class="wp-social-link wp-social-link-youtube  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.youtube.com/c/XojoInc" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M21.8,8.001c0,0-0.195-1.378-0.795-1.985c-0.76-0.797-1.613-0.801-2.004-0.847c-2.799-0.202-6.997-0.202-6.997-0.202 h-0.009c0,0-4.198,0-6.997,0.202C4.608,5.216,3.756,5.22,2.995,6.016C2.395,6.623,2.2,8.001,2.2,8.001S2,9.62,2,11.238v1.517 c0,1.618,0.2,3.237,0.2,3.237s0.195,1.378,0.795,1.985c0.761,0.797,1.76,0.771,2.205,0.855c1.6,0.153,6.8,0.201,6.8,0.201 s4.203-0.006,7.001-0.209c0.391-0.047,1.243-0.051,2.004-0.847c0.6-0.607,0.795-1.985,0.795-1.985s0.2-1.618,0.2-3.237v-1.517 C22,9.62,21.8,8.001,21.8,8.001z M9.935,14.594l-0.001-5.62l5.404,2.82L9.935,14.594z"></path></svg><span class="wp-block-social-link-label screen-reader-text">YouTube</span></a></li></ul>



<p class="has-text-align-center has-text-color has-link-color wp-elements-a0a2ac26ad214a49dac577734d259176" style="color:#84bd00"><a href="https://xojo.com/download/" target="_blank" rel="noreferrer noopener">Download Xojo</a></p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>DBKit v2: Data-Aware Controls That Do the Work</title>
		<link>https://blog.xojo.com/2026/10/21/dbkit-v2-data-aware-controls-that-do-the-work/</link>
		
		<dc:creator><![CDATA[Geoff Perlman]]></dc:creator>
		<pubDate>Wed, 21 Oct 2026 20:23:41 +0000</pubDate>
				<category><![CDATA[Database]]></category>
		<category><![CDATA[General]]></category>
		<category><![CDATA[DBkit]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=16718</guid>

					<description><![CDATA[DBKit v2 eliminates virtually all the code required to use DBKit. Open the database. Run the query. Copy values from the row into the controls.&#8230;]]></description>
										<content:encoded><![CDATA[
<p>DBKit v2 eliminates virtually all the code required to use DBKit. Open the database. Run the query. Copy values from the row into the controls. Copy them back when the user edits. Handle the errors. Repeat on every window or webpage; and none of it requires any code with DBKit.</p>



<p>DBKit is a set of data-aware controls for Xojo: drop a DBKit.TextField on a layout, point it at a database, table, and column, and it loads, displays, and saves the value by itself. The query code, the glue code, the error handling: gone.</p>



<p>Version 1 proved the idea. It covered the basics and saved real time. But it still left work on your plate: filling listboxes, keeping controls in sync, writing the code that moves data back and forth.</p>



<p>Version 2 finishes the job. The controls are now fully self-sufficient. In most cases there is no database code left to write at all. The CustomersWindow from the DBKit Desktop Example project has no code at all. The same is true of the CustomersPage of the DBKit Web Example.</p>



<figure class="wp-block-image size-large"><img decoding="async" width="1024" height="699" src="https://blog.xojo.com/wp-content/uploads/2026/10/CleanShot-2026-10-17-at-11.29.18-AM@2x-1024x699.png" alt="" class="wp-image-16719" srcset="https://blog.xojo.com/wp-content/uploads/2026/10/CleanShot-2026-10-17-at-11.29.18-AM@2x-1024x699.png 1024w, https://blog.xojo.com/wp-content/uploads/2026/10/CleanShot-2026-10-17-at-11.29.18-AM@2x-300x205.png 300w, https://blog.xojo.com/wp-content/uploads/2026/10/CleanShot-2026-10-17-at-11.29.18-AM@2x-768x524.png 768w, https://blog.xojo.com/wp-content/uploads/2026/10/CleanShot-2026-10-17-at-11.29.18-AM@2x.png 1404w" sizes="(max-width: 1024px) 100vw, 1024px" /></figure>



<p><strong>DBKit.Table.</strong>&nbsp;This is an all-new control built from the ground up: it fetches only the rows it needs to display, so whether you have hundreds of rows or millions no longer matters. Rows load fast. Table replaces the old ListBox-based approach entirely, on Desktop and Web alike.</p>



<h2 class="wp-block-heading">What is new</h2>



<p><strong>DBKit.Row.</strong>&nbsp;This is the heart of v2. A Row is the object every row event hands you, and it is how you work with data everywhere in DBKit. Read and write column values by name:&nbsp;<code>row.Column("quantity")</code>. Values from related tables use qualified names:&nbsp;<code>row.Column("products.price")</code>. Columns that do not exist in the database, like calculated columns, work exactly the same way: assign them and the table picks them up. One object, one API, everywhere.</p>



<p><strong>Row events.</strong>&nbsp;v2 introduces a full set of row events covering the row&#8217;s whole lifecycle: RowDisplayed, RowLoaded, RowChanged, RowEditing, RowSaving, RowSaved, RowCreated, RowDeleted, RowUndone, and RowNotSelected. RowDisplayed fires for each row as it appears, which is where per-row customization lives, including calculated columns:</p>



<pre class="wp-block-code"><code>Sub RowDisplayed(row As DBKit.Row) Handles RowDisplayed
  row.Column("linetotal") = row.Column("quantity") * row.Column("products.price")
End Sub</code></pre>



<p><strong>Calculated columns.</strong>&nbsp;Some values do not live in the database. A line total is quantity times price. Define the column, compute it in RowDisplayed, and the table treats it like any other column, including in totals and inline editing.</p>



<p><strong>Related rows, automatically.</strong>&nbsp;Tell DBKit about your table relationships and it loads related rows on its own. You just set the TableRelationships property in the Inspector, one relationship per line:</p>



<pre class="wp-block-code"><code>invoices.customerid=customers.id</code></pre>



<p>DBKit.Table displays related columns with no extra work, and on DBKit layouts, controls bound to related-table columns load automatically too. That&nbsp;<code>products.price</code>&nbsp;in the example above comes from the related products table. No JOINs in your code.</p>



<p><strong>Inline editing.</strong>&nbsp;Mark columns editable and users can edit cells right in the table. Edits flow through the same row events, so calculated columns like that line total stay correct automatically.</p>



<p><strong>A much more powerful SearchField.</strong>&nbsp;Drop a DBKit.SearchField on a layout and users can search as they type, with no code at all. It automatically searches every displayed column whose data type matches what they enter: text matches from the beginning of the value, quotes force an exact match, &gt; and &lt; compare numbers, two periods define a range, dates work in local or ISO format, and typing a column name first searches just that column.</p>



<p><strong>Database connections without the code.</strong>&nbsp;DBKit works directly with DatabaseConnection objects. Configure the connection in the IDE for SQLite, MySQL, PostgreSQL, or ODBC, hand it to DBKit, and there is no connection code to write.</p>



<p><strong>DBKit layouts.</strong>&nbsp;DBKit.Window, DBKit.Page, and DBKit.Container are layouts with a simple idea: bind the layout to a table, and every DBKit control on it shows the current row. The layout handles loading the row, saving edits, adding and deleting rows, undo, navigating between rows, and loading related rows. You arrange controls; DBKit does the rest.</p>



<p><strong>Nearly identical on Desktop and Web.</strong>&nbsp;Everything above works the same in desktop and web apps: the same controls, the same events, the same Row object. Learn it once, use it everywhere.</p>



<h2 class="wp-block-heading">If you are coming from v1</h2>



<p>The&nbsp;<a href="https://documentation.xojo.com/topics/databases/dbkit-conversion-guide.html">conversion guide</a>&nbsp;is short, and most of it is code to delete. That is the point.</p>



<h2 class="wp-block-heading">Try it</h2>



<p>DBKit v2 is available now. The DBKit Desktop Example and DBKit Web Example projects show it all working together: customers, invoices, and invoice items, with barely any database code in sight. The customers page in the web example, which displays and edits complete customer records, contains no code at all. Not one line. And that is just the start: v2 has a lot more new features, so check out the&nbsp;<a href="https://documentation.xojo.com/versions/2026r3/topics/databases/dbkit.html">DBKit overview</a>&nbsp;and the&nbsp;<a href="https://documentation.xojo.com/versions/2026r3/api/databases/dbkit/index.html">Classes reference</a>.</p>



<p>If you&#8217;re new to DBKit, try out the DBKit tutorials for <a href="https://documentation.xojo.com/versions/2026r3/getting_started/tutorials/dbkit_desktop_tutorial.html">desktop</a> and <a href="https://documentation.xojo.com/versions/2026r3/getting_started/tutorials/dbkit_web_tutorial.html">web</a>.</p>



<p><em>Geoff Perlman is the Founder and CEO of Xojo. When he’s not leading the Xojo team he can be found playing drums in Austin, Texas and spending time with his family.</em></p>



<ul class="wp-block-social-links has-normal-icon-size is-content-justification-center is-layout-flex wp-container-core-social-links-is-layout-16018d1d wp-block-social-links-is-layout-flex"><li class="wp-social-link wp-social-link-facebook  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.facebook.com/goxojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M12 2C6.5 2 2 6.5 2 12c0 5 3.7 9.1 8.4 9.9v-7H7.9V12h2.5V9.8c0-2.5 1.5-3.9 3.8-3.9 1.1 0 2.2.2 2.2.2v2.5h-1.3c-1.2 0-1.6.8-1.6 1.6V12h2.8l-.4 2.9h-2.3v7C18.3 21.1 22 17 22 12c0-5.5-4.5-10-10-10z"></path></svg><span class="wp-block-social-link-label screen-reader-text">Facebook</span></a></li>

<li class="wp-social-link wp-social-link-x  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://x.com/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M13.982 10.622 20.54 3h-1.554l-5.693 6.618L8.745 3H3.5l6.876 10.007L3.5 21h1.554l6.012-6.989L15.868 21h5.245l-7.131-10.378Zm-2.128 2.474-.697-.997-5.543-7.93H8l4.474 6.4.697.996 5.815 8.318h-2.387l-4.745-6.787Z" /></svg><span class="wp-block-social-link-label screen-reader-text">X</span></a></li>

<li class="wp-social-link wp-social-link-linkedin  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.linkedin.com/company/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M19.7,3H4.3C3.582,3,3,3.582,3,4.3v15.4C3,20.418,3.582,21,4.3,21h15.4c0.718,0,1.3-0.582,1.3-1.3V4.3 C21,3.582,20.418,3,19.7,3z M8.339,18.338H5.667v-8.59h2.672V18.338z M7.004,8.574c-0.857,0-1.549-0.694-1.549-1.548 c0-0.855,0.691-1.548,1.549-1.548c0.854,0,1.547,0.694,1.547,1.548C8.551,7.881,7.858,8.574,7.004,8.574z M18.339,18.338h-2.669 v-4.177c0-0.996-0.017-2.278-1.387-2.278c-1.389,0-1.601,1.086-1.601,2.206v4.249h-2.667v-8.59h2.559v1.174h0.037 c0.356-0.675,1.227-1.387,2.526-1.387c2.703,0,3.203,1.779,3.203,4.092V18.338z"></path></svg><span class="wp-block-social-link-label screen-reader-text">LinkedIn</span></a></li>

<li class="wp-social-link wp-social-link-github  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://github.com/topics/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M12,2C6.477,2,2,6.477,2,12c0,4.419,2.865,8.166,6.839,9.489c0.5,0.09,0.682-0.218,0.682-0.484 c0-0.236-0.009-0.866-0.014-1.699c-2.782,0.602-3.369-1.34-3.369-1.34c-0.455-1.157-1.11-1.465-1.11-1.465 c-0.909-0.62,0.069-0.608,0.069-0.608c1.004,0.071,1.532,1.03,1.532,1.03c0.891,1.529,2.341,1.089,2.91,0.833 c0.091-0.647,0.349-1.086,0.635-1.337c-2.22-0.251-4.555-1.111-4.555-4.943c0-1.091,0.39-1.984,1.03-2.682 C6.546,8.54,6.202,7.524,6.746,6.148c0,0,0.84-0.269,2.75,1.025C10.295,6.95,11.15,6.84,12,6.836 c0.85,0.004,1.705,0.114,2.504,0.336c1.909-1.294,2.748-1.025,2.748-1.025c0.546,1.376,0.202,2.394,0.1,2.646 c0.64,0.699,1.026,1.591,1.026,2.682c0,3.841-2.337,4.687-4.565,4.935c0.359,0.307,0.679,0.917,0.679,1.852 c0,1.335-0.012,2.415-0.012,2.741c0,0.269,0.18,0.579,0.688,0.481C19.138,20.161,22,16.416,22,12C22,6.477,17.523,2,12,2z"></path></svg><span class="wp-block-social-link-label screen-reader-text">GitHub</span></a></li>

<li class="wp-social-link wp-social-link-youtube  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.youtube.com/c/XojoInc" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M21.8,8.001c0,0-0.195-1.378-0.795-1.985c-0.76-0.797-1.613-0.801-2.004-0.847c-2.799-0.202-6.997-0.202-6.997-0.202 h-0.009c0,0-4.198,0-6.997,0.202C4.608,5.216,3.756,5.22,2.995,6.016C2.395,6.623,2.2,8.001,2.2,8.001S2,9.62,2,11.238v1.517 c0,1.618,0.2,3.237,0.2,3.237s0.195,1.378,0.795,1.985c0.761,0.797,1.76,0.771,2.205,0.855c1.6,0.153,6.8,0.201,6.8,0.201 s4.203-0.006,7.001-0.209c0.391-0.047,1.243-0.051,2.004-0.847c0.6-0.607,0.795-1.985,0.795-1.985s0.2-1.618,0.2-3.237v-1.517 C22,9.62,21.8,8.001,21.8,8.001z M9.935,14.594l-0.001-5.62l5.404,2.82L9.935,14.594z"></path></svg><span class="wp-block-social-link-label screen-reader-text">YouTube</span></a></li></ul>



<p class="has-text-align-center has-text-color has-link-color wp-elements-a0a2ac26ad214a49dac577734d259176" style="color:#84bd00"><a href="https://xojo.com/download/" target="_blank" rel="noreferrer noopener">Download Xojo</a></p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>WinUI Support Moves to Beta</title>
		<link>https://blog.xojo.com/2026/10/20/winui-support-moves-to-beta/</link>
		
		<dc:creator><![CDATA[William Yu]]></dc:creator>
		<pubDate>Tue, 20 Oct 2026 16:53:54 +0000</pubDate>
				<category><![CDATA[Desktop]]></category>
		<category><![CDATA[General]]></category>
		<category><![CDATA[Learning]]></category>
		<category><![CDATA[Windows]]></category>
		<category><![CDATA[2026r3]]></category>
		<category><![CDATA[WinUI]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=16648</guid>

					<description><![CDATA[We&#8217;ve been making steady progress on our WinUI support for Windows, and we&#8217;re excited to announce that it has now moved from&#160;Experimental to Beta in&#8230;]]></description>
										<content:encoded><![CDATA[
<p>We&#8217;ve been making steady progress on our WinUI support for Windows, and we&#8217;re excited to announce that it has now moved from&nbsp;<strong>Experimental to Beta</strong> in Xojo 2026r3.</p>



<p>There&#8217;s still work to be done, but WinUI has reached an important milestone. We&#8217;re encouraging developers to start testing their existing applications with WinUI and, most importantly, to let us know when you encounter something that doesn&#8217;t work as expected.</p>



<h2 class="wp-block-heading">Menus and Contextual Menus</h2>



<p>One of the biggest additions in this release (Xojo 2026r3) is support for WinUI based Menus and Contextual Menus.</p>



<p>Menus are an essential part of many desktop applications, and bringing them to WinUI makes it possible to build more complete, native-feeling Windows applications with Xojo.</p>



<h2 class="wp-block-heading">Symbol Support</h2>



<p>We&#8217;ve also added support for symbols to a variety of controls, including <code>DesktopPopupMenu</code> and <code>Menus</code>.</p>



<p>Symbols provide a convenient way to add familiar visual indicators and icons to your application&#8217;s interface while taking advantage of the system&#8217;s available symbol resources. This gives you another way to create modern Windows interfaces without having to manage and distribute every image yourself. Note that Symbol support is only available for WinUI, Linux and macOS.</p>



<h2 class="wp-block-heading">Picture.SystemImage&nbsp;Comes to Desktop</h2>



<p>Originally available for iOS projects,&nbsp;<code>Picture.SystemImage</code>&nbsp;is now available on desktop as well. This provides a simple way to access system-provided images and symbols from your Xojo applications.</p>



<p>The list of supported symbols can be found here:</p>



<ul class="wp-block-list">
<li>Windows:&nbsp;<a href="https://learn.microsoft.com/en-us/windows/apps/design/iconography/segoe-fluent-icons-font" target="_blank" rel="noreferrer noopener">https://learn.microsoft.com/en-us/windows/apps/design/iconography/segoe-fluent-icons-font</a></li>



<li>Linux:&nbsp;<a href="https://specifications.freedesktop.org/icon-naming" target="_blank" rel="noreferrer noopener">https://specifications.freedesktop.org/icon-naming</a></li>



<li>macOS:&nbsp;<a href="https://developer.apple.com/design/human-interface-guidelines/sf-symbols" target="_blank" rel="noreferrer noopener">https://developer.apple.com/design/human-interface-guidelines/sf-symbols</a></li>
</ul>



<p>On Windows, symbols are loaded from the Segoe Fluent Icons font (on Windows 10 they are loaded from the Segoe MDL2 Assets), so this feature is supported on both WinUI and non-WinUI Windows targets.</p>



<h2 class="wp-block-heading">Designed with WinUI in Mind</h2>



<p>As we add new functionality and controls, we&#8217;re designing with modern desktop platforms like WinUI in mind from the start. This means not only adding WinUI support to existing controls, but also improving the overall desktop experience where we can.</p>



<p>For example, our new <code><a href="https://documentation.xojo.com/api/user_interface/desktop/desktoptable.html" target="_blank" rel="noreferrer noopener">DesktopTable</a></code> provides a much better WinUI look and feel than the older <code>DesktopListBox</code> control, giving you a more modern foundation for displaying tabular data.</p>



<figure class="wp-block-image size-large"><img decoding="async" width="810" height="701" src="https://blog.xojo.com/wp-content/uploads/2026/10/WinUIHierarchical.png" alt="" class="wp-image-16672" srcset="https://blog.xojo.com/wp-content/uploads/2026/10/WinUIHierarchical.png 810w, https://blog.xojo.com/wp-content/uploads/2026/10/WinUIHierarchical-300x260.png 300w, https://blog.xojo.com/wp-content/uploads/2026/10/WinUIHierarchical-768x665.png 768w" sizes="(max-width: 810px) 100vw, 810px" /></figure>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="934" height="677" src="https://blog.xojo.com/wp-content/uploads/2026/10/WinUITable.png" alt="" class="wp-image-16673" srcset="https://blog.xojo.com/wp-content/uploads/2026/10/WinUITable.png 934w, https://blog.xojo.com/wp-content/uploads/2026/10/WinUITable-300x217.png 300w, https://blog.xojo.com/wp-content/uploads/2026/10/WinUITable-768x557.png 768w" sizes="auto, (max-width: 934px) 100vw, 934px" /></figure>



<p>We&#8217;re also making existing controls take better advantage of the features available on modern platforms. <code><a href="https://documentation.xojo.com/api/user_interface/desktop/desktoppopupmenu.html" target="_blank" rel="noreferrer noopener">PopupMenu</a></code> now makes use of the Icons assigned to its <code>MenuItems</code>, so when building for WinUI, Linux, or macOS, those Icons automatically appear in your <code>PopupMenus</code>.</p>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="637" height="305" src="https://blog.xojo.com/wp-content/uploads/2026/10/WinUIPopupMenuIcons-1.png" alt="" class="wp-image-16657" srcset="https://blog.xojo.com/wp-content/uploads/2026/10/WinUIPopupMenuIcons-1.png 637w, https://blog.xojo.com/wp-content/uploads/2026/10/WinUIPopupMenuIcons-1-300x144.png 300w" sizes="auto, (max-width: 637px) 100vw, 637px" /></figure>



<p>Even familiar controls are getting an update. <code>SegmentedButtons</code> can now properly receive focus and be navigated between segments using the keyboard.</p>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="904" height="253" src="https://blog.xojo.com/wp-content/uploads/2026/10/WinUISegmentedButton.png" alt="" class="wp-image-16680" srcset="https://blog.xojo.com/wp-content/uploads/2026/10/WinUISegmentedButton.png 904w, https://blog.xojo.com/wp-content/uploads/2026/10/WinUISegmentedButton-300x84.png 300w, https://blog.xojo.com/wp-content/uploads/2026/10/WinUISegmentedButton-768x215.png 768w" sizes="auto, (max-width: 904px) 100vw, 904px" /></figure>



<p>&nbsp;<code>MessageBox</code>&nbsp;is now dark-mode aware when built with WinUI, allowing it to better match the appearance of your application and the user&#8217;s system settings.</p>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="593" height="280" src="https://blog.xojo.com/wp-content/uploads/2026/10/WinUIMessageBox.png" alt="" class="wp-image-16654" srcset="https://blog.xojo.com/wp-content/uploads/2026/10/WinUIMessageBox.png 593w, https://blog.xojo.com/wp-content/uploads/2026/10/WinUIMessageBox-300x142.png 300w" sizes="auto, (max-width: 593px) 100vw, 593px" /></figure>



<h2 class="wp-block-heading">From Experimental to Beta</h2>



<p>Moving WinUI support from Experimental to&nbsp;Beta&nbsp;is an important step for Xojo.</p>



<p>Beta means that we believe WinUI is ready for more developers to begin using and testing in real-world applications. It does&nbsp;not&nbsp;mean that every feature is complete or that there aren&#8217;t still issues to address. There is more work ahead, and your feedback will be an important part of getting WinUI ready for production use.</p>



<h2 class="wp-block-heading">Give WinUI a Try</h2>



<p>WinUI represents an important step forward for Xojo on Windows, and we&#8217;re excited about where it is heading.</p>



<p>If you&#8217;ve been waiting to try WinUI, <strong>now is the time</strong>. Start testing your applications, explore the new functionality, and let us know what you discover. Your feedback will help us make Xojo&#8217;s WinUI support a great foundation for building modern Windows applications.</p>



<p><em><em><em>William Yu grew up in Canada learning to program BASIC on a Vic-20. He is Xojo’s resident Windows and Linux engineer, among his many other skills. Some may say he has joined the dark side here in the USA, but he will always be a Canadian at heart.</em></em></em></p>



<ul class="wp-block-social-links has-normal-icon-size is-content-justification-center is-layout-flex wp-container-core-social-links-is-layout-16018d1d wp-block-social-links-is-layout-flex"><li class="wp-social-link wp-social-link-facebook  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.facebook.com/goxojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M12 2C6.5 2 2 6.5 2 12c0 5 3.7 9.1 8.4 9.9v-7H7.9V12h2.5V9.8c0-2.5 1.5-3.9 3.8-3.9 1.1 0 2.2.2 2.2.2v2.5h-1.3c-1.2 0-1.6.8-1.6 1.6V12h2.8l-.4 2.9h-2.3v7C18.3 21.1 22 17 22 12c0-5.5-4.5-10-10-10z"></path></svg><span class="wp-block-social-link-label screen-reader-text">Facebook</span></a></li>

<li class="wp-social-link wp-social-link-x  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://x.com/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M13.982 10.622 20.54 3h-1.554l-5.693 6.618L8.745 3H3.5l6.876 10.007L3.5 21h1.554l6.012-6.989L15.868 21h5.245l-7.131-10.378Zm-2.128 2.474-.697-.997-5.543-7.93H8l4.474 6.4.697.996 5.815 8.318h-2.387l-4.745-6.787Z" /></svg><span class="wp-block-social-link-label screen-reader-text">X</span></a></li>

<li class="wp-social-link wp-social-link-linkedin  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.linkedin.com/company/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M19.7,3H4.3C3.582,3,3,3.582,3,4.3v15.4C3,20.418,3.582,21,4.3,21h15.4c0.718,0,1.3-0.582,1.3-1.3V4.3 C21,3.582,20.418,3,19.7,3z M8.339,18.338H5.667v-8.59h2.672V18.338z M7.004,8.574c-0.857,0-1.549-0.694-1.549-1.548 c0-0.855,0.691-1.548,1.549-1.548c0.854,0,1.547,0.694,1.547,1.548C8.551,7.881,7.858,8.574,7.004,8.574z M18.339,18.338h-2.669 v-4.177c0-0.996-0.017-2.278-1.387-2.278c-1.389,0-1.601,1.086-1.601,2.206v4.249h-2.667v-8.59h2.559v1.174h0.037 c0.356-0.675,1.227-1.387,2.526-1.387c2.703,0,3.203,1.779,3.203,4.092V18.338z"></path></svg><span class="wp-block-social-link-label screen-reader-text">LinkedIn</span></a></li>

<li class="wp-social-link wp-social-link-github  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://github.com/topics/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M12,2C6.477,2,2,6.477,2,12c0,4.419,2.865,8.166,6.839,9.489c0.5,0.09,0.682-0.218,0.682-0.484 c0-0.236-0.009-0.866-0.014-1.699c-2.782,0.602-3.369-1.34-3.369-1.34c-0.455-1.157-1.11-1.465-1.11-1.465 c-0.909-0.62,0.069-0.608,0.069-0.608c1.004,0.071,1.532,1.03,1.532,1.03c0.891,1.529,2.341,1.089,2.91,0.833 c0.091-0.647,0.349-1.086,0.635-1.337c-2.22-0.251-4.555-1.111-4.555-4.943c0-1.091,0.39-1.984,1.03-2.682 C6.546,8.54,6.202,7.524,6.746,6.148c0,0,0.84-0.269,2.75,1.025C10.295,6.95,11.15,6.84,12,6.836 c0.85,0.004,1.705,0.114,2.504,0.336c1.909-1.294,2.748-1.025,2.748-1.025c0.546,1.376,0.202,2.394,0.1,2.646 c0.64,0.699,1.026,1.591,1.026,2.682c0,3.841-2.337,4.687-4.565,4.935c0.359,0.307,0.679,0.917,0.679,1.852 c0,1.335-0.012,2.415-0.012,2.741c0,0.269,0.18,0.579,0.688,0.481C19.138,20.161,22,16.416,22,12C22,6.477,17.523,2,12,2z"></path></svg><span class="wp-block-social-link-label screen-reader-text">GitHub</span></a></li>

<li class="wp-social-link wp-social-link-youtube  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.youtube.com/c/XojoInc" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M21.8,8.001c0,0-0.195-1.378-0.795-1.985c-0.76-0.797-1.613-0.801-2.004-0.847c-2.799-0.202-6.997-0.202-6.997-0.202 h-0.009c0,0-4.198,0-6.997,0.202C4.608,5.216,3.756,5.22,2.995,6.016C2.395,6.623,2.2,8.001,2.2,8.001S2,9.62,2,11.238v1.517 c0,1.618,0.2,3.237,0.2,3.237s0.195,1.378,0.795,1.985c0.761,0.797,1.76,0.771,2.205,0.855c1.6,0.153,6.8,0.201,6.8,0.201 s4.203-0.006,7.001-0.209c0.391-0.047,1.243-0.051,2.004-0.847c0.6-0.607,0.795-1.985,0.795-1.985s0.2-1.618,0.2-3.237v-1.517 C22,9.62,21.8,8.001,21.8,8.001z M9.935,14.594l-0.001-5.62l5.404,2.82L9.935,14.594z"></path></svg><span class="wp-block-social-link-label screen-reader-text">YouTube</span></a></li></ul>



<p class="has-text-align-center has-text-color has-link-color wp-elements-a0a2ac26ad214a49dac577734d259176" style="color:#84bd00"><a href="https://xojo.com/download/" target="_blank" rel="noreferrer noopener">Download Xojo</a></p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>I Asked Claude Code to &#8220;Make Something Wow&#8221; in Xojo Web. Here&#8217;s What It Built.</title>
		<link>https://blog.xojo.com/2026/10/20/i-asked-claude-code-to-make-something-wow-in-xojo-web-heres-what-it-built/</link>
		
		<dc:creator><![CDATA[Ricardo Cruz]]></dc:creator>
		<pubDate>Tue, 20 Oct 2026 16:53:39 +0000</pubDate>
				<category><![CDATA[General]]></category>
		<category><![CDATA[Web]]></category>
		<category><![CDATA[2026r3]]></category>
		<category><![CDATA[AI]]></category>
		<category><![CDATA[AI Code Generation]]></category>
		<category><![CDATA[Git]]></category>
		<category><![CDATA[Xojo Web]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=16664</guid>

					<description><![CDATA[Agentic Mode is one of the big additions in 2026r3. It lets Claude Code and other coding agents drive the Xojo IDE. Other posts in&#8230;]]></description>
										<content:encoded><![CDATA[
<p>Agentic Mode is one of the big additions in 2026r3. It lets Claude Code and other coding agents drive the Xojo IDE. Other posts in this series cover things like the IDE picking up file changes from disk. In this one, I want to show you why I think <a href="https://documentation.xojo.com/getting_started/using_the_ide/agentic_mode.html" target="_blank" rel="noreferrer noopener">Agentic Mode</a> is a great fit for Xojo Web projects.</p>



<p>While I&#8217;ve been using Claude Code and I refer to it through this blog post, any other coding agent that knows how to read the AGENTS.md file should work just fine as well. We&#8217;d love to hear your AI stories and we even have <a href="https://forum.xojo.com/c/ai/92" target="_blank" rel="noreferrer noopener">a dedicated forum category for AI related posts</a>.</p>



<p>I&#8217;ve been testing Agentic Mode for a while, and one session stands out. I gave Claude Code an intentionally vague prompt, something like &#8220;make something wow, the more wow, the better&#8221;. This is what Opus 5.5 came with after 11 minutes:</p>



<figure class="wp-block-video"><video height="1322" style="aspect-ratio: 2550 / 1322;" width="2550" controls src="https://blog.xojo.com/wp-content/uploads/2026/10/globe-demo.mp4"></video></figure>



<p>Far from perfect, but still very cool!</p>



<p>It&#8217;s a mission control panel showing a 3D globe with the earthquakes of the last seven days from the USGS feed, the live position and trajectory of the International Space Station, and the day/night line. It also has a command palette. And it&#8217;s multiplayer: every web session joins as a crew member, and you can see each other appear and move around in real time. Click a crew member and you jump to their view.</p>



<p>Let me show you how we got there.</p>



<h2 class="wp-block-heading">The Setup</h2>



<p>There isn&#8217;t much to it, honestly. I created a new Xojo Web project, saved it in the plain text file format, and enabled Agentic Mode.</p>



<p>When you turn Agentic Mode on, the IDE creates an AGENTS.md file in the project folder if there isn&#8217;t one already. That file points to XOJO-CODING.md, which explains to the agent how to work with the IDE. It also links to example projects for each Xojo target, including Web.</p>



<p>There&#8217;s no MCP server involved, no plugin to install. The whole protocol is a couple of text files. When the agent wants to build and run the project, it touches a file called XojoRunProject.txt, and the IDE does the rest. If something doesn&#8217;t compile, the IDE writes the errors to XojoCompileErrors.txt so the agent can read them.</p>



<p>Claude Code read the instructions and followed them perfectly from the very first prompt.</p>



<h2 class="wp-block-heading">A JavaScript app in a Xojo shell? No, thanks</h2>



<p>The first version was impressive, but there was a catch. Claude Code built almost everything in JavaScript. It worked, but what I had was a JavaScript web app inside a Xojo Web shell, and that&#8217;s not really the point.</p>



<p>So I asked it to refine the project, using WebContainers and regular Xojo Web controls as much as possible. This is how the project looks in the IDE afterwards:</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="658" src="https://blog.xojo.com/wp-content/uploads/2026/10/Captura-de-pantalla-2026-10-07-a-las-11.35.24-1024x658.png" alt="" class="wp-image-16666" srcset="https://blog.xojo.com/wp-content/uploads/2026/10/Captura-de-pantalla-2026-10-07-a-las-11.35.24-1024x658.png 1024w, https://blog.xojo.com/wp-content/uploads/2026/10/Captura-de-pantalla-2026-10-07-a-las-11.35.24-300x193.png 300w, https://blog.xojo.com/wp-content/uploads/2026/10/Captura-de-pantalla-2026-10-07-a-las-11.35.24-768x493.png 768w, https://blog.xojo.com/wp-content/uploads/2026/10/Captura-de-pantalla-2026-10-07-a-las-11.35.24-1536x986.png 1536w, https://blog.xojo.com/wp-content/uploads/2026/10/Captura-de-pantalla-2026-10-07-a-las-11.35.24.png 1872w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<p>The page is now built from reusable pieces you&#8217;d recognize from any Xojo project: a StatsPanel, a CrewPanel with a CrewRow for each crew member, QuakeCard, LegendPanel, HintBar, a ToastStack for notifications, and so on.</p>



<p>JavaScript didn&#8217;t disappear completely, and that&#8217;s fine. It stayed where it really makes sense. GlobeControl is a WebSDKUIControl wrapping the&nbsp;<a href="https://globe.gl/" target="_blank" rel="noreferrer noopener">Globe.GL</a>&nbsp;library, which handles the 3D globe. Claude Code also wrote a few other Web SDK controls for things that really should happen in the browser, like opening the command palette when you press Cmd+K. You wouldn&#8217;t want a round trip to the server just to show a palette.</p>



<p>If you open the project, you&#8217;ll be able to follow it, and change it, like any other Xojo Web app.</p>



<p>This is my main tip if you try this yourself: tell the agent explicitly that you want a maintainable Xojo app. Otherwise, it will reach for whatever it knows best in order to please you.</p>



<h2 class="wp-block-heading">Compile, Fix, Repeat</h2>



<p>Every now and then, Claude Code wrote something that didn&#8217;t compile. A syntax error here, a wrong type there. The good news is that it saw the error in XojoCompileErrors.txt right away, fixed it and built the project again. I didn&#8217;t have to jump in a single time.</p>



<p>If you&#8217;ve ever copied and pasted code from a chat window into the IDE, then copied the compile error back into the chat, you know how much friction this removes.</p>



<h2 class="wp-block-heading">Testing in a real browser</h2>



<p>This is where it gets interesting for web projects. Code that compiles isn&#8217;t necessarily code that works, and in a web app, the only way to know for sure is to open it in a browser.</p>



<p>With the Claude in Chrome extension, Claude Code can do exactly that. You just need Google Chrome open, with the extension installed and logged in. From there, the agent runs the app, opens it in Chrome, clicks around and tests the project end to end.</p>



<p>When something looks a bit off at runtime, it takes a screenshot of the browser, tweaks the project, runs it again, and keeps looping until it looks right. Since a multiplayer feature needs more than one user, it opened several tabs to check that the crew members showed up for each other, and closed them once it didn&#8217;t need them anymore. And if the Chrome extension isn&#8217;t available for whatever reason (like using other coding agents), it can fall back to Puppeteer and drive a browser on its own.</p>



<p>In practice, this means I could describe a feature, go outside and have a coffee, and come back to find it implemented, tested and polished.</p>



<p>If you&#8217;re using other targets, feel free to ask your coding agent to embed an MCP server and use it to test the app. It will find its way to test it, no matter what. It will ask you to do a final human review on specific new features, but overall, the agent will be on autopilot most of the time.</p>



<h2 class="wp-block-heading">A few rough edges</h2>



<p>This is a promising setup, but it isn&#8217;t perfect yet.</p>



<p>If two or more coding agents try to compile different apps at the same time (and I mean the very same second), the IDE may tell you the compiler is busy, or that it couldn&#8217;t find the debug app. If you are not in front of your computer, you might find the session stuck, waiting for some human help.</p>



<p>The limitations I&#8217;ve found so far were easy to work around, by explaining to Claude Code what to do when it happens. More on that in a moment.</p>



<h2 class="wp-block-heading">Teaching your agent new tricks</h2>



<p>XOJO-CODING.md will keep improving, and we&#8217;ll keep updating the example projects to give coding agents more context. Still, sooner or later you&#8217;ll find something the agent doesn&#8217;t know how to do.</p>



<p>In my case, Claude Code didn&#8217;t know how to encode constants, or how to use folders. It was dropping every single class into the root of the project. It worked, but imagine finding your way around a big project like that.</p>



<p>If your project is under Git, this is really easy to fix. Tell the agent you&#8217;re about to create some nested folders, or a constant with special characters. It will take a look at the repository and ask you to make the change in the IDE and save the project. Once you&#8217;ve done it, tell Claude Code, and it will look at the differences to see how the IDE wrote those files. From there, you can let it refactor the project and move everything into folders.</p>



<p>Then comes the important part: ask the agent to write down what it learned in AGENTS.md. Every new session reads that file, so the next one will already know how the IDE creates project files, and how you like to work. This is also where it added the note about the busy compiler.</p>



<p>If you&#8217;re working on an existing project, it gets even easier. You won&#8217;t need to show the agent how to use folders if your project already uses them, because it will follow what&#8217;s there. The more you use it, the better it gets. And the bigger the project, the easier it is for the agent to add new features in the same way you&#8217;re already working.</p>



<h2 class="wp-block-heading">Try it yourself!</h2>



<p>You can download the Mission Control project here:</p>



<p><a href="https://blog.xojo.com/wp-content/uploads/2026/10/GlobeProjectTest.zip" target="_blank" rel="noreferrer noopener">Download GlobeProjectTest.zip</a></p>



<p>Open it with 2026r3, run it in a couple of browser windows, and watch your crew show up.</p>



<h2 class="wp-block-heading">Working on Several Features at Once with Git Worktrees</h2>



<p>Once you get used to delegating features, you&#8217;ll start wondering why you have to wait for one to finish before starting the next. This is where Git worktrees come in.</p>



<p>A worktree lets you check out several branches of the same repository at once, each one in its own folder. Since every folder has its own copy of the project file, the Xojo IDE just sees them as different projects and opens each one separately. You can have one agent adding a new panel in one worktree, while another one fixes a bug in a second worktree, without stepping on each other&#8217;s toes.</p>



<p>When a feature is ready, review the changes and merge the branch, just like you would with work coming from any other developer on your team. Or even better, ask the agent to do the merge.</p>



<p>A few things to keep in mind. First, each web app needs its own port. If two worktrees try to run their debug apps on the same port, only the first one will start. Ask each agent to use a different debug port in its worktree, and they&#8217;ll be able to run side by side.</p>



<p>Second, commit your AGENTS.md file. That way, every worktree starts with everything your agents have learned so far, and a finding from one worktree can be merged back for the rest. Just don&#8217;t write a specific port number there, or every worktree will inherit the same one. Tell each agent which port to use when you start the session instead.</p>



<p>And third, remember the rough edge I mentioned earlier: if two agents happen to compile at the very same second, the IDE may report the compiler as busy. That&#8217;s exactly the kind of note worth adding to AGENTS.md, so your agents know to wait a moment and try again.</p>



<h2 class="wp-block-heading">Wrapping up</h2>



<p>I didn&#8217;t expect this to work as well as it did. The agent writes the code, the IDE compiles it, Chrome shows the result, and the loop keeps going until the app works. Your job moves from typing code to deciding what to build, and reviewing what comes back.</p>



<p>Learn more about using Agentic Mode in the <a href="https://documentation.xojo.com/getting_started/using_the_ide/agentic_mode.html" target="_blank" rel="noreferrer noopener">Docs</a> and in the <a href="https://documentation.xojo.com/getting_started/quickstarts/ai_quickstart.html" target="_blank" rel="noreferrer noopener">AI QuickStart</a>. I&#8217;d love to see what you build with Agentic Mode. Share some screenshots or recordings in a new forum thread, or send me a private message if you prefer.</p>



<p>Happy coding!</p>



<p><em>Ricardo has always been curious about how things work. Growing up surrounded by computers</em> he became interested in <em>web technologies in the dial-up connections era. Xojo has been his secret weapon and language of preference since 2018. When he’s not online, chances are he will be scuba diving … or crocheting amigurumis. Find Ricardo on Twitter <a href="https://x.com/piradoiv" target="_blank" rel="noreferrer noopener">@piradoiv</a>.</em></p>



<ul class="wp-block-social-links has-normal-icon-size is-content-justification-center is-layout-flex wp-container-core-social-links-is-layout-16018d1d wp-block-social-links-is-layout-flex"><li class="wp-social-link wp-social-link-facebook  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.facebook.com/goxojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M12 2C6.5 2 2 6.5 2 12c0 5 3.7 9.1 8.4 9.9v-7H7.9V12h2.5V9.8c0-2.5 1.5-3.9 3.8-3.9 1.1 0 2.2.2 2.2.2v2.5h-1.3c-1.2 0-1.6.8-1.6 1.6V12h2.8l-.4 2.9h-2.3v7C18.3 21.1 22 17 22 12c0-5.5-4.5-10-10-10z"></path></svg><span class="wp-block-social-link-label screen-reader-text">Facebook</span></a></li>

<li class="wp-social-link wp-social-link-x  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://x.com/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M13.982 10.622 20.54 3h-1.554l-5.693 6.618L8.745 3H3.5l6.876 10.007L3.5 21h1.554l6.012-6.989L15.868 21h5.245l-7.131-10.378Zm-2.128 2.474-.697-.997-5.543-7.93H8l4.474 6.4.697.996 5.815 8.318h-2.387l-4.745-6.787Z" /></svg><span class="wp-block-social-link-label screen-reader-text">X</span></a></li>

<li class="wp-social-link wp-social-link-linkedin  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.linkedin.com/company/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M19.7,3H4.3C3.582,3,3,3.582,3,4.3v15.4C3,20.418,3.582,21,4.3,21h15.4c0.718,0,1.3-0.582,1.3-1.3V4.3 C21,3.582,20.418,3,19.7,3z M8.339,18.338H5.667v-8.59h2.672V18.338z M7.004,8.574c-0.857,0-1.549-0.694-1.549-1.548 c0-0.855,0.691-1.548,1.549-1.548c0.854,0,1.547,0.694,1.547,1.548C8.551,7.881,7.858,8.574,7.004,8.574z M18.339,18.338h-2.669 v-4.177c0-0.996-0.017-2.278-1.387-2.278c-1.389,0-1.601,1.086-1.601,2.206v4.249h-2.667v-8.59h2.559v1.174h0.037 c0.356-0.675,1.227-1.387,2.526-1.387c2.703,0,3.203,1.779,3.203,4.092V18.338z"></path></svg><span class="wp-block-social-link-label screen-reader-text">LinkedIn</span></a></li>

<li class="wp-social-link wp-social-link-github  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://github.com/topics/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M12,2C6.477,2,2,6.477,2,12c0,4.419,2.865,8.166,6.839,9.489c0.5,0.09,0.682-0.218,0.682-0.484 c0-0.236-0.009-0.866-0.014-1.699c-2.782,0.602-3.369-1.34-3.369-1.34c-0.455-1.157-1.11-1.465-1.11-1.465 c-0.909-0.62,0.069-0.608,0.069-0.608c1.004,0.071,1.532,1.03,1.532,1.03c0.891,1.529,2.341,1.089,2.91,0.833 c0.091-0.647,0.349-1.086,0.635-1.337c-2.22-0.251-4.555-1.111-4.555-4.943c0-1.091,0.39-1.984,1.03-2.682 C6.546,8.54,6.202,7.524,6.746,6.148c0,0,0.84-0.269,2.75,1.025C10.295,6.95,11.15,6.84,12,6.836 c0.85,0.004,1.705,0.114,2.504,0.336c1.909-1.294,2.748-1.025,2.748-1.025c0.546,1.376,0.202,2.394,0.1,2.646 c0.64,0.699,1.026,1.591,1.026,2.682c0,3.841-2.337,4.687-4.565,4.935c0.359,0.307,0.679,0.917,0.679,1.852 c0,1.335-0.012,2.415-0.012,2.741c0,0.269,0.18,0.579,0.688,0.481C19.138,20.161,22,16.416,22,12C22,6.477,17.523,2,12,2z"></path></svg><span class="wp-block-social-link-label screen-reader-text">GitHub</span></a></li>

<li class="wp-social-link wp-social-link-youtube  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.youtube.com/c/XojoInc" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M21.8,8.001c0,0-0.195-1.378-0.795-1.985c-0.76-0.797-1.613-0.801-2.004-0.847c-2.799-0.202-6.997-0.202-6.997-0.202 h-0.009c0,0-4.198,0-6.997,0.202C4.608,5.216,3.756,5.22,2.995,6.016C2.395,6.623,2.2,8.001,2.2,8.001S2,9.62,2,11.238v1.517 c0,1.618,0.2,3.237,0.2,3.237s0.195,1.378,0.795,1.985c0.761,0.797,1.76,0.771,2.205,0.855c1.6,0.153,6.8,0.201,6.8,0.201 s4.203-0.006,7.001-0.209c0.391-0.047,1.243-0.051,2.004-0.847c0.6-0.607,0.795-1.985,0.795-1.985s0.2-1.618,0.2-3.237v-1.517 C22,9.62,21.8,8.001,21.8,8.001z M9.935,14.594l-0.001-5.62l5.404,2.82L9.935,14.594z"></path></svg><span class="wp-block-social-link-label screen-reader-text">YouTube</span></a></li></ul>



<p class="has-text-align-center has-text-color has-link-color wp-elements-a0a2ac26ad214a49dac577734d259176" style="color:#84bd00"><a href="https://xojo.com/download/" target="_blank" rel="noreferrer noopener">Download Xojo</a></p>
]]></content:encoded>
					
		
		<enclosure url="https://blog.xojo.com/wp-content/uploads/2026/10/globe-demo.mp4" length="8889006" type="video/mp4" />

			</item>
		<item>
		<title>Use AI Coding Agents with Xojo Agentic Mode</title>
		<link>https://blog.xojo.com/2026/10/20/use-ai-coding-agents-with-xojo-agentic-mode/</link>
		
		<dc:creator><![CDATA[Paul Lefebvre]]></dc:creator>
		<pubDate>Tue, 20 Oct 2026 16:52:47 +0000</pubDate>
				<category><![CDATA[General]]></category>
		<category><![CDATA[Learning]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[2026r3]]></category>
		<category><![CDATA[Agentic Mode]]></category>
		<category><![CDATA[AI]]></category>
		<category><![CDATA[AI Code Generation]]></category>
		<category><![CDATA[Artificial Intelligence]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=16563</guid>

					<description><![CDATA[In Xojo 2026r3, the new Agentic Mode makes it easy to work with your favorite coding agent to help make apps. For about a year&#8230;]]></description>
										<content:encoded><![CDATA[
<p>In Xojo 2026r3, the new Agentic Mode makes it easy to work with your favorite coding agent to help make apps.</p>



<p>For about a year now, Jade, Xojo&#8217;s built-in AI chat assistant, has been able to help you with coding questions, code reviews, bug fixes and focused code generation. Agentic Mode takes things to an entirely new level.</p>



<p>Coding agents are separate products that are able to do interactive code generation directly on project files. Popular coding agents include <a href="https://claude.com/product/claude-code" target="_blank" rel="noreferrer noopener">Claude Code</a> and <a href="https://chatgpt.com/codex" target="_blank" rel="noreferrer noopener">ChatGPT Codex</a>, but there are many others. I&#8217;ve personally found that Claude Code works well from inside the Claude desktop app.</p>



<p>Although most of the AI companies let you use their chat products for free, you usually have to purchase a plan to get access to the coding agent. Of course, there are some free plans around and you could even install a local LLM and an open-source agent if you wanted. Since the coding agent works directly on the project files, any coding agent will work with Agentic Mode in Xojo.</p>



<h2 class="wp-block-heading">What is Agentic Mode?</h2>



<p>For Xojo, <a href="https://documentation.xojo.com/getting_started/using_the_ide/agentic_mode.html" target="_blank" rel="noreferrer noopener">Agentic Mode</a> is a setting in the File menu that provides some guidance to the coding agent and allows the agent to request to run Xojo projects and get back compilation errors. It also tells Xojo to regularly reload files in the project as they are changed.</p>



<p>To use Agentic Mode you first have to save the project to text format. After doing this, you can select File-&gt;Agentic Mode to turn it on. This displays the Messages panel so you can see information about project files that get reloaded.</p>



<p>You can now go to your coding agent and add the folder containing your text project as a work folder. After doing that you can type prompts to the coding agent and watch it do its thing. The agent will think, change files, request to run the project, review any compilation errors and generally just chug along until it has finished the task you gave it. While this is all happening, you&#8217;ll be able to watch project items change in Xojo and even see the debug app start and stop.</p>



<p>Each coding agent works similarly, but they have their differences as well. They are also all highly capable and will learn new features as they work through your project and your prompts.</p>



<h2 class="wp-block-heading">Agentic Mode in Action</h2>



<p>To show you how Agentic Mode works, we will do two quick examples.</p>



<p>This first example creates an empty project and asks the coding agent to create an app.</p>



<p>Start Xojo, from the Project Chooser select Desktop and give it the name StockTicker. Check the &#8220;for AI (Agentic Mode)&#8221; checkbox and click Create. You will be immediately prompted to choose a folder. Select a folder and Xojo will automatically create a new folder in that folder with the name StockTicker, save the project as text into the folder and turn on Agentic Mode.</p>



<p>You can now open your coding agent (I&#8217;m using Claude Code for this example) and start a new session. Add the StockTicker folder as a working directory and select your preferred model (I used Sonnet 5.5/Medium). Now enter the prompt to create the app. I used this:</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p>Create a stock ticker app. By default have it show some common stocks in the S&amp;P 500, but allow the user to enter their own stock tickers. Use a web service to get values for stocks in common indices. Display the stock prices in a list.</p>
</blockquote>



<p>Here is my initial setup with Xojo and Claude Code both open:</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="446" src="https://blog.xojo.com/wp-content/uploads/2026/09/CleanShot-2026-09-29-at-14.09.06@2x-1024x446.png" alt="" class="wp-image-16585" srcset="https://blog.xojo.com/wp-content/uploads/2026/09/CleanShot-2026-09-29-at-14.09.06@2x-1024x446.png 1024w, https://blog.xojo.com/wp-content/uploads/2026/09/CleanShot-2026-09-29-at-14.09.06@2x-300x131.png 300w, https://blog.xojo.com/wp-content/uploads/2026/09/CleanShot-2026-09-29-at-14.09.06@2x-768x334.png 768w, https://blog.xojo.com/wp-content/uploads/2026/09/CleanShot-2026-09-29-at-14.09.06@2x-1536x668.png 1536w, https://blog.xojo.com/wp-content/uploads/2026/09/CleanShot-2026-09-29-at-14.09.06@2x-2048x891.png 2048w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<p>Claude Code chugged for a couple minutes and when it was done it had created this app:</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="750" src="https://blog.xojo.com/wp-content/uploads/2026/09/CleanShot-2026-09-29-at-14.14.19@2x-1024x750.png" alt="" class="wp-image-16586" srcset="https://blog.xojo.com/wp-content/uploads/2026/09/CleanShot-2026-09-29-at-14.14.19@2x-1024x750.png 1024w, https://blog.xojo.com/wp-content/uploads/2026/09/CleanShot-2026-09-29-at-14.14.19@2x-300x220.png 300w, https://blog.xojo.com/wp-content/uploads/2026/09/CleanShot-2026-09-29-at-14.14.19@2x-768x562.png 768w, https://blog.xojo.com/wp-content/uploads/2026/09/CleanShot-2026-09-29-at-14.14.19@2x-1536x1125.png 1536w, https://blog.xojo.com/wp-content/uploads/2026/09/CleanShot-2026-09-29-at-14.14.19@2x.png 1584w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<p>Here is a (sped-up) video of the overall process:</p>



<figure class="wp-block-embed is-type-video is-provider-youtube wp-block-embed-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio"><div class="wp-block-embed__wrapper">
<iframe loading="lazy" title="Using Xojo&#039;s Agentic Mode - ToDo Claude Example" width="500" height="281" src="https://www.youtube.com/embed/dRDzpOHi9Bw?feature=oembed" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
</div></figure>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<p>The next example modifies an existing project. In this case, we will use the ToDo project that is included as a Xojo example. Using the Project Chooser, open the Desktop ToDo example and save it as a text project to a folder called DesktopToDo. Turn on Agentic Mode (File-&gt;Agentic Mode).</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="663" src="https://blog.xojo.com/wp-content/uploads/2026/09/CleanShot-2026-09-29-at-11.42.29@2x-1024x663.png" alt="" class="wp-image-16574" srcset="https://blog.xojo.com/wp-content/uploads/2026/09/CleanShot-2026-09-29-at-11.42.29@2x-1024x663.png 1024w, https://blog.xojo.com/wp-content/uploads/2026/09/CleanShot-2026-09-29-at-11.42.29@2x-300x194.png 300w, https://blog.xojo.com/wp-content/uploads/2026/09/CleanShot-2026-09-29-at-11.42.29@2x-768x497.png 768w, https://blog.xojo.com/wp-content/uploads/2026/09/CleanShot-2026-09-29-at-11.42.29@2x-1536x994.png 1536w, https://blog.xojo.com/wp-content/uploads/2026/09/CleanShot-2026-09-29-at-11.42.29@2x-2048x1325.png 2048w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<p>Open your coding agent, add the DesktopToDo folder and give it your prompt. I used this:</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p>Please review and improve this project. Perhaps make the UI a little snazzier and clean up code as necessary.</p>
</blockquote>



<p>The ToDo app UI went from looking like this:</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="711" src="https://blog.xojo.com/wp-content/uploads/2026/09/CleanShot-2026-09-29-at-11.45.09@2x-1024x711.png" alt="" class="wp-image-16575" srcset="https://blog.xojo.com/wp-content/uploads/2026/09/CleanShot-2026-09-29-at-11.45.09@2x-1024x711.png 1024w, https://blog.xojo.com/wp-content/uploads/2026/09/CleanShot-2026-09-29-at-11.45.09@2x-300x208.png 300w, https://blog.xojo.com/wp-content/uploads/2026/09/CleanShot-2026-09-29-at-11.45.09@2x-768x533.png 768w, https://blog.xojo.com/wp-content/uploads/2026/09/CleanShot-2026-09-29-at-11.45.09@2x-1536x1067.png 1536w, https://blog.xojo.com/wp-content/uploads/2026/09/CleanShot-2026-09-29-at-11.45.09@2x-2048x1422.png 2048w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<p>To this:</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="713" src="https://blog.xojo.com/wp-content/uploads/2026/09/CleanShot-2026-09-29-at-11.50.08@2x-1024x713.png" alt="" class="wp-image-16576" srcset="https://blog.xojo.com/wp-content/uploads/2026/09/CleanShot-2026-09-29-at-11.50.08@2x-1024x713.png 1024w, https://blog.xojo.com/wp-content/uploads/2026/09/CleanShot-2026-09-29-at-11.50.08@2x-300x209.png 300w, https://blog.xojo.com/wp-content/uploads/2026/09/CleanShot-2026-09-29-at-11.50.08@2x-768x535.png 768w, https://blog.xojo.com/wp-content/uploads/2026/09/CleanShot-2026-09-29-at-11.50.08@2x-1536x1069.png 1536w, https://blog.xojo.com/wp-content/uploads/2026/09/CleanShot-2026-09-29-at-11.50.08@2x-2048x1426.png 2048w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<p>It took less than two minutes for Claude Code to make these changes, fixing some of its own compile errors along the way. There were also code changes, of course. It even offered to make additional changes, such as add the ability to save the ToDo items between app launches.</p>



<p>Here is a (sped up) video of Claude Code working on this with Xojo:</p>



<figure class="wp-block-embed is-type-video is-provider-youtube wp-block-embed-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio"><div class="wp-block-embed__wrapper">
<iframe loading="lazy" title="Using Xojo&#039;s Agentic Mode - ToDo Claude Example" width="500" height="281" src="https://www.youtube.com/embed/dRDzpOHi9Bw?feature=oembed" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
</div></figure>



<p>Keep in mind that because these AI systems are non-deterministic you will get wildly different results from the same prompt. For example, in different tests with this same example and prompt, I got a changed ToDo app UI that was more colorful and had automatic saving and loading.</p>



<h2 class="wp-block-heading">Other Agentic Mode Notes</h2>



<p>You can toggle Agentic Mode on or off via IDE scripting with this command:</p>



<pre class="wp-block-code"><code>DoCommand("ToggleAgenticMode")</code></pre>



<p>Many coding agents have their own built-in browser and can use that to run and test Xojo web apps.</p>



<p>You can use Xojo while a coding agent is changing things, but keep in mind that changes you make might get overwritten by agent changes.</p>



<p>When Agentic Mode is turned on, Xojo adds an empty AGENTS.md file to the project folder that imports the XOJO-CODING.md guidelines file. You can add your own tips and suggestions to AGENTS.md (and even have the agent do it itself), but keep the link to XOJO-CODING.md intact. If you already have an AGENTs.md file in that folder that you added then Xojo won&#8217;t overwrite it, so be sure to tell it to reference XOJO-CODING.md with something like this:</p>



<pre class="wp-block-code"><code>&lt;xojo-coding&gt;
Before answering ANY message (including questions, suggestions, and planning) read the @XOJO-CODING.md file, right now.
Begin your first reply with one line: "XOJO-CODING.md loaded", then answer normally.
&lt;/xojo-coding&gt;</code></pre>



<p>The Agentic Mode setting is saved with your Xojo text project file. This allows you to have projects that automatically activate Agentic Mode when they are opened.</p>



<p>I hope you find Agentic Mode helpful for your workflow! Read more in the <a href="https://documentation.xojo.com/getting_started/using_the_ide/agentic_mode.html" target="_blank" rel="noreferrer noopener">Xojo Docs</a> or get started with the <a href="https://documentation.xojo.com/getting_started/quickstarts/ai_quickstart.html" target="_blank" rel="noreferrer noopener">AI QuickStart</a>.</p>



<figure class="wp-block-image size-full"><a href="https://knowyourmeme.com/memes/i-for-one-welcome-our-new-insect-overlords"><img loading="lazy" decoding="async" width="577" height="433" src="https://blog.xojo.com/wp-content/uploads/2026/09/image.png" alt="" class="wp-image-16568" srcset="https://blog.xojo.com/wp-content/uploads/2026/09/image.png 577w, https://blog.xojo.com/wp-content/uploads/2026/09/image-300x225.png 300w" sizes="auto, (max-width: 577px) 100vw, 577px" /></a></figure>



<p><em>Paul learned to program in BASIC at age 13 and has programmed in more languages than he remembers, with Xojo being an obvious favorite. When not working on Xojo, you can find him talking about retrocomputing at <a href="https://goto10.substack.com" target="_blank" rel="noreferrer noopener">Goto 10</a> and </em>on Mastodon @lefebvre@hachyderm.io.</p>



<ul class="wp-block-social-links has-normal-icon-size is-content-justification-center is-layout-flex wp-container-core-social-links-is-layout-16018d1d wp-block-social-links-is-layout-flex"><li class="wp-social-link wp-social-link-facebook  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.facebook.com/goxojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M12 2C6.5 2 2 6.5 2 12c0 5 3.7 9.1 8.4 9.9v-7H7.9V12h2.5V9.8c0-2.5 1.5-3.9 3.8-3.9 1.1 0 2.2.2 2.2.2v2.5h-1.3c-1.2 0-1.6.8-1.6 1.6V12h2.8l-.4 2.9h-2.3v7C18.3 21.1 22 17 22 12c0-5.5-4.5-10-10-10z"></path></svg><span class="wp-block-social-link-label screen-reader-text">Facebook</span></a></li>

<li class="wp-social-link wp-social-link-x  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://x.com/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M13.982 10.622 20.54 3h-1.554l-5.693 6.618L8.745 3H3.5l6.876 10.007L3.5 21h1.554l6.012-6.989L15.868 21h5.245l-7.131-10.378Zm-2.128 2.474-.697-.997-5.543-7.93H8l4.474 6.4.697.996 5.815 8.318h-2.387l-4.745-6.787Z" /></svg><span class="wp-block-social-link-label screen-reader-text">X</span></a></li>

<li class="wp-social-link wp-social-link-linkedin  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.linkedin.com/company/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M19.7,3H4.3C3.582,3,3,3.582,3,4.3v15.4C3,20.418,3.582,21,4.3,21h15.4c0.718,0,1.3-0.582,1.3-1.3V4.3 C21,3.582,20.418,3,19.7,3z M8.339,18.338H5.667v-8.59h2.672V18.338z M7.004,8.574c-0.857,0-1.549-0.694-1.549-1.548 c0-0.855,0.691-1.548,1.549-1.548c0.854,0,1.547,0.694,1.547,1.548C8.551,7.881,7.858,8.574,7.004,8.574z M18.339,18.338h-2.669 v-4.177c0-0.996-0.017-2.278-1.387-2.278c-1.389,0-1.601,1.086-1.601,2.206v4.249h-2.667v-8.59h2.559v1.174h0.037 c0.356-0.675,1.227-1.387,2.526-1.387c2.703,0,3.203,1.779,3.203,4.092V18.338z"></path></svg><span class="wp-block-social-link-label screen-reader-text">LinkedIn</span></a></li>

<li class="wp-social-link wp-social-link-github  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://github.com/topics/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M12,2C6.477,2,2,6.477,2,12c0,4.419,2.865,8.166,6.839,9.489c0.5,0.09,0.682-0.218,0.682-0.484 c0-0.236-0.009-0.866-0.014-1.699c-2.782,0.602-3.369-1.34-3.369-1.34c-0.455-1.157-1.11-1.465-1.11-1.465 c-0.909-0.62,0.069-0.608,0.069-0.608c1.004,0.071,1.532,1.03,1.532,1.03c0.891,1.529,2.341,1.089,2.91,0.833 c0.091-0.647,0.349-1.086,0.635-1.337c-2.22-0.251-4.555-1.111-4.555-4.943c0-1.091,0.39-1.984,1.03-2.682 C6.546,8.54,6.202,7.524,6.746,6.148c0,0,0.84-0.269,2.75,1.025C10.295,6.95,11.15,6.84,12,6.836 c0.85,0.004,1.705,0.114,2.504,0.336c1.909-1.294,2.748-1.025,2.748-1.025c0.546,1.376,0.202,2.394,0.1,2.646 c0.64,0.699,1.026,1.591,1.026,2.682c0,3.841-2.337,4.687-4.565,4.935c0.359,0.307,0.679,0.917,0.679,1.852 c0,1.335-0.012,2.415-0.012,2.741c0,0.269,0.18,0.579,0.688,0.481C19.138,20.161,22,16.416,22,12C22,6.477,17.523,2,12,2z"></path></svg><span class="wp-block-social-link-label screen-reader-text">GitHub</span></a></li>

<li class="wp-social-link wp-social-link-youtube  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.youtube.com/c/XojoInc" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M21.8,8.001c0,0-0.195-1.378-0.795-1.985c-0.76-0.797-1.613-0.801-2.004-0.847c-2.799-0.202-6.997-0.202-6.997-0.202 h-0.009c0,0-4.198,0-6.997,0.202C4.608,5.216,3.756,5.22,2.995,6.016C2.395,6.623,2.2,8.001,2.2,8.001S2,9.62,2,11.238v1.517 c0,1.618,0.2,3.237,0.2,3.237s0.195,1.378,0.795,1.985c0.761,0.797,1.76,0.771,2.205,0.855c1.6,0.153,6.8,0.201,6.8,0.201 s4.203-0.006,7.001-0.209c0.391-0.047,1.243-0.051,2.004-0.847c0.6-0.607,0.795-1.985,0.795-1.985s0.2-1.618,0.2-3.237v-1.517 C22,9.62,21.8,8.001,21.8,8.001z M9.935,14.594l-0.001-5.62l5.404,2.82L9.935,14.594z"></path></svg><span class="wp-block-social-link-label screen-reader-text">YouTube</span></a></li></ul>



<p class="has-text-align-center has-text-color has-link-color wp-elements-a0a2ac26ad214a49dac577734d259176" style="color:#84bd00"><a href="https://xojo.com/download/" target="_blank" rel="noreferrer noopener">Download Xojo</a></p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Project and Project Item Reloading</title>
		<link>https://blog.xojo.com/2026/10/20/project-and-project-item-reloading/</link>
		
		<dc:creator><![CDATA[Paul Lefebvre]]></dc:creator>
		<pubDate>Tue, 20 Oct 2026 16:52:37 +0000</pubDate>
				<category><![CDATA[General]]></category>
		<category><![CDATA[2026r3]]></category>
		<category><![CDATA[Version Control]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=16447</guid>

					<description><![CDATA[Xojo 2026r3 brings some improvements to project and project item reloading, which make it easier to use Xojo with version control systems and AI coding&#8230;]]></description>
										<content:encoded><![CDATA[
<p>Xojo 2026r3 brings some improvements to project and project item reloading, which make it easier to use Xojo with version control systems and AI coding agents.</p>



<h2 class="wp-block-heading">Project Reloading</h2>



<p>In prior versions of Xojo you could reload a project, after it had been modified, by using File -&gt; Revert to Saved. This feature essentially closes and re-opens the entire project and it works with all project formats: Binary, XML and Text.</p>



<p>With 2026r3, this feature remains with a couple small tweaks. First, you can now reload the project without having to first modify it. An example when this might be useful is if you have just updated your Git client with the latest changes from your team and want to quickly reload the entire project.</p>



<p>This feature has also been renamed from &#8220;Revert to Saved&#8221; to &#8220;Reload Project&#8221;.</p>



<h2 class="wp-block-heading">Project Item Reloading</h2>



<p>Reloading the entire project can be handy, but is also somewhat overkill for text projects that save each project item as a separate file. If just a single file on disk was changed, then you may not want to reload the entire project, which could cause you to lose IDE changes, lose your place in the Navigator or just take too long.</p>



<p>You can now use File -&gt; Reload Item to reload the selected item in the Navigator. Note that &#8220;Item&#8221; in the menu is replaced with the name of the selected item. This feature reloads the selected item and keeps it selected.</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p><strong>This feature is destructive</strong>, so if you have made changes to the project item in the IDE, they will be lost as the item is completely replaced by the version on the disk.</p>
</blockquote>



<p>It is a quick way to reload an item that has been changed by a version control update or an AI coding agent. Reloading is also a great way to fix a borked edit, rather than doing multiple Undos.</p>



<p>This feature only works with Text projects.</p>



<h2 class="wp-block-heading">Reload Changed Files</h2>



<p>Finally, you may have multiple files you want to reload but don&#8217;t know exactly which ones they are. This sort of thing can happen with a version control update or an AI coding agent. Rather than force you to reload the entire project, you can now use File -&gt; Reload Changed Files to reload the files on disk that are different than what is in the IDE.</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p><strong>This feature is destructive</strong>, so if you have made changes to the project items in the IDE, they will be lost as the item is completely replaced by the version on the disk.</p>
</blockquote>



<p>This feature only works with Text projects.</p>



<h2 class="wp-block-heading">IDE Scripting</h2>



<p>The above features now also have equivalent IDE Scripting commands. They are:</p>



<ul class="wp-block-list">
<li>ReloadProject()</li>



<li>ReloadProjectItem(itemPath As String) As Boolean</li>



<li>ReloadChangedFiles()</li>
</ul>



<p><em>Paul learned to program in BASIC at age 13 and has programmed in more languages than he remembers, with Xojo being an obvious favorite. When not working on Xojo, you can find him talking about retrocomputing at <a href="https://goto10.substack.com" target="_blank" rel="noreferrer noopener">Goto 10</a> and </em>on Mastodon @lefebvre@hachyderm.io.</p>



<ul class="wp-block-social-links has-normal-icon-size is-content-justification-center is-layout-flex wp-container-core-social-links-is-layout-16018d1d wp-block-social-links-is-layout-flex"><li class="wp-social-link wp-social-link-facebook  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.facebook.com/goxojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M12 2C6.5 2 2 6.5 2 12c0 5 3.7 9.1 8.4 9.9v-7H7.9V12h2.5V9.8c0-2.5 1.5-3.9 3.8-3.9 1.1 0 2.2.2 2.2.2v2.5h-1.3c-1.2 0-1.6.8-1.6 1.6V12h2.8l-.4 2.9h-2.3v7C18.3 21.1 22 17 22 12c0-5.5-4.5-10-10-10z"></path></svg><span class="wp-block-social-link-label screen-reader-text">Facebook</span></a></li>

<li class="wp-social-link wp-social-link-x  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://x.com/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M13.982 10.622 20.54 3h-1.554l-5.693 6.618L8.745 3H3.5l6.876 10.007L3.5 21h1.554l6.012-6.989L15.868 21h5.245l-7.131-10.378Zm-2.128 2.474-.697-.997-5.543-7.93H8l4.474 6.4.697.996 5.815 8.318h-2.387l-4.745-6.787Z" /></svg><span class="wp-block-social-link-label screen-reader-text">X</span></a></li>

<li class="wp-social-link wp-social-link-linkedin  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.linkedin.com/company/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M19.7,3H4.3C3.582,3,3,3.582,3,4.3v15.4C3,20.418,3.582,21,4.3,21h15.4c0.718,0,1.3-0.582,1.3-1.3V4.3 C21,3.582,20.418,3,19.7,3z M8.339,18.338H5.667v-8.59h2.672V18.338z M7.004,8.574c-0.857,0-1.549-0.694-1.549-1.548 c0-0.855,0.691-1.548,1.549-1.548c0.854,0,1.547,0.694,1.547,1.548C8.551,7.881,7.858,8.574,7.004,8.574z M18.339,18.338h-2.669 v-4.177c0-0.996-0.017-2.278-1.387-2.278c-1.389,0-1.601,1.086-1.601,2.206v4.249h-2.667v-8.59h2.559v1.174h0.037 c0.356-0.675,1.227-1.387,2.526-1.387c2.703,0,3.203,1.779,3.203,4.092V18.338z"></path></svg><span class="wp-block-social-link-label screen-reader-text">LinkedIn</span></a></li>

<li class="wp-social-link wp-social-link-github  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://github.com/topics/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M12,2C6.477,2,2,6.477,2,12c0,4.419,2.865,8.166,6.839,9.489c0.5,0.09,0.682-0.218,0.682-0.484 c0-0.236-0.009-0.866-0.014-1.699c-2.782,0.602-3.369-1.34-3.369-1.34c-0.455-1.157-1.11-1.465-1.11-1.465 c-0.909-0.62,0.069-0.608,0.069-0.608c1.004,0.071,1.532,1.03,1.532,1.03c0.891,1.529,2.341,1.089,2.91,0.833 c0.091-0.647,0.349-1.086,0.635-1.337c-2.22-0.251-4.555-1.111-4.555-4.943c0-1.091,0.39-1.984,1.03-2.682 C6.546,8.54,6.202,7.524,6.746,6.148c0,0,0.84-0.269,2.75,1.025C10.295,6.95,11.15,6.84,12,6.836 c0.85,0.004,1.705,0.114,2.504,0.336c1.909-1.294,2.748-1.025,2.748-1.025c0.546,1.376,0.202,2.394,0.1,2.646 c0.64,0.699,1.026,1.591,1.026,2.682c0,3.841-2.337,4.687-4.565,4.935c0.359,0.307,0.679,0.917,0.679,1.852 c0,1.335-0.012,2.415-0.012,2.741c0,0.269,0.18,0.579,0.688,0.481C19.138,20.161,22,16.416,22,12C22,6.477,17.523,2,12,2z"></path></svg><span class="wp-block-social-link-label screen-reader-text">GitHub</span></a></li>

<li class="wp-social-link wp-social-link-youtube  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.youtube.com/c/XojoInc" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M21.8,8.001c0,0-0.195-1.378-0.795-1.985c-0.76-0.797-1.613-0.801-2.004-0.847c-2.799-0.202-6.997-0.202-6.997-0.202 h-0.009c0,0-4.198,0-6.997,0.202C4.608,5.216,3.756,5.22,2.995,6.016C2.395,6.623,2.2,8.001,2.2,8.001S2,9.62,2,11.238v1.517 c0,1.618,0.2,3.237,0.2,3.237s0.195,1.378,0.795,1.985c0.761,0.797,1.76,0.771,2.205,0.855c1.6,0.153,6.8,0.201,6.8,0.201 s4.203-0.006,7.001-0.209c0.391-0.047,1.243-0.051,2.004-0.847c0.6-0.607,0.795-1.985,0.795-1.985s0.2-1.618,0.2-3.237v-1.517 C22,9.62,21.8,8.001,21.8,8.001z M9.935,14.594l-0.001-5.62l5.404,2.82L9.935,14.594z"></path></svg><span class="wp-block-social-link-label screen-reader-text">YouTube</span></a></li></ul>



<p class="has-text-align-center has-text-color has-link-color wp-elements-a0a2ac26ad214a49dac577734d259176" style="color:#84bd00"><a href="https://xojo.com/download/" target="_blank" rel="noreferrer noopener">Download Xojo</a></p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Project Item Copy/Paste Improvements</title>
		<link>https://blog.xojo.com/2026/10/20/project-item-copy-paste-improvements/</link>
		
		<dc:creator><![CDATA[Paul Lefebvre]]></dc:creator>
		<pubDate>Tue, 20 Oct 2026 16:52:25 +0000</pubDate>
				<category><![CDATA[General]]></category>
		<category><![CDATA[2026r3]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=16536</guid>

					<description><![CDATA[Another improvement to Copy/Paste for code as text is that you can now paste a layout as text into your projects. This works for Window,&#8230;]]></description>
										<content:encoded><![CDATA[
<p>Another improvement to Copy/Paste for code as text is that you can now paste a layout as text into your projects. This works for Window, WebPage, MobileScreen and Container.</p>



<p>This is the output you get when copying a layout to text:</p>



<pre class="wp-block-code"><code>Window HelloThere
Inherits DesktopWindow
  Layout Property Width = 600
  Layout Property Height = 400
  Layout Property MinimumWidth = 64
  Layout Property MinimumHeight = 64
  Layout Property MaximumWidth = 32000
  Layout Property MaximumHeight = 32000
  Layout Property Title = "Hello World"
  Layout Property HasCloseButton = True
  Layout Property HasMaximizeButton = True
  Layout Property HasMinimizeButton = True
  Layout Property HasTitleBar = True
  Layout Property Resizeable = True
  Layout Property DefaultLocation = 2
  Layout Property Visible = True
  Layout Property ImplicitInstance = True
  Layout Property BackgroundColor = &amp;cFFFFFF
  Layout Property MenuBar = 1436252159

  Control Button1 Inherits DesktopButton
    Layout Property Scope = 2
    Layout Property Left = 20
    Layout Property Top = 55
    Layout Property Width = 171
    Layout Property Height = 20
    Layout Property LockLeft = True
    Layout Property LockTop = True
    Layout Property TabStop = True
    Layout Property AllowAutoDeactivate = True
    Layout Property Caption = "Hello"
    Layout Property Default = True
    Layout Property Enabled = True
    Layout Property Visible = True
    Layout Property FontName = "System"

    Private Sub Pressed() Handles Pressed
      MessageBox("Hello " + TextField1.Text)
    End Sub
  End Control

  Control TextField1 Inherits DesktopTextField
    Layout Property Scope = 2
    Layout Property Left = 20
    Layout Property Top = 11
    Layout Property Width = 171
    Layout Property Height = 38
    Layout Property LockLeft = True
    Layout Property LockTop = True
    Layout Property TabIndex = 1
    Layout Property TabStop = True
    Layout Property AllowAutoDeactivate = True
    Layout Property BackgroundColor = &amp;hFFFFFF
    Layout Property HasBorder = True
    Layout Property Enabled = True
    Layout Property TextColor = &amp;h000000
    Layout Property AllowFocusRing = True
    Layout Property Visible = True
    Layout Property FontName = "System"
    Layout Property Text = "Xojo"
  End Control

End Window</code></pre>



<p>You can copy that text and paste it back into a desktop project to add the window to it.</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p>Note: Layouts that contain control sets do not copy/paste properly.</p>
</blockquote>



<p>But one other cool thing you can now do is paste the above window text into a different project type, such as a web project. The window gets converted to a WebPage and its controls are converted to web controls. Here is what the above window looks like when pasted into a web project:</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="821" src="https://blog.xojo.com/wp-content/uploads/2026/09/CleanShot-2026-09-14-at-15.08.16@2x-1024x821.png" alt="" class="wp-image-16537" srcset="https://blog.xojo.com/wp-content/uploads/2026/09/CleanShot-2026-09-14-at-15.08.16@2x-1024x821.png 1024w, https://blog.xojo.com/wp-content/uploads/2026/09/CleanShot-2026-09-14-at-15.08.16@2x-300x240.png 300w, https://blog.xojo.com/wp-content/uploads/2026/09/CleanShot-2026-09-14-at-15.08.16@2x-768x616.png 768w, https://blog.xojo.com/wp-content/uploads/2026/09/CleanShot-2026-09-14-at-15.08.16@2x.png 1290w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<p>You could also paste it into an Android or iOS project:</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="508" height="1024" src="https://blog.xojo.com/wp-content/uploads/2026/09/CleanShot-2026-09-14-at-15.09.12@2x-508x1024.png" alt="" class="wp-image-16538" srcset="https://blog.xojo.com/wp-content/uploads/2026/09/CleanShot-2026-09-14-at-15.09.12@2x-508x1024.png 508w, https://blog.xojo.com/wp-content/uploads/2026/09/CleanShot-2026-09-14-at-15.09.12@2x-149x300.png 149w, https://blog.xojo.com/wp-content/uploads/2026/09/CleanShot-2026-09-14-at-15.09.12@2x-768x1547.png 768w, https://blog.xojo.com/wp-content/uploads/2026/09/CleanShot-2026-09-14-at-15.09.12@2x-762x1536.png 762w, https://blog.xojo.com/wp-content/uploads/2026/09/CleanShot-2026-09-14-at-15.09.12@2x.png 822w" sizes="auto, (max-width: 508px) 100vw, 508px" /></figure>



<p>When you do this, your controls, code and properties are moved over, but the layout itself is not otherwise adjusted. Control sizes and positioning may need adjustments for the different size layouts. But this should provide a way to give you a quick jumpstart when migrating some UI between project types. If there is enough interest in this capability, perhaps we can add some conversion rules to help adjust control position and sizing between project types.</p>



<p><em>Paul learned to program in BASIC at age 13 and has programmed in more languages than he remembers, with Xojo being an obvious favorite. When not working on Xojo, you can find him talking about retrocomputing at <a href="https://goto10.substack.com" target="_blank" rel="noreferrer noopener">Goto 10</a> and </em>on Mastodon @lefebvre@hachyderm.io.</p>



<ul class="wp-block-social-links has-normal-icon-size is-content-justification-center is-layout-flex wp-container-core-social-links-is-layout-16018d1d wp-block-social-links-is-layout-flex"><li class="wp-social-link wp-social-link-facebook  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.facebook.com/goxojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M12 2C6.5 2 2 6.5 2 12c0 5 3.7 9.1 8.4 9.9v-7H7.9V12h2.5V9.8c0-2.5 1.5-3.9 3.8-3.9 1.1 0 2.2.2 2.2.2v2.5h-1.3c-1.2 0-1.6.8-1.6 1.6V12h2.8l-.4 2.9h-2.3v7C18.3 21.1 22 17 22 12c0-5.5-4.5-10-10-10z"></path></svg><span class="wp-block-social-link-label screen-reader-text">Facebook</span></a></li>

<li class="wp-social-link wp-social-link-x  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://x.com/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M13.982 10.622 20.54 3h-1.554l-5.693 6.618L8.745 3H3.5l6.876 10.007L3.5 21h1.554l6.012-6.989L15.868 21h5.245l-7.131-10.378Zm-2.128 2.474-.697-.997-5.543-7.93H8l4.474 6.4.697.996 5.815 8.318h-2.387l-4.745-6.787Z" /></svg><span class="wp-block-social-link-label screen-reader-text">X</span></a></li>

<li class="wp-social-link wp-social-link-linkedin  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.linkedin.com/company/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M19.7,3H4.3C3.582,3,3,3.582,3,4.3v15.4C3,20.418,3.582,21,4.3,21h15.4c0.718,0,1.3-0.582,1.3-1.3V4.3 C21,3.582,20.418,3,19.7,3z M8.339,18.338H5.667v-8.59h2.672V18.338z M7.004,8.574c-0.857,0-1.549-0.694-1.549-1.548 c0-0.855,0.691-1.548,1.549-1.548c0.854,0,1.547,0.694,1.547,1.548C8.551,7.881,7.858,8.574,7.004,8.574z M18.339,18.338h-2.669 v-4.177c0-0.996-0.017-2.278-1.387-2.278c-1.389,0-1.601,1.086-1.601,2.206v4.249h-2.667v-8.59h2.559v1.174h0.037 c0.356-0.675,1.227-1.387,2.526-1.387c2.703,0,3.203,1.779,3.203,4.092V18.338z"></path></svg><span class="wp-block-social-link-label screen-reader-text">LinkedIn</span></a></li>

<li class="wp-social-link wp-social-link-github  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://github.com/topics/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M12,2C6.477,2,2,6.477,2,12c0,4.419,2.865,8.166,6.839,9.489c0.5,0.09,0.682-0.218,0.682-0.484 c0-0.236-0.009-0.866-0.014-1.699c-2.782,0.602-3.369-1.34-3.369-1.34c-0.455-1.157-1.11-1.465-1.11-1.465 c-0.909-0.62,0.069-0.608,0.069-0.608c1.004,0.071,1.532,1.03,1.532,1.03c0.891,1.529,2.341,1.089,2.91,0.833 c0.091-0.647,0.349-1.086,0.635-1.337c-2.22-0.251-4.555-1.111-4.555-4.943c0-1.091,0.39-1.984,1.03-2.682 C6.546,8.54,6.202,7.524,6.746,6.148c0,0,0.84-0.269,2.75,1.025C10.295,6.95,11.15,6.84,12,6.836 c0.85,0.004,1.705,0.114,2.504,0.336c1.909-1.294,2.748-1.025,2.748-1.025c0.546,1.376,0.202,2.394,0.1,2.646 c0.64,0.699,1.026,1.591,1.026,2.682c0,3.841-2.337,4.687-4.565,4.935c0.359,0.307,0.679,0.917,0.679,1.852 c0,1.335-0.012,2.415-0.012,2.741c0,0.269,0.18,0.579,0.688,0.481C19.138,20.161,22,16.416,22,12C22,6.477,17.523,2,12,2z"></path></svg><span class="wp-block-social-link-label screen-reader-text">GitHub</span></a></li>

<li class="wp-social-link wp-social-link-youtube  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.youtube.com/c/XojoInc" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M21.8,8.001c0,0-0.195-1.378-0.795-1.985c-0.76-0.797-1.613-0.801-2.004-0.847c-2.799-0.202-6.997-0.202-6.997-0.202 h-0.009c0,0-4.198,0-6.997,0.202C4.608,5.216,3.756,5.22,2.995,6.016C2.395,6.623,2.2,8.001,2.2,8.001S2,9.62,2,11.238v1.517 c0,1.618,0.2,3.237,0.2,3.237s0.195,1.378,0.795,1.985c0.761,0.797,1.76,0.771,2.205,0.855c1.6,0.153,6.8,0.201,6.8,0.201 s4.203-0.006,7.001-0.209c0.391-0.047,1.243-0.051,2.004-0.847c0.6-0.607,0.795-1.985,0.795-1.985s0.2-1.618,0.2-3.237v-1.517 C22,9.62,21.8,8.001,21.8,8.001z M9.935,14.594l-0.001-5.62l5.404,2.82L9.935,14.594z"></path></svg><span class="wp-block-social-link-label screen-reader-text">YouTube</span></a></li></ul>



<p class="has-text-align-center has-text-color has-link-color wp-elements-a0a2ac26ad214a49dac577734d259176" style="color:#84bd00"><a href="https://xojo.com/download/" target="_blank" rel="noreferrer noopener">Download Xojo</a></p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Introducing DesktopTable: A More Capable DesktopListBox</title>
		<link>https://blog.xojo.com/2026/10/20/introducing-desktoptable-a-more-capable-desktoplistbox/</link>
		
		<dc:creator><![CDATA[William Yu]]></dc:creator>
		<pubDate>Tue, 20 Oct 2026 16:52:10 +0000</pubDate>
				<category><![CDATA[Desktop]]></category>
		<category><![CDATA[General]]></category>
		<category><![CDATA[Learning]]></category>
		<category><![CDATA[2026r3]]></category>
		<category><![CDATA[DesktopTable]]></category>
		<category><![CDATA[Listbox]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=16615</guid>

					<description><![CDATA[DesktopTable is a new control introduced in Xojo 2026r3, it is designed as a drop-in replacement for DesktopListBox, while adding a range of features for&#8230;]]></description>
										<content:encoded><![CDATA[
<p>DesktopTable is a new control introduced in Xojo 2026r3, it is designed as a drop-in replacement for DesktopListBox, while adding a range of features for building richer, more capable tables.</p>



<p>Most existing DesktopListBox code will compile with little or no change when transitioning to DesktopTable. At the same time, DesktopTable adds features that previously required custom controls or additional code.</p>



<h2 class="wp-block-heading">What’s New?</h2>



<p>DesktopTable adds support for:</p>



<ul class="wp-block-list">
<li><strong>Frozen columns and rows</strong> — Keep important columns, headers, or totals visible while scrolling</li>
</ul>



<figure class="wp-block-video"><video height="1130" style="aspect-ratio: 1664 / 1130;" width="1664" controls src="https://blog.xojo.com/wp-content/uploads/2026/10/DesktopTable_FrozenColumns.mov"></video></figure>



<ul class="wp-block-list">
<li><strong>Merged cells</strong>&nbsp;— Span cells across rows and columns for titles, groupings, and custom layouts</li>



<li><strong>Sticky section headers</strong>&nbsp;— Keep section headers pinned as their section scrolls</li>



<li><strong>Hidden and reorderable columns</strong>&nbsp;— Hide columns without removing their data, or let users rearrange them</li>



<li><strong>Per-row heights</strong>&nbsp;— Set individual row heights and optionally allow users to resize rows</li>
</ul>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="992" src="https://blog.xojo.com/wp-content/uploads/2026/10/DesktopTable_VariableRowHeights-1024x992.png" alt="" class="wp-image-16627" srcset="https://blog.xojo.com/wp-content/uploads/2026/10/DesktopTable_VariableRowHeights-1024x992.png 1024w, https://blog.xojo.com/wp-content/uploads/2026/10/DesktopTable_VariableRowHeights-300x291.png 300w, https://blog.xojo.com/wp-content/uploads/2026/10/DesktopTable_VariableRowHeights-768x744.png 768w, https://blog.xojo.com/wp-content/uploads/2026/10/DesktopTable_VariableRowHeights.png 1170w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<ul class="wp-block-list">
<li><strong>Insets</strong>&nbsp;— Add space before the first or after the last row</li>



<li><strong>Progress bars, checkboxes, and containers</strong>&nbsp;— Built-in cell types for richer data presentation</li>
</ul>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="714" src="https://blog.xojo.com/wp-content/uploads/2026/10/Screenshot-2026-10-06-at-1.16.33-PM-1024x714.png" alt="" class="wp-image-16636" srcset="https://blog.xojo.com/wp-content/uploads/2026/10/Screenshot-2026-10-06-at-1.16.33-PM-1024x714.png 1024w, https://blog.xojo.com/wp-content/uploads/2026/10/Screenshot-2026-10-06-at-1.16.33-PM-300x209.png 300w, https://blog.xojo.com/wp-content/uploads/2026/10/Screenshot-2026-10-06-at-1.16.33-PM-768x535.png 768w, https://blog.xojo.com/wp-content/uploads/2026/10/Screenshot-2026-10-06-at-1.16.33-PM-1536x1071.png 1536w, https://blog.xojo.com/wp-content/uploads/2026/10/Screenshot-2026-10-06-at-1.16.33-PM.png 1664w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<figure class="wp-block-gallery has-nested-images columns-default is-cropped wp-block-gallery-1 is-layout-flex wp-block-gallery-is-layout-flex">
<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="387" height="755" data-id="16646" src="https://blog.xojo.com/wp-content/uploads/2026/10/Win32ProgressBarCellType-2.png" alt="" class="wp-image-16646" srcset="https://blog.xojo.com/wp-content/uploads/2026/10/Win32ProgressBarCellType-2.png 387w, https://blog.xojo.com/wp-content/uploads/2026/10/Win32ProgressBarCellType-2-154x300.png 154w" sizes="auto, (max-width: 387px) 100vw, 387px" /></figure>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="387" height="785" data-id="16645" src="https://blog.xojo.com/wp-content/uploads/2026/10/WinUIProgressBarCellType-1.png" alt="" class="wp-image-16645" srcset="https://blog.xojo.com/wp-content/uploads/2026/10/WinUIProgressBarCellType-1.png 387w, https://blog.xojo.com/wp-content/uploads/2026/10/WinUIProgressBarCellType-1-148x300.png 148w" sizes="auto, (max-width: 387px) 100vw, 387px" /></figure>
</figure>



<ul class="wp-block-list">
<li><strong>Custom cell controls</strong>&nbsp;— Use&nbsp;<code>CellBoundsAt</code>&nbsp;to position your own controls over cells</li>



<li><strong>Automatic Right-to-Left support</strong>&nbsp;— The table automatically adapts and aligns columns and text for right-to-left languages</li>
</ul>



<figure class="wp-block-gallery has-nested-images columns-default is-cropped wp-block-gallery-2 is-layout-flex wp-block-gallery-is-layout-flex">
<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="777" data-id="16640" src="https://blog.xojo.com/wp-content/uploads/2026/10/Screenshot-2026-10-06-at-1.45.09-PM-1024x777.png" alt="" class="wp-image-16640" srcset="https://blog.xojo.com/wp-content/uploads/2026/10/Screenshot-2026-10-06-at-1.45.09-PM-1024x777.png 1024w, https://blog.xojo.com/wp-content/uploads/2026/10/Screenshot-2026-10-06-at-1.45.09-PM-300x228.png 300w, https://blog.xojo.com/wp-content/uploads/2026/10/Screenshot-2026-10-06-at-1.45.09-PM-768x582.png 768w, https://blog.xojo.com/wp-content/uploads/2026/10/Screenshot-2026-10-06-at-1.45.09-PM.png 1424w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="777" data-id="16639" src="https://blog.xojo.com/wp-content/uploads/2026/10/Screenshot-2026-10-06-at-1.44.23-PM-1024x777.png" alt="" class="wp-image-16639" srcset="https://blog.xojo.com/wp-content/uploads/2026/10/Screenshot-2026-10-06-at-1.44.23-PM-1024x777.png 1024w, https://blog.xojo.com/wp-content/uploads/2026/10/Screenshot-2026-10-06-at-1.44.23-PM-300x228.png 300w, https://blog.xojo.com/wp-content/uploads/2026/10/Screenshot-2026-10-06-at-1.44.23-PM-768x582.png 768w, https://blog.xojo.com/wp-content/uploads/2026/10/Screenshot-2026-10-06-at-1.44.23-PM.png 1424w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>
</figure>



<ul class="wp-block-list">
<li><strong>Virtual data sources</strong>&nbsp;— Work with large datasets without storing every row in the control</li>



<li><strong>CSV and TSV support</strong>&nbsp;— Save and load table data directly</li>



<li><strong>Row swipe actions</strong>&nbsp;— Provide familiar leading and trailing actions on macOS, Windows, and Linux touchpads</li>
</ul>



<figure class="wp-block-video"><video height="1090" style="aspect-ratio: 1424 / 1090;" width="1424" controls src="https://blog.xojo.com/wp-content/uploads/2026/10/DesktopTable_MouseGesture.mov"></video></figure>



<ul class="wp-block-list">
<li><strong>Live column resizing</strong>&nbsp;— Respond while a column is being resized, as well as when resizing finishes</li>



<li><strong>Custom drawing and macOS vibrancy</strong>&nbsp;— More control over the table&#8217;s appearance and behavior</li>
</ul>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="1000" height="878" src="https://blog.xojo.com/wp-content/uploads/2026/10/DesktopTable_Translucent.png" alt="" class="wp-image-16623" srcset="https://blog.xojo.com/wp-content/uploads/2026/10/DesktopTable_Translucent.png 1000w, https://blog.xojo.com/wp-content/uploads/2026/10/DesktopTable_Translucent-300x263.png 300w, https://blog.xojo.com/wp-content/uploads/2026/10/DesktopTable_Translucent-768x674.png 768w" sizes="auto, (max-width: 1000px) 100vw, 1000px" /></figure>



<h2 class="wp-block-heading">Moving from DesktopListBox</h2>



<p>The transition is intentionally straightforward. Change the super of your <code>DesktopListBox</code> control to&nbsp;<code>DesktopTable</code>, build your project, and address the few members that have been renamed.</p>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>DesktopListBox</th><th>DesktopTable</th></tr></thead><tbody><tr><td>HeaderAt</td><td>ColumnHeaderAt</td></tr><tr><td>HasHeader</td><td>HasColumnHeader</td></tr><tr><td>RefreshCell</td><td>RefreshCellAt</td></tr><tr><td>PressHeader</td><td>PressColumnHeaderAt</td></tr></tbody></table></figure>



<p>Most familiar APIs—including&nbsp;<code>AddRow</code>,&nbsp;<code>CellTextAt</code>,&nbsp;<code>ColumnCount</code>,&nbsp;<code>ColumnWidths</code>,&nbsp;<code>RemoveRowAt</code>, and&nbsp;<code>SelectedRowIndex</code>—retain their existing names.</p>



<h2 class="wp-block-heading">A Few Things to Check</h2>



<p>Some behavior is intentionally different. In particular, row reordering with a&nbsp;<code>DataSource</code>&nbsp;or expandable rows requires you to handle&nbsp;<code>DragReorderRows</code>, and row dragging requires&nbsp;<code>DragRow</code>&nbsp;to populate the&nbsp;<code>DragItem</code>&nbsp;and return&nbsp;<code>True</code>.</p>



<p>Sorting also removes merged cells, so applications using merged cells should re-apply their merges after sorting. Frozen rows retain their position and cannot be reordered.</p>



<p><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f4a1.png" alt="💡" class="wp-smiley" style="height: 1em; max-height: 1em;" />If you want to improve performance when adding and removing rows, you can set <code>AllowRowAnimation</code> to False.</p>



<h2 class="wp-block-heading">An Enhanced IDE Experience</h2>



<p>We couldn&#8217;t introduce DesktopTable without enhancing the IDE experience as well. Table editing in the IDE is now more intuitive, compared against DesktopListBox, making it easier to edit and work with your tables.</p>



<figure class="wp-block-gallery has-nested-images columns-default is-cropped wp-block-gallery-3 is-layout-flex wp-block-gallery-is-layout-flex">
<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="750" data-id="16631" src="https://blog.xojo.com/wp-content/uploads/2026/10/Screenshot-2026-10-06-at-11.02.18-AM-1024x750.png" alt="" class="wp-image-16631" srcset="https://blog.xojo.com/wp-content/uploads/2026/10/Screenshot-2026-10-06-at-11.02.18-AM-1024x750.png 1024w, https://blog.xojo.com/wp-content/uploads/2026/10/Screenshot-2026-10-06-at-11.02.18-AM-300x220.png 300w, https://blog.xojo.com/wp-content/uploads/2026/10/Screenshot-2026-10-06-at-11.02.18-AM-768x563.png 768w, https://blog.xojo.com/wp-content/uploads/2026/10/Screenshot-2026-10-06-at-11.02.18-AM.png 1228w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /><figcaption class="wp-element-caption">DesktopTable editor</figcaption></figure>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="752" data-id="16632" src="https://blog.xojo.com/wp-content/uploads/2026/10/Screenshot-2026-10-06-at-11.03.53-AM-1024x752.png" alt="" class="wp-image-16632" srcset="https://blog.xojo.com/wp-content/uploads/2026/10/Screenshot-2026-10-06-at-11.03.53-AM-1024x752.png 1024w, https://blog.xojo.com/wp-content/uploads/2026/10/Screenshot-2026-10-06-at-11.03.53-AM-300x220.png 300w, https://blog.xojo.com/wp-content/uploads/2026/10/Screenshot-2026-10-06-at-11.03.53-AM-768x564.png 768w, https://blog.xojo.com/wp-content/uploads/2026/10/Screenshot-2026-10-06-at-11.03.53-AM.png 1220w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /><figcaption class="wp-element-caption">DesktopListBox editor</figcaption></figure>
</figure>



<p>We&#8217;ve also updated the debugger to better handle DesktopTable contents, efficiently loading rows dynamically and allowing you to jump directly to and inspect specific rows without loading the entire table.</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="500" src="https://blog.xojo.com/wp-content/uploads/2026/10/Screenshot-2026-10-06-at-11.14.48-AM-1024x500.png" alt="" class="wp-image-16633" srcset="https://blog.xojo.com/wp-content/uploads/2026/10/Screenshot-2026-10-06-at-11.14.48-AM-1024x500.png 1024w, https://blog.xojo.com/wp-content/uploads/2026/10/Screenshot-2026-10-06-at-11.14.48-AM-300x147.png 300w, https://blog.xojo.com/wp-content/uploads/2026/10/Screenshot-2026-10-06-at-11.14.48-AM-768x375.png 768w, https://blog.xojo.com/wp-content/uploads/2026/10/Screenshot-2026-10-06-at-11.14.48-AM.png 1134w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<h2 class="wp-block-heading">Final Thoughts</h2>



<p>DesktopTable gives existing DesktopListBox applications a familiar starting point while opening the door to considerably richer table interfaces. Stay tuned for more blog posts exploring many of its exciting new features!</p>



<p><em><em><em>William Yu grew up in Canada learning to program BASIC on a Vic-20. He is Xojo’s resident Windows and Linux engineer, among his many other skills. Some may say he has joined the dark side here in the USA, but he will always be a Canadian at heart.</em></em></em></p>



<ul class="wp-block-social-links has-normal-icon-size is-content-justification-center is-layout-flex wp-container-core-social-links-is-layout-16018d1d wp-block-social-links-is-layout-flex"><li class="wp-social-link wp-social-link-facebook  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.facebook.com/goxojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M12 2C6.5 2 2 6.5 2 12c0 5 3.7 9.1 8.4 9.9v-7H7.9V12h2.5V9.8c0-2.5 1.5-3.9 3.8-3.9 1.1 0 2.2.2 2.2.2v2.5h-1.3c-1.2 0-1.6.8-1.6 1.6V12h2.8l-.4 2.9h-2.3v7C18.3 21.1 22 17 22 12c0-5.5-4.5-10-10-10z"></path></svg><span class="wp-block-social-link-label screen-reader-text">Facebook</span></a></li>

<li class="wp-social-link wp-social-link-x  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://x.com/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M13.982 10.622 20.54 3h-1.554l-5.693 6.618L8.745 3H3.5l6.876 10.007L3.5 21h1.554l6.012-6.989L15.868 21h5.245l-7.131-10.378Zm-2.128 2.474-.697-.997-5.543-7.93H8l4.474 6.4.697.996 5.815 8.318h-2.387l-4.745-6.787Z" /></svg><span class="wp-block-social-link-label screen-reader-text">X</span></a></li>

<li class="wp-social-link wp-social-link-linkedin  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.linkedin.com/company/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M19.7,3H4.3C3.582,3,3,3.582,3,4.3v15.4C3,20.418,3.582,21,4.3,21h15.4c0.718,0,1.3-0.582,1.3-1.3V4.3 C21,3.582,20.418,3,19.7,3z M8.339,18.338H5.667v-8.59h2.672V18.338z M7.004,8.574c-0.857,0-1.549-0.694-1.549-1.548 c0-0.855,0.691-1.548,1.549-1.548c0.854,0,1.547,0.694,1.547,1.548C8.551,7.881,7.858,8.574,7.004,8.574z M18.339,18.338h-2.669 v-4.177c0-0.996-0.017-2.278-1.387-2.278c-1.389,0-1.601,1.086-1.601,2.206v4.249h-2.667v-8.59h2.559v1.174h0.037 c0.356-0.675,1.227-1.387,2.526-1.387c2.703,0,3.203,1.779,3.203,4.092V18.338z"></path></svg><span class="wp-block-social-link-label screen-reader-text">LinkedIn</span></a></li>

<li class="wp-social-link wp-social-link-github  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://github.com/topics/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M12,2C6.477,2,2,6.477,2,12c0,4.419,2.865,8.166,6.839,9.489c0.5,0.09,0.682-0.218,0.682-0.484 c0-0.236-0.009-0.866-0.014-1.699c-2.782,0.602-3.369-1.34-3.369-1.34c-0.455-1.157-1.11-1.465-1.11-1.465 c-0.909-0.62,0.069-0.608,0.069-0.608c1.004,0.071,1.532,1.03,1.532,1.03c0.891,1.529,2.341,1.089,2.91,0.833 c0.091-0.647,0.349-1.086,0.635-1.337c-2.22-0.251-4.555-1.111-4.555-4.943c0-1.091,0.39-1.984,1.03-2.682 C6.546,8.54,6.202,7.524,6.746,6.148c0,0,0.84-0.269,2.75,1.025C10.295,6.95,11.15,6.84,12,6.836 c0.85,0.004,1.705,0.114,2.504,0.336c1.909-1.294,2.748-1.025,2.748-1.025c0.546,1.376,0.202,2.394,0.1,2.646 c0.64,0.699,1.026,1.591,1.026,2.682c0,3.841-2.337,4.687-4.565,4.935c0.359,0.307,0.679,0.917,0.679,1.852 c0,1.335-0.012,2.415-0.012,2.741c0,0.269,0.18,0.579,0.688,0.481C19.138,20.161,22,16.416,22,12C22,6.477,17.523,2,12,2z"></path></svg><span class="wp-block-social-link-label screen-reader-text">GitHub</span></a></li>

<li class="wp-social-link wp-social-link-youtube  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.youtube.com/c/XojoInc" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M21.8,8.001c0,0-0.195-1.378-0.795-1.985c-0.76-0.797-1.613-0.801-2.004-0.847c-2.799-0.202-6.997-0.202-6.997-0.202 h-0.009c0,0-4.198,0-6.997,0.202C4.608,5.216,3.756,5.22,2.995,6.016C2.395,6.623,2.2,8.001,2.2,8.001S2,9.62,2,11.238v1.517 c0,1.618,0.2,3.237,0.2,3.237s0.195,1.378,0.795,1.985c0.761,0.797,1.76,0.771,2.205,0.855c1.6,0.153,6.8,0.201,6.8,0.201 s4.203-0.006,7.001-0.209c0.391-0.047,1.243-0.051,2.004-0.847c0.6-0.607,0.795-1.985,0.795-1.985s0.2-1.618,0.2-3.237v-1.517 C22,9.62,21.8,8.001,21.8,8.001z M9.935,14.594l-0.001-5.62l5.404,2.82L9.935,14.594z"></path></svg><span class="wp-block-social-link-label screen-reader-text">YouTube</span></a></li></ul>



<p class="has-text-align-center has-text-color has-link-color wp-elements-a0a2ac26ad214a49dac577734d259176" style="color:#84bd00"><a href="https://xojo.com/download/" target="_blank" rel="noreferrer noopener">Download Xojo</a></p>
]]></content:encoded>
					
		
		<enclosure url="https://blog.xojo.com/wp-content/uploads/2026/10/DesktopTable_FrozenColumns.mov" length="5935964" type="video/quicktime" />
<enclosure url="https://blog.xojo.com/wp-content/uploads/2026/10/DesktopTable_MouseGesture.mov" length="1111294" type="video/quicktime" />

			</item>
		<item>
		<title>How to code-sign Windows apps, including an automation script</title>
		<link>https://blog.xojo.com/2026/08/26/how-to-code-sign-windows-apps-including-an-automation-script/</link>
		
		<dc:creator><![CDATA[Gabriel Ludosanu]]></dc:creator>
		<pubDate>Wed, 26 Aug 2026 16:03:14 +0000</pubDate>
				<category><![CDATA[General]]></category>
		<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[Windows]]></category>
		<category><![CDATA[azure-artifact]]></category>
		<category><![CDATA[code-signing]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=16459</guid>

					<description><![CDATA[You build a Windows app, zip it up, hand it to a user, and Windows may hit them with&#160;&#8220;Windows protected your PC&#8221;. A clean but&#8230;]]></description>
										<content:encoded><![CDATA[
<p>You build a Windows app, zip it up, hand it to a user, and Windows may hit them with&nbsp;<em>&#8220;Windows protected your PC&#8221;</em>. A clean but unsigned binary has no publisher identity or established SmartScreen reputation, so Windows has little reason to trust it.</p>



<p>This guide walks you through the complete process of signing EXE and DLL files on Windows with&nbsp;<strong>Azure Artifact Signing</strong>.</p>



<p>Here&#8217;s the shape of it, so you know what you&#8217;re signing up for:</p>



<ul class="wp-block-list">
<li><strong>One-time setup (Steps 1–9):</strong>&nbsp;Azure account, portal clicks, and identity validation. This is the slow part. Budget a day to a week for the identity check to clear.</li>



<li><strong>Every build (Step 10):</strong>&nbsp;one script that signs your exe and DLLs in seconds.</li>
</ul>



<p>If you&#8217;ve already done the setup, skip straight to&nbsp;Step 10.</p>



<h2 class="wp-block-heading" id="why-i-picked-azure-artifact-signing">Why I Picked Azure Artifact Signing</h2>



<ul class="wp-block-list">
<li><strong>$9.99/mo</strong>&nbsp;for up to 5,000 signatures (Basic tier), with no USB hardware token to manage.</li>



<li><strong>Fully managed.</strong>&nbsp;Microsoft rotates the certificates daily behind the scenes. You never see or store a private key.</li>



<li><strong>Identity-based publisher reputation.</strong>&nbsp;Public Trust signing ties the signature to your validated identity instead of a certificate you manage yourself. SmartScreen warnings can still appear for first-time or low-volume downloads; signing does not guarantee they will disappear immediately.</li>
</ul>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p><strong>A note on names:</strong>&nbsp;this service was called &#8220;Azure Trusted Signing&#8221; until recently. Same thing, new name. If you see &#8220;Trusted Signing&#8221; in older docs or screenshots, it&#8217;s the same service.</p>
</blockquote>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading" id="prerequisites">Prerequisites</h2>



<ol class="wp-block-list">
<li>A Microsoft account (you get one when you sign up with Azure).</li>



<li>A&nbsp;<strong>paid Azure subscription.</strong>&nbsp;<img src="https://s.w.org/images/core/emoji/17.0.2/72x72/26a0.png" alt="⚠" class="wp-smiley" style="height: 1em; max-height: 1em;" /> This is the #1 early blocker: Artifact Signing&nbsp;<strong>does not work on free/trial/sponsored subscriptions.</strong>&nbsp;Upgrade to&nbsp;<strong>pay-as-you-go</strong>&nbsp;first (Cost Management + Billing → your subscription → upgrade) &#8211;&nbsp;<a href="https://azure.microsoft.com/en-us/products/artifact-signing" target="_blank" rel="noreferrer noopener">https://azure.microsoft.com/en-us/products/artifact-signing</a>.</li>
</ol>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading" id="step-1--register-the-resource-provider">Step 1 — Register the resource provider</h2>



<p>Quick orientation first: an Azure&nbsp;<strong>subscription</strong>&nbsp;is the billing container for everything you create. Azure charges your services to it, and it also defines where those resources live and who can access them. When you signed up, Azure created one for you automatically (often with a forgettable default name like &#8220;Azure subscription 1&#8221;).</p>



<p>A separate subscription is optional. If you want clean billing and access boundaries for signing, create or dedicate one; otherwise, use your existing paid subscription and keep the signing resources in a dedicated resource group.</p>



<p>Then:</p>



<ol class="wp-block-list">
<li>Portal →&nbsp;<strong>Subscriptions</strong>&nbsp;→ the subscription you chose.</li>



<li>Left menu →&nbsp;<strong>Settings → Resource providers</strong>.</li>



<li>Find&nbsp;<strong><code>Microsoft.CodeSigning</code></strong>&nbsp;→ click the&nbsp;<strong>…</strong>&nbsp;→&nbsp;<strong>Register</strong>. Wait for&nbsp;<strong>Registered</strong>.</li>
</ol>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading" id="step-2--create-the-artifact-signing-account">Step 2 — Create the Artifact Signing account</h2>



<p>Keep the signing resources together in the same subscription and a dedicated resource group.</p>



<ol class="wp-block-list">
<li>Portal search →&nbsp;<strong>Artifact Signing Accounts → Create</strong>.</li>



<li><strong>Subscription</strong>: the paid subscription you chose.&nbsp;<strong>Resource group</strong>: new, e.g.&nbsp;<code>rg-artifact-signing</code>.</li>



<li><strong>Account name</strong>: 3–24 alphanumeric, starts with a letter,&nbsp;<strong>globally unique</strong>&nbsp;(no consecutive hyphens). e.g.&nbsp;<code>xojoappsigning</code>.</li>



<li><strong>Region</strong>: pick one you&#8217;ll remember; it determines your signing endpoint.</li>



<li><strong>Pricing</strong>:&nbsp;<strong>Basic</strong>&nbsp;unless you&#8217;ll exceed 5,000 signs/month.</li>



<li>Create, then note the&nbsp;<strong>Account URI</strong>&nbsp;on the overview page. It follows the pattern&nbsp;<code>https://&lt;region-code&gt;.codesigning.azure.net/</code>.</li>
</ol>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading" id="step-3--assign-the-identity-verifier-role">Step 3 — Assign the Identity Verifier role</h2>



<p>You need this before the identity-validation button becomes clickable.</p>



<ol class="wp-block-list">
<li>From your Artifact Signing account, left menu →&nbsp;<strong>Access control (IAM)</strong>&nbsp;→&nbsp;<strong>Add role assignment</strong>.</li>



<li>Role:&nbsp;<strong>Artifact Signing Identity Verifier</strong>&nbsp;(use the search field) → assign to&nbsp;<strong>your own user account</strong>.</li>
</ol>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading" id="step-4--identity-validation-the-real-gate">Step 4 — Identity validation (the real gate)</h2>



<p>From your Artifact Signing account (the one you created in Step 2), go to the left menu →&nbsp;<strong>Objects → Identity validations</strong>&nbsp;→&nbsp;<strong>New Identity</strong>&nbsp;→&nbsp;<strong>Public</strong>.</p>



<p><strong>Public</strong>&nbsp;is what you want for normal app signing (it&#8217;s what SmartScreen cares about).</p>



<p>Fill in your legal business name, website, emails, business identifier (tax ID / DUNS), and address. Two gotchas that bite everyone:</p>



<ul class="wp-block-list">
<li>The&nbsp;<strong>secondary email must be on the same domain as the primary</strong>.</li>



<li><strong>Individual developers</strong>: the form pulls from your Azure&nbsp;<em>billing account</em>, and its name/address must exactly match your ID.</li>
</ul>



<p><strong>What happens next:</strong>&nbsp;status goes&nbsp;<code>In Progress</code>&nbsp;→&nbsp;<code>Action Required</code>&nbsp;(this is the point when you may have to wait a few hours to days&#8230; In my case, it took only an hour). You&#8217;ll be routed through a third-party verifier (<strong>AU10TIX</strong>). You upload a government ID and a selfie from your phone, then add the resulting&nbsp;<strong>Verified ID to Microsoft Authenticator</strong>&nbsp;and share it back (another hour or so).</p>



<p><strong>Timeline:</strong>&nbsp;officially 1–20 business days; in practice often hours to a few days. If it stalls, re-submit with a different identifier (tax ID instead of DUNS) and make sure your company name/address match your documents&nbsp;<em>exactly</em>.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading" id="step-5--create-the-certificate-profile">Step 5 — Create the certificate profile</h2>



<ol class="wp-block-list">
<li>From your Artifact Signing account, left menu →&nbsp;<strong>Objects → Certificate profiles</strong>&nbsp;→&nbsp;<strong>Create</strong>.</li>



<li>Type:&nbsp;<strong>Public Trust</strong>.</li>



<li>Name it (5–100 chars), then pick your completed identity validation under&nbsp;<strong>Verified CN and O</strong>.</li>



<li>Create. You never see or hold the certificate. It&#8217;s rotated daily behind the scenes. The public cert is embedded in every file you sign.</li>
</ol>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading" id="step-6--assign-the-certificate-profile-signer-role">Step 6 — Assign the Certificate Profile Signer role</h2>



<p>This is the role that lets you actually sign. Because we&#8217;re using the Azure CLI, it goes on&nbsp;<strong>your user</strong>. No app registration is needed (this is a separate/alternative process, but we&#8217;re not talking about that in this article).</p>



<ol class="wp-block-list">
<li>From your Artifact Signing account, left menu →&nbsp;<strong>Access control (IAM)</strong>&nbsp;→&nbsp;<strong>Add role assignment</strong>.</li>



<li>Role:&nbsp;<strong>Artifact Signing Certificate Profile Signer</strong>&nbsp;→ assign to&nbsp;<strong>your own user account</strong>.</li>
</ol>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p>Give role assignments a few minutes to propagate. If you try signing immediately and hit a 403, wait ~5 minutes and retry.</p>
</blockquote>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading" id="step-7--install-the-signing-tools">Step 7 — Install the signing tools</h2>



<p>First, the <strong>Azure CLI</strong>: <code>winget install Microsoft.AzureCLI</code></p>



<p><em>You’ll use it in Step 9 to authenticate with Azure.</em></p>



<p><strong>SignTool</strong>&nbsp;comes with the Windows SDK. Install it with: <code>winget install --id Microsoft.WindowsSDK --exact</code></p>



<p><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/26a0.png" alt="⚠" class="wp-smiley" style="height: 1em; max-height: 1em;" />&nbsp;Run this to find the newest x64&nbsp;signtool.exe:<br><code>Get-ChildItem "C:\Program Files (x86)\Windows Kits\10\bin" -Recurse -Filter signtool.exe | Where-Object { $_.FullName -match '\\x64\\signtool\.exe$' } | Sort-Object FullName -Descending | Select-Object -First 1 -ExpandProperty FullName</code></p>



<p><em>Note the path down.</em></p>



<p><strong>.NET 8 runtime</strong>&nbsp;(x64).</p>



<p><strong>Microsoft Visual C++ Redistributable</strong>.</p>



<p><strong>Artifact Signing Client Tools</strong>:<code>winget install -e --id Microsoft.Azure.ArtifactSigningClientTools</code><br>This installs&nbsp;<code>Azure.CodeSigning.Dlib.dll</code>&nbsp;(the plugin signtool uses to talk to Azure).</p>



<p><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/26a0.png" alt="⚠" class="wp-smiley" style="height: 1em; max-height: 1em;" />&nbsp;Locate the actual dll path after install:<br><code>Get-ChildItem -Path "C:\Program Files","$env:LOCALAPPDATA" -Recurse -Filter Azure.CodeSigning.Dlib.dll -ErrorAction SilentlyContinue | Select-Object -First 1 -ExpandProperty FullName</code></p>



<p><em>Note the path down.</em></p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p>If&nbsp;<code>signtool</code>&nbsp;gives you &#8220;command not found&#8221;, that&#8217;s normal; it&#8217;s not on PATH. Use the full path, or add&nbsp;<code>...\10\&lt;version&gt;\x64</code>&nbsp;to your PATH.</p>
</blockquote>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading" id="step-8--create-the-metadata-file">Step 8 — Create the metadata file</h2>



<p>This is a small JSON with three values. Name it anything you like, e.g.&nbsp;<code>artifact-code-signing.json</code>:</p>



<pre class="wp-block-code"><code>{
	"Endpoint": "https://&lt;region-code&gt;.codesigning.azure.net",
	"CodeSigningAccountName": "xojoappsigning",
	"CertificateProfileName": "...."
}</code></pre>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p>This JSON file will be used a lot, so save it somewhere safe.</p>
</blockquote>



<ul class="wp-block-list">
<li><strong>Endpoint</strong>&nbsp;= your account URI (region-specific; must match where the account + profile live, or you get a 403).</li>



<li><strong>CodeSigningAccountName</strong>&nbsp;= the Artifact Signing account name from Step 2.</li>



<li><strong>CertificateProfileName</strong>&nbsp;= the certificate profile name you created in Step 5.</li>
</ul>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading" id="step-9--authenticate-with-the-azure-cli">Step 9 — Authenticate with the Azure CLI</h2>



<pre class="wp-block-code"><code>az login</code></pre>



<p>This opens your browser; sign in with the Microsoft account tied to your Azure subscription. When signtool runs, the dlib picks up your logged-in Azure CLI session automatically.</p>



<p>If you have multiple Azure subscriptions, point the CLI at the right one, then confirm it took:</p>



<pre class="wp-block-code"><code>az account set --subscription "&lt;your subscription id&gt;"
az account show --query name -o tsv</code></pre>



<p>The second command should print your code-signing subscription&#8217;s name. If you also have multiple Microsoft tenants (a personal account&nbsp;<em>and</em>&nbsp;a work account, for example), log straight into the right one:</p>



<pre class="wp-block-code"><code>az login --tenant "&lt;tenant id&gt;"</code></pre>



<p>You may occasionally need to re-run&nbsp;<code>az login</code>&nbsp;after long idle periods.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading" id="step-10--sign-your-xojo-app">Step 10 — Sign your Xojo app</h2>



<p>Just remember, you need to&nbsp;<strong>sign the compiled application after each new build</strong>.</p>



<h3 class="wp-block-heading" id="what-to-sign-and-skip">What to sign (and skip)</h3>



<p>Your Xojo Windows build folder looks roughly like this. Sign the binaries you build or distribute under your publisher identity; leave Xojo, Microsoft, and other vendor-signed dependencies alone.</p>



<pre class="wp-block-code"><code>Windows 64 bit/
└── YourApp/
    ├── YourApp.exe              ← sign
    ├── &lt;your own DLLs&gt;          ← sign
    ├── XojoGUIFramework64.dll   ← skip, Xojo provides signed DLLs
    ├── YourApp Libs/            ← skip, Xojo provides signed DLLs
    ├── msvcp140.dll, vcruntime*.dll …  ← skip (Microsoft runtime)
    └── YourApp.exe.WebView2/    ← skip (WebView2 cache)
</code></pre>



<h3 class="wp-block-heading" id="the-script">The script</h3>



<p>Save this as&nbsp;<code>sign.ps1</code>, next to the Xojo project, update the paths at the top, and run it from PowerShell:</p>



<pre class="wp-block-code"><code>$ErrorActionPreference = "Stop"

$Signtool    = "C:\...\signtool.exe"                            <em># path from Step 7</em>
$Dlib        = "C:\...\Azure.CodeSigning.Dlib.dll"              <em># path from Step 7</em>
$Metadata    = "C:\...\artifact-code-signing.json"              <em># from Step 8</em>
$BuildFolder = "F:\...\YourApp"                                 <em># folder containing YourApp.exe</em>

<em># Installer (Inno Setup) — optional. Set $EnableInno to $false to skip this part.</em>
$EnableInno  = $true
$InnoSetup   = "C:\Program Files (x86)\Inno Setup 6\ISCC.exe"
$IssScript   = "F:\...\YourAppSetup.iss"                        <em># your Inno Setup script</em>
$Installer   = "F:\...\YourAppSetup.exe"                        <em># output from the .iss</em>

<em># Sign binaries you build or distribute under your publisher identity.</em>
<em># Leave Xojo, Microsoft, and other vendor-signed dependencies alone.</em>
$FilesToSign = @(
    "$BuildFolder\YourApp.exe"
    "$BuildFolder\MyPlugin.dll"
    <em># add any other files you own here, one per line</em>
)

function Invoke-SigningCommand {
    param(&#91;string&#91;]]$Arguments)

    &amp; $Signtool @Arguments
    if ($LASTEXITCODE -ne 0) {
        throw "SignTool failed with exit code $LASTEXITCODE."
    }
}

foreach ($f in $FilesToSign) {
    Invoke-SigningCommand @(
        "sign", "/v", "/fd", "SHA256",
        "/tr", "http://timestamp.acs.microsoft.com", "/td", "SHA256",
        "/dlib", $Dlib, "/dmdf", $Metadata,
        $f
    )
}

if ($EnableInno) {
    <em># Build a fresh installer, then sign it.</em>
    &amp; $InnoSetup $IssScript
    if ($LASTEXITCODE -ne 0) {
        throw "Inno Setup failed with exit code $LASTEXITCODE."
    }

    Invoke-SigningCommand @(
        "sign", "/v", "/fd", "SHA256",
        "/tr", "http://timestamp.acs.microsoft.com", "/td", "SHA256",
        "/dlib", $Dlib, "/dmdf", $Metadata,
        $Installer
    )
}</code></pre>



<p>What the flags mean:</p>



<ul class="wp-block-list">
<li><code>/tr http://timestamp.acs.microsoft.com</code>: the timestamp server. The&nbsp;<code>http://</code>&nbsp;(not https) is intentional.</li>



<li><code>/fd SHA256</code>&nbsp;and&nbsp;<code>/td SHA256</code>: SHA-256 for the file and the timestamp.</li>



<li><code>/dlib</code>: the Azure plugin from Step 7.&nbsp;<code>/dmdf</code>: your metadata JSON from Step 8.</li>
</ul>



<h3 class="wp-block-heading" id="confirm-it-worked">Confirm it worked</h3>



<p>Two checks:</p>



<ol class="wp-block-list">
<li><strong>Signtool:</strong><code>$Signtool verify /v /pa "$BuildFolder\YourApp.exe" </code>You want to see&nbsp;<code>Successfully verified</code>.</li>



<li><strong>Or:</strong>&nbsp;right-click&nbsp;<code>YourApp.exe</code>&nbsp;→&nbsp;<strong>Properties → Digital Signatures</strong>&nbsp;→ your org name should be listed.</li>
</ol>



<h3 class="wp-block-heading" id="rules-of-thumb">Rules of thumb</h3>



<ul class="wp-block-list">
<li><strong>Sign after every build.</strong>&nbsp;Each new&nbsp;<code>.exe</code>&nbsp;is a fresh unsigned binary.</li>



<li><strong>Sign before you zip.</strong>&nbsp;Sign the files,&nbsp;<em>then</em>&nbsp;package them. Signing inside a zip does nothing.</li>
</ul>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading" id="troubleshooting">Troubleshooting</h2>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th class="has-text-align-left" data-align="left">Symptom</th><th class="has-text-align-left" data-align="left">Fix</th></tr></thead><tbody><tr><td><code>signtool: command not found</code></td><td>Use the full SDK path; it&#8217;s not on PATH</td></tr><tr><td><code>No certificates were found</code></td><td>dlib path wrong, or x86/x64 mismatch between signtool and dlib</td></tr><tr><td><code>403 Forbidden</code></td><td>Signer role on the wrong account, wrong account name in JSON, or endpoint/region mismatch</td></tr><tr><td><code>SignTool Error: An unexpected internal error</code></td><td>Update signtool to ≥ 10.0.22621.755; check .NET 8 + VC++ redist</td></tr><tr><td>Signing appeared to succeed, but no signature is visible</td><td>Run&nbsp;<code>signtool verify /v /pa &lt;file&gt;</code>; its exit code and&nbsp;<code>Successfully verified</code>&nbsp;output are authoritative. Explorer&#8217;s Digital Signatures tab is not available for every file type.</td></tr></tbody></table></figure>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading" id="recap">Recap</h2>



<p><strong>One time (Steps 1–9):</strong>&nbsp;register the&nbsp;<code>Microsoft.CodeSigning</code>&nbsp;provider → create the account → assign the Identity Verifier role → complete identity validation (slow&#8217;ish) → create the certificate profile → assign the Signer role → install tools → write the metadata JSON →&nbsp;<code>az login</code>.</p>



<p><strong>Every build (Step 10):</strong>&nbsp;run&nbsp;<code>sign.ps1</code>.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading" id="the-bottom-line">The bottom line</h2>



<p>Azure Artifact Signing is a low-cost managed option for signing Windows apps, and Azure CLI authentication means local builds do not need a stored signing private key. The setup has some Azure bureaucracy, and identity validation is the slow part. After that, it is one script per build.</p>



<h4 class="wp-block-heading">Related discussion</h4>



<p>For an alternative approach that automates Xojo application signing and Inno Setup installer creation, see Jürg Otter’s Xojo Forum topic, <a href="https://forum.xojo.com/t/windows-code-signing-installer-creation-with-innosetup/84732" target="_blank" rel="noreferrer noopener">Windows Code Signing &amp; Installer Creation with Inno Setup</a>. The topic includes Jürg’s open-source code, which supports both Azure Artifact Signing and traditional <code>.pfx</code> certificates.</p>



<p><em>Gabriel is a digital marketing enthusiast who loves coding with Xojo to create cool software tools for any platform. He is always eager to learn and share new ideas!</em></p>



<ul class="wp-block-social-links has-normal-icon-size is-content-justification-center is-layout-flex wp-container-core-social-links-is-layout-16018d1d wp-block-social-links-is-layout-flex"><li class="wp-social-link wp-social-link-facebook  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.facebook.com/goxojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M12 2C6.5 2 2 6.5 2 12c0 5 3.7 9.1 8.4 9.9v-7H7.9V12h2.5V9.8c0-2.5 1.5-3.9 3.8-3.9 1.1 0 2.2.2 2.2.2v2.5h-1.3c-1.2 0-1.6.8-1.6 1.6V12h2.8l-.4 2.9h-2.3v7C18.3 21.1 22 17 22 12c0-5.5-4.5-10-10-10z"></path></svg><span class="wp-block-social-link-label screen-reader-text">Facebook</span></a></li>

<li class="wp-social-link wp-social-link-x  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://x.com/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M13.982 10.622 20.54 3h-1.554l-5.693 6.618L8.745 3H3.5l6.876 10.007L3.5 21h1.554l6.012-6.989L15.868 21h5.245l-7.131-10.378Zm-2.128 2.474-.697-.997-5.543-7.93H8l4.474 6.4.697.996 5.815 8.318h-2.387l-4.745-6.787Z" /></svg><span class="wp-block-social-link-label screen-reader-text">X</span></a></li>

<li class="wp-social-link wp-social-link-linkedin  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.linkedin.com/company/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M19.7,3H4.3C3.582,3,3,3.582,3,4.3v15.4C3,20.418,3.582,21,4.3,21h15.4c0.718,0,1.3-0.582,1.3-1.3V4.3 C21,3.582,20.418,3,19.7,3z M8.339,18.338H5.667v-8.59h2.672V18.338z M7.004,8.574c-0.857,0-1.549-0.694-1.549-1.548 c0-0.855,0.691-1.548,1.549-1.548c0.854,0,1.547,0.694,1.547,1.548C8.551,7.881,7.858,8.574,7.004,8.574z M18.339,18.338h-2.669 v-4.177c0-0.996-0.017-2.278-1.387-2.278c-1.389,0-1.601,1.086-1.601,2.206v4.249h-2.667v-8.59h2.559v1.174h0.037 c0.356-0.675,1.227-1.387,2.526-1.387c2.703,0,3.203,1.779,3.203,4.092V18.338z"></path></svg><span class="wp-block-social-link-label screen-reader-text">LinkedIn</span></a></li>

<li class="wp-social-link wp-social-link-github  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://github.com/topics/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M12,2C6.477,2,2,6.477,2,12c0,4.419,2.865,8.166,6.839,9.489c0.5,0.09,0.682-0.218,0.682-0.484 c0-0.236-0.009-0.866-0.014-1.699c-2.782,0.602-3.369-1.34-3.369-1.34c-0.455-1.157-1.11-1.465-1.11-1.465 c-0.909-0.62,0.069-0.608,0.069-0.608c1.004,0.071,1.532,1.03,1.532,1.03c0.891,1.529,2.341,1.089,2.91,0.833 c0.091-0.647,0.349-1.086,0.635-1.337c-2.22-0.251-4.555-1.111-4.555-4.943c0-1.091,0.39-1.984,1.03-2.682 C6.546,8.54,6.202,7.524,6.746,6.148c0,0,0.84-0.269,2.75,1.025C10.295,6.95,11.15,6.84,12,6.836 c0.85,0.004,1.705,0.114,2.504,0.336c1.909-1.294,2.748-1.025,2.748-1.025c0.546,1.376,0.202,2.394,0.1,2.646 c0.64,0.699,1.026,1.591,1.026,2.682c0,3.841-2.337,4.687-4.565,4.935c0.359,0.307,0.679,0.917,0.679,1.852 c0,1.335-0.012,2.415-0.012,2.741c0,0.269,0.18,0.579,0.688,0.481C19.138,20.161,22,16.416,22,12C22,6.477,17.523,2,12,2z"></path></svg><span class="wp-block-social-link-label screen-reader-text">GitHub</span></a></li>

<li class="wp-social-link wp-social-link-youtube  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.youtube.com/c/XojoInc" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M21.8,8.001c0,0-0.195-1.378-0.795-1.985c-0.76-0.797-1.613-0.801-2.004-0.847c-2.799-0.202-6.997-0.202-6.997-0.202 h-0.009c0,0-4.198,0-6.997,0.202C4.608,5.216,3.756,5.22,2.995,6.016C2.395,6.623,2.2,8.001,2.2,8.001S2,9.62,2,11.238v1.517 c0,1.618,0.2,3.237,0.2,3.237s0.195,1.378,0.795,1.985c0.761,0.797,1.76,0.771,2.205,0.855c1.6,0.153,6.8,0.201,6.8,0.201 s4.203-0.006,7.001-0.209c0.391-0.047,1.243-0.051,2.004-0.847c0.6-0.607,0.795-1.985,0.795-1.985s0.2-1.618,0.2-3.237v-1.517 C22,9.62,21.8,8.001,21.8,8.001z M9.935,14.594l-0.001-5.62l5.404,2.82L9.935,14.594z"></path></svg><span class="wp-block-social-link-label screen-reader-text">YouTube</span></a></li></ul>



<p class="has-text-align-center has-text-color has-link-color wp-elements-a0a2ac26ad214a49dac577734d259176" style="color:#84bd00"><a href="https://xojo.com/download/" target="_blank" rel="noreferrer noopener">Download Xojo</a></p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>DesktopHTMLViewer Adds WebView2 Support on Windows</title>
		<link>https://blog.xojo.com/2026/07/08/desktophtmlviewer-adds-webview2-support-on-windows/</link>
		
		<dc:creator><![CDATA[William Yu]]></dc:creator>
		<pubDate>Wed, 08 Jul 2026 13:46:00 +0000</pubDate>
				<category><![CDATA[Desktop]]></category>
		<category><![CDATA[General]]></category>
		<category><![CDATA[Learning]]></category>
		<category><![CDATA[Tips]]></category>
		<category><![CDATA[Windows]]></category>
		<category><![CDATA[2026r2]]></category>
		<category><![CDATA[CEF]]></category>
		<category><![CDATA[DesktopHTMLViewer]]></category>
		<category><![CDATA[WebView2]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=16355</guid>

					<description><![CDATA[In Xojo 2026r2, developers targeting Windows now have a new option for&#160;DesktopHTMLViewer: support for Microsoft Edge WebView2. This is an important change for those who&#8230;]]></description>
										<content:encoded><![CDATA[
<p>In Xojo 2026r2, developers targeting Windows now have a new option for&nbsp;DesktopHTMLViewer: support for Microsoft Edge WebView2.</p>



<p>This is an important change for those who want modern web rendering on Windows without the large deployment footprint required by the Chromium Embedded Framework (CEF).</p>



<h2 class="wp-block-heading">Why WebView2 Matters</h2>



<p>Until now, Windows HTML rendering in&nbsp;DesktopHTMLViewer&nbsp;has primarily relied on CEF. While CEF provides excellent compatibility and a consistent Chromium-based rendering engine, it also comes with a substantial deployment cost. Including the required CEF runtime files can add well over 200 MB to an application&#8217;s distribution size.</p>



<p>Using CEF also means applications are tied to specific Chromium and CEF versions bundled with the app itself. Keeping current requires continuously rebuilding and redistributing newer CEF releases as Chromium evolves and security updates are released.</p>



<p>WebView2 changes that equation considerably.</p>



<p>Because WebView2 uses the Microsoft Edge rendering engine already present on many modern Windows systems, applications can avoid bundling a large embedded Chromium runtime entirely. Security and changes to WebView2 are handled through the operating system via Windows Update, rather than requiring applications to ship and maintain their own browser engine updates.</p>



<h2 class="wp-block-heading">WebView2 Runtime Requirements</h2>



<p>One important consideration is that WebView2 may require the Microsoft Edge WebView2 Runtime to be installed on the target system.</p>



<h3 class="wp-block-heading">Windows 11</h3>



<p>Most Windows 11 systems already include WebView2 as part of the operating system, so no additional installation is usually necessary.</p>



<h3 class="wp-block-heading">Windows 10</h3>



<p>Many Windows 10 systems already have the runtime installed because Microsoft distributes it through Edge and Microsoft 365 updates. However, older or managed systems may still require a separate runtime installation.</p>



<p>Applications that depend on WebView2 should verify runtime availability during installation and, if it is not present, either prompt the user or provide a link to download and install the required runtime.</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f449.png" alt="👉" class="wp-smiley" style="height: 1em; max-height: 1em;" /> You can also check&nbsp;<code>DesktopHTMLViewer.IsAvailable</code>&nbsp;at runtime to determine whether WebView2 is available.</p>
</blockquote>



<p>Microsoft provides the runtime here:<br><a href="https://developer.microsoft.com/en-us/microsoft-edge/webview2/" target="_blank" rel="noreferrer noopener">https://developer.microsoft.com/en-us/microsoft-edge/webview2/</a></p>



<h2 class="wp-block-heading">WinUI Targets Use WebView2 by Default</h2>



<p>For WinUI desktop targets, WebView2 is now the default (and only) HTML rendering engine for the DesktopHTMLViewer. In addition, any new projects created in Xojo 2026r2 or later will default to using the WebView2 engine whenever a&nbsp;DesktopHTMLViewer&nbsp;is added to the layout.</p>



<h3 class="wp-block-heading">Enabling WebView2 in older projects or non-WinUI Windows targets</h3>



<p>For traditional Windows desktop targets that are not using WinUI, you can still opt into WebView2 support by enabling the <strong>HTMLViewer uses WebView2</strong> option in the Advanced Windows build setting in the IDE:</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="692" src="https://blog.xojo.com/wp-content/uploads/2026/06/HTMLViewerUsersWebView2-1024x692.png" alt="" class="wp-image-16364" srcset="https://blog.xojo.com/wp-content/uploads/2026/06/HTMLViewerUsersWebView2-1024x692.png 1024w, https://blog.xojo.com/wp-content/uploads/2026/06/HTMLViewerUsersWebView2-300x203.png 300w, https://blog.xojo.com/wp-content/uploads/2026/06/HTMLViewerUsersWebView2-768x519.png 768w, https://blog.xojo.com/wp-content/uploads/2026/06/HTMLViewerUsersWebView2.png 1504w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<p>When enabled,&nbsp;DesktopHTMLViewer&nbsp;will use WebView2 instead of CEF for HTML rendering.</p>



<p>This gives you the flexibility to choose between:</p>



<ul class="wp-block-list">
<li>smaller deployment size with WebView2, or</li>



<li>fully self-contained deployment with CEF</li>
</ul>



<p>depending on the needs of your application and target audience. However, moving forward we will be transitioning away from CEF entirely, and it is likely that we will no longer support or update our CEF based HTMLViewer in future releases.</p>



<h2 class="wp-block-heading">Differences from CEF</h2>



<p>Although both CEF and WebView2 are Chromium-based technologies, there are some behavioral differences you should be aware of:</p>



<ul class="wp-block-list">
<li>You may notice some subtle differences in how WebView2 returns results for JSON.Stringify when executed using ExecuteJavaScriptSync. i.e. the result coming back may be quoted.</li>



<li>executeInXojoSync is supported, but it uses JavaScript Promises to simulate synchronous behavior, so existing code may need to be updated to use async/await. Example:&nbsp;<code>const result = await executeInXojoSync("addNumbers", 2, 3);</code></li>



<li>A WebView2-specific cache folder is created alongside the executable. If that directory is not writable, the cache folder is instead created in the user&#8217;s local AppData directory.</li>
</ul>



<h2 class="wp-block-heading">Final Thoughts</h2>



<p>The addition of WebView2 support for&nbsp;DesktopHTMLViewer&nbsp;is a major improvement for Windows desktop deployment in Xojo, and reducing runtime size by hundreds of megabytes while still delivering modern Chromium-based rendering is a significant win.</p>



<p>Those who require rendering consistency or offline/self-contained deployments may still prefer CEF, but WebView2 offers an excellent modern alternative that better matches the direction of the Windows platform itself.</p>



<p>For now, you can choose between either engine depending on your needs, but moving forward we believe WebView2 is the preferred path on Windows. Happy browsing!</p>



<p><em><em><em>William Yu grew up in Canada learning to program BASIC on a Vic-20. He is Xojo’s resident Windows and Linux engineer, among his many other skills. Some may say he has joined the dark side here in the USA, but he will always be a Canadian at heart.</em></em></em></p>



<ul class="wp-block-social-links has-normal-icon-size is-content-justification-center is-layout-flex wp-container-core-social-links-is-layout-16018d1d wp-block-social-links-is-layout-flex"><li class="wp-social-link wp-social-link-facebook  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.facebook.com/goxojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M12 2C6.5 2 2 6.5 2 12c0 5 3.7 9.1 8.4 9.9v-7H7.9V12h2.5V9.8c0-2.5 1.5-3.9 3.8-3.9 1.1 0 2.2.2 2.2.2v2.5h-1.3c-1.2 0-1.6.8-1.6 1.6V12h2.8l-.4 2.9h-2.3v7C18.3 21.1 22 17 22 12c0-5.5-4.5-10-10-10z"></path></svg><span class="wp-block-social-link-label screen-reader-text">Facebook</span></a></li>

<li class="wp-social-link wp-social-link-x  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://x.com/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M13.982 10.622 20.54 3h-1.554l-5.693 6.618L8.745 3H3.5l6.876 10.007L3.5 21h1.554l6.012-6.989L15.868 21h5.245l-7.131-10.378Zm-2.128 2.474-.697-.997-5.543-7.93H8l4.474 6.4.697.996 5.815 8.318h-2.387l-4.745-6.787Z" /></svg><span class="wp-block-social-link-label screen-reader-text">X</span></a></li>

<li class="wp-social-link wp-social-link-linkedin  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.linkedin.com/company/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M19.7,3H4.3C3.582,3,3,3.582,3,4.3v15.4C3,20.418,3.582,21,4.3,21h15.4c0.718,0,1.3-0.582,1.3-1.3V4.3 C21,3.582,20.418,3,19.7,3z M8.339,18.338H5.667v-8.59h2.672V18.338z M7.004,8.574c-0.857,0-1.549-0.694-1.549-1.548 c0-0.855,0.691-1.548,1.549-1.548c0.854,0,1.547,0.694,1.547,1.548C8.551,7.881,7.858,8.574,7.004,8.574z M18.339,18.338h-2.669 v-4.177c0-0.996-0.017-2.278-1.387-2.278c-1.389,0-1.601,1.086-1.601,2.206v4.249h-2.667v-8.59h2.559v1.174h0.037 c0.356-0.675,1.227-1.387,2.526-1.387c2.703,0,3.203,1.779,3.203,4.092V18.338z"></path></svg><span class="wp-block-social-link-label screen-reader-text">LinkedIn</span></a></li>

<li class="wp-social-link wp-social-link-github  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://github.com/topics/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M12,2C6.477,2,2,6.477,2,12c0,4.419,2.865,8.166,6.839,9.489c0.5,0.09,0.682-0.218,0.682-0.484 c0-0.236-0.009-0.866-0.014-1.699c-2.782,0.602-3.369-1.34-3.369-1.34c-0.455-1.157-1.11-1.465-1.11-1.465 c-0.909-0.62,0.069-0.608,0.069-0.608c1.004,0.071,1.532,1.03,1.532,1.03c0.891,1.529,2.341,1.089,2.91,0.833 c0.091-0.647,0.349-1.086,0.635-1.337c-2.22-0.251-4.555-1.111-4.555-4.943c0-1.091,0.39-1.984,1.03-2.682 C6.546,8.54,6.202,7.524,6.746,6.148c0,0,0.84-0.269,2.75,1.025C10.295,6.95,11.15,6.84,12,6.836 c0.85,0.004,1.705,0.114,2.504,0.336c1.909-1.294,2.748-1.025,2.748-1.025c0.546,1.376,0.202,2.394,0.1,2.646 c0.64,0.699,1.026,1.591,1.026,2.682c0,3.841-2.337,4.687-4.565,4.935c0.359,0.307,0.679,0.917,0.679,1.852 c0,1.335-0.012,2.415-0.012,2.741c0,0.269,0.18,0.579,0.688,0.481C19.138,20.161,22,16.416,22,12C22,6.477,17.523,2,12,2z"></path></svg><span class="wp-block-social-link-label screen-reader-text">GitHub</span></a></li>

<li class="wp-social-link wp-social-link-youtube  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.youtube.com/c/XojoInc" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M21.8,8.001c0,0-0.195-1.378-0.795-1.985c-0.76-0.797-1.613-0.801-2.004-0.847c-2.799-0.202-6.997-0.202-6.997-0.202 h-0.009c0,0-4.198,0-6.997,0.202C4.608,5.216,3.756,5.22,2.995,6.016C2.395,6.623,2.2,8.001,2.2,8.001S2,9.62,2,11.238v1.517 c0,1.618,0.2,3.237,0.2,3.237s0.195,1.378,0.795,1.985c0.761,0.797,1.76,0.771,2.205,0.855c1.6,0.153,6.8,0.201,6.8,0.201 s4.203-0.006,7.001-0.209c0.391-0.047,1.243-0.051,2.004-0.847c0.6-0.607,0.795-1.985,0.795-1.985s0.2-1.618,0.2-3.237v-1.517 C22,9.62,21.8,8.001,21.8,8.001z M9.935,14.594l-0.001-5.62l5.404,2.82L9.935,14.594z"></path></svg><span class="wp-block-social-link-label screen-reader-text">YouTube</span></a></li></ul>



<p class="has-text-align-center has-text-color has-link-color wp-elements-a0a2ac26ad214a49dac577734d259176" style="color:#84bd00"><a href="https://xojo.com/download/" target="_blank" rel="noreferrer noopener">Download Xojo</a></p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>New DesktopToolbar Enhancements</title>
		<link>https://blog.xojo.com/2026/07/08/new-desktoptoolbar-enhancements/</link>
		
		<dc:creator><![CDATA[William Yu]]></dc:creator>
		<pubDate>Wed, 08 Jul 2026 13:45:00 +0000</pubDate>
				<category><![CDATA[Cross-Platform]]></category>
		<category><![CDATA[Desktop]]></category>
		<category><![CDATA[General]]></category>
		<category><![CDATA[Learning]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[Mac]]></category>
		<category><![CDATA[Tips]]></category>
		<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[Windows]]></category>
		<category><![CDATA[2026r2]]></category>
		<category><![CDATA[DesktopToolbar]]></category>
		<category><![CDATA[Symbols]]></category>
		<category><![CDATA[Toolbar]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=16368</guid>

					<description><![CDATA[The latest updates to DesktopToolbar add new options that make toolbars easier to customize across all platforms, along with support for WinUI on Windows. These&#8230;]]></description>
										<content:encoded><![CDATA[
<p>The latest updates to DesktopToolbar add new options that make toolbars easier to customize across all platforms, along with support for WinUI on Windows.</p>



<p>These changes focus on two main areas:</p>



<ul class="wp-block-list">
<li>Expanded button symbol support in&nbsp;DesktopToolbarButton</li>



<li>New layout and presentation control via toolbar style options</li>
</ul>



<h2 class="wp-block-heading">Smarter Icon Handling with Symbols</h2>



<p>A key addition is the new <code>Symbol</code> property on DesktopToolbarButton. It lets you provide a single string containing multiple symbol names separated by semicolons. Each platform will then check that list and use the first symbol it recognizes.</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f449.png" alt="👉" class="wp-smiley" style="height: 1em; max-height: 1em;" /> The Symbol feature is only supported on Windows when using the WinUI target.</p>



<p><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f449.png" alt="👉" class="wp-smiley" style="height: 1em; max-height: 1em;" /> AllowMulticolorSymbol was added for macOS. When enabled, the OS may render toolbar symbols using multicolor variants where available, instead of enforcing monochrome styling.</p>
</blockquote>



<h3 class="wp-block-heading">Example</h3>



<pre class="wp-block-code"><code>home.Symbol = "house.fill;home;go-home"
home.AllowMulticolorSymbol = True
back.Symbol = "chevron.left;back;go-previous"
forward.Symbol = "chevron.right;forward;go-forward"
search.Symbol = "magnifyingglass;find;system-search"</code></pre>



<div class="wp-block-columns is-layout-flex wp-container-core-columns-is-layout-9d6595d7 wp-block-columns-is-layout-flex">
<div class="wp-block-column is-vertically-aligned-center is-layout-flow wp-block-column-is-layout-flow" style="flex-basis:33.34%"><div class="wp-block-image">
<figure class="aligncenter size-full"><img loading="lazy" decoding="async" width="684" height="542" src="https://blog.xojo.com/wp-content/uploads/2026/06/ToolbarMacOS.png" alt="" class="wp-image-16372" style="aspect-ratio:1.2620603364382037;object-fit:cover" srcset="https://blog.xojo.com/wp-content/uploads/2026/06/ToolbarMacOS.png 684w, https://blog.xojo.com/wp-content/uploads/2026/06/ToolbarMacOS-300x238.png 300w" sizes="auto, (max-width: 684px) 100vw, 684px" /></figure>
</div></div>



<div class="wp-block-column is-vertically-aligned-center is-layout-flow wp-block-column-is-layout-flow" style="flex-basis:33.34%"><div class="wp-block-image">
<figure class="aligncenter size-full"><img loading="lazy" decoding="async" width="822" height="394" src="https://blog.xojo.com/wp-content/uploads/2026/06/ToolbarLinux2-1.png" alt="" class="wp-image-16378" srcset="https://blog.xojo.com/wp-content/uploads/2026/06/ToolbarLinux2-1.png 822w, https://blog.xojo.com/wp-content/uploads/2026/06/ToolbarLinux2-1-300x144.png 300w, https://blog.xojo.com/wp-content/uploads/2026/06/ToolbarLinux2-1-768x368.png 768w" sizes="auto, (max-width: 822px) 100vw, 822px" /></figure>
</div></div>



<div class="wp-block-column is-vertically-aligned-center is-layout-flow wp-block-column-is-layout-flow" style="flex-basis:33.33%"><div class="wp-block-image">
<figure class="aligncenter size-full"><img loading="lazy" decoding="async" width="589" height="296" src="https://blog.xojo.com/wp-content/uploads/2026/06/ToolbarWindows.png" alt="" class="wp-image-16374" srcset="https://blog.xojo.com/wp-content/uploads/2026/06/ToolbarWindows.png 589w, https://blog.xojo.com/wp-content/uploads/2026/06/ToolbarWindows-300x151.png 300w" sizes="auto, (max-width: 589px) 100vw, 589px" /></figure>
</div></div>
</div>



<h3 class="wp-block-heading">How it works</h3>



<p>Instead of relying only on a static icon, the toolbar now attempts to resolve a&nbsp;<em>symbol first</em>. If a symbol is found, it is used in preference to any icon.</p>



<p>The lookup order is:</p>



<ol class="wp-block-list">
<li>First matching symbol in the list</li>



<li>If none resolve, fallback to the standard icon (if one is set)</li>
</ol>



<p>This allows you to provide multiple symbolic names as a fallback chain, improving cross-theme and cross-platform reliability.</p>



<h3 class="wp-block-heading">Where to find the list of supported symbols</h3>



<p>WinUI:&nbsp;<a href="https://learn.microsoft.com/en-us/uwp/api/windows.ui.xaml.controls.symbol" rel="noreferrer noopener" target="_blank">https://learn.microsoft.com/en-us/uwp/api/windows.ui.xaml.controls.symbol</a></p>



<p>Linux:&nbsp;<a href="https://specifications.freedesktop.org/icon-naming" rel="noreferrer noopener" target="_blank">https://specifications.freedesktop.org/icon-naming</a></p>



<p>macOS:&nbsp;<a href="https://developer.apple.com/design/human-interface-guidelines/sf-symbols" rel="noreferrer noopener" target="_blank">https://developer.apple.com/design/human-interface-guidelines/sf-symbols</a></p>



<h2 class="wp-block-heading">Better Control Over Toolbar Layout</h2>



<p>The toolbar itself now supports a new&nbsp;<code>Style</code>&nbsp;property.  This controls how buttons are visually arranged.</p>



<p><strong>DesktopToolbarStyles options</strong>:</p>



<ul class="wp-block-list">
<li><strong>Default</strong>
<ul class="wp-block-list">
<li>Generally icon/symbol on top, caption below</li>



<li>On Linux and WinUI: icon/symbol on left, caption on right</li>
</ul>
</li>



<li><strong>IconCaptionVertical</strong>
<ul class="wp-block-list">
<li>Forces vertical layout (icon/symbol above text)</li>
</ul>
</li>



<li><strong>IconCaptionHorizontal</strong>
<ul class="wp-block-list">
<li>Forces horizontal layout (icon/symbol beside text)</li>



<li>Only supported on Linux and Windows</li>
</ul>
</li>



<li><strong>IconOnly</strong>
<ul class="wp-block-list">
<li>Displays only the icon/symbol</li>
</ul>
</li>



<li><strong>CaptionOnly</strong>
<ul class="wp-block-list">
<li>Displays only text labels</li>
</ul>
</li>
</ul>



<div class="wp-block-columns is-layout-flex wp-container-core-columns-is-layout-9d6595d7 wp-block-columns-is-layout-flex">
<div class="wp-block-column is-vertically-aligned-center is-layout-flow wp-block-column-is-layout-flow">
<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="676" height="524" src="https://blog.xojo.com/wp-content/uploads/2026/06/ToolbarMacOS_IconOnly.png" alt="" class="wp-image-16385" srcset="https://blog.xojo.com/wp-content/uploads/2026/06/ToolbarMacOS_IconOnly.png 676w, https://blog.xojo.com/wp-content/uploads/2026/06/ToolbarMacOS_IconOnly-300x233.png 300w" sizes="auto, (max-width: 676px) 100vw, 676px" /></figure>
</div>



<div class="wp-block-column is-vertically-aligned-center is-layout-flow wp-block-column-is-layout-flow">
<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="530" height="378" src="https://blog.xojo.com/wp-content/uploads/2026/06/ToolbarLinux_IconOnly.png" alt="" class="wp-image-16386" srcset="https://blog.xojo.com/wp-content/uploads/2026/06/ToolbarLinux_IconOnly.png 530w, https://blog.xojo.com/wp-content/uploads/2026/06/ToolbarLinux_IconOnly-300x214.png 300w" sizes="auto, (max-width: 530px) 100vw, 530px" /></figure>
</div>



<div class="wp-block-column is-vertically-aligned-center is-layout-flow wp-block-column-is-layout-flow">
<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="445" height="258" src="https://blog.xojo.com/wp-content/uploads/2026/06/ToolbarWindows_IconOnly.png" alt="" class="wp-image-16387" srcset="https://blog.xojo.com/wp-content/uploads/2026/06/ToolbarWindows_IconOnly.png 445w, https://blog.xojo.com/wp-content/uploads/2026/06/ToolbarWindows_IconOnly-300x174.png 300w" sizes="auto, (max-width: 445px) 100vw, 445px" /></figure>
</div>
</div>



<h2 class="wp-block-heading">In Conclusion</h2>



<p>With support for symbols, additional layout styles, and WinUI support on Windows, we&#8217;re making it easier to create toolbars that look more modern, feel more native on each operating system, and adapt better to different user environments. Whether you prefer icon-only toolbars, text labels, or platform-specific symbols, the new options give you more ways to fine-tune the experience for your users without adding extra complexity to your projects.</p>



<p><em><em><em>William Yu grew up in Canada learning to program BASIC on a Vic-20. He is Xojo’s resident Windows and Linux engineer, among his many other skills. Some may say he has joined the dark side here in the USA, but he will always be a Canadian at heart.</em></em></em></p>



<ul class="wp-block-social-links has-normal-icon-size is-content-justification-center is-layout-flex wp-container-core-social-links-is-layout-16018d1d wp-block-social-links-is-layout-flex"><li class="wp-social-link wp-social-link-facebook  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.facebook.com/goxojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M12 2C6.5 2 2 6.5 2 12c0 5 3.7 9.1 8.4 9.9v-7H7.9V12h2.5V9.8c0-2.5 1.5-3.9 3.8-3.9 1.1 0 2.2.2 2.2.2v2.5h-1.3c-1.2 0-1.6.8-1.6 1.6V12h2.8l-.4 2.9h-2.3v7C18.3 21.1 22 17 22 12c0-5.5-4.5-10-10-10z"></path></svg><span class="wp-block-social-link-label screen-reader-text">Facebook</span></a></li>

<li class="wp-social-link wp-social-link-x  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://x.com/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M13.982 10.622 20.54 3h-1.554l-5.693 6.618L8.745 3H3.5l6.876 10.007L3.5 21h1.554l6.012-6.989L15.868 21h5.245l-7.131-10.378Zm-2.128 2.474-.697-.997-5.543-7.93H8l4.474 6.4.697.996 5.815 8.318h-2.387l-4.745-6.787Z" /></svg><span class="wp-block-social-link-label screen-reader-text">X</span></a></li>

<li class="wp-social-link wp-social-link-linkedin  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.linkedin.com/company/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M19.7,3H4.3C3.582,3,3,3.582,3,4.3v15.4C3,20.418,3.582,21,4.3,21h15.4c0.718,0,1.3-0.582,1.3-1.3V4.3 C21,3.582,20.418,3,19.7,3z M8.339,18.338H5.667v-8.59h2.672V18.338z M7.004,8.574c-0.857,0-1.549-0.694-1.549-1.548 c0-0.855,0.691-1.548,1.549-1.548c0.854,0,1.547,0.694,1.547,1.548C8.551,7.881,7.858,8.574,7.004,8.574z M18.339,18.338h-2.669 v-4.177c0-0.996-0.017-2.278-1.387-2.278c-1.389,0-1.601,1.086-1.601,2.206v4.249h-2.667v-8.59h2.559v1.174h0.037 c0.356-0.675,1.227-1.387,2.526-1.387c2.703,0,3.203,1.779,3.203,4.092V18.338z"></path></svg><span class="wp-block-social-link-label screen-reader-text">LinkedIn</span></a></li>

<li class="wp-social-link wp-social-link-github  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://github.com/topics/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M12,2C6.477,2,2,6.477,2,12c0,4.419,2.865,8.166,6.839,9.489c0.5,0.09,0.682-0.218,0.682-0.484 c0-0.236-0.009-0.866-0.014-1.699c-2.782,0.602-3.369-1.34-3.369-1.34c-0.455-1.157-1.11-1.465-1.11-1.465 c-0.909-0.62,0.069-0.608,0.069-0.608c1.004,0.071,1.532,1.03,1.532,1.03c0.891,1.529,2.341,1.089,2.91,0.833 c0.091-0.647,0.349-1.086,0.635-1.337c-2.22-0.251-4.555-1.111-4.555-4.943c0-1.091,0.39-1.984,1.03-2.682 C6.546,8.54,6.202,7.524,6.746,6.148c0,0,0.84-0.269,2.75,1.025C10.295,6.95,11.15,6.84,12,6.836 c0.85,0.004,1.705,0.114,2.504,0.336c1.909-1.294,2.748-1.025,2.748-1.025c0.546,1.376,0.202,2.394,0.1,2.646 c0.64,0.699,1.026,1.591,1.026,2.682c0,3.841-2.337,4.687-4.565,4.935c0.359,0.307,0.679,0.917,0.679,1.852 c0,1.335-0.012,2.415-0.012,2.741c0,0.269,0.18,0.579,0.688,0.481C19.138,20.161,22,16.416,22,12C22,6.477,17.523,2,12,2z"></path></svg><span class="wp-block-social-link-label screen-reader-text">GitHub</span></a></li>

<li class="wp-social-link wp-social-link-youtube  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.youtube.com/c/XojoInc" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M21.8,8.001c0,0-0.195-1.378-0.795-1.985c-0.76-0.797-1.613-0.801-2.004-0.847c-2.799-0.202-6.997-0.202-6.997-0.202 h-0.009c0,0-4.198,0-6.997,0.202C4.608,5.216,3.756,5.22,2.995,6.016C2.395,6.623,2.2,8.001,2.2,8.001S2,9.62,2,11.238v1.517 c0,1.618,0.2,3.237,0.2,3.237s0.195,1.378,0.795,1.985c0.761,0.797,1.76,0.771,2.205,0.855c1.6,0.153,6.8,0.201,6.8,0.201 s4.203-0.006,7.001-0.209c0.391-0.047,1.243-0.051,2.004-0.847c0.6-0.607,0.795-1.985,0.795-1.985s0.2-1.618,0.2-3.237v-1.517 C22,9.62,21.8,8.001,21.8,8.001z M9.935,14.594l-0.001-5.62l5.404,2.82L9.935,14.594z"></path></svg><span class="wp-block-social-link-label screen-reader-text">YouTube</span></a></li></ul>



<p class="has-text-align-center has-text-color has-link-color wp-elements-a0a2ac26ad214a49dac577734d259176" style="color:#84bd00"><a href="https://xojo.com/download/" target="_blank" rel="noreferrer noopener">Download Xojo</a></p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Custom Control Rendering with DrawControlInLayoutEditor</title>
		<link>https://blog.xojo.com/2026/03/31/custom-control-rendering-with-drawcontrolinlayouteditor/</link>
		
		<dc:creator><![CDATA[William Yu]]></dc:creator>
		<pubDate>Tue, 31 Mar 2026 15:22:00 +0000</pubDate>
				<category><![CDATA[Android]]></category>
		<category><![CDATA[Desktop]]></category>
		<category><![CDATA[General]]></category>
		<category><![CDATA[iOS]]></category>
		<category><![CDATA[Learning]]></category>
		<category><![CDATA[Tips]]></category>
		<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[2026r1]]></category>
		<category><![CDATA[DrawControlInLayoutEditor]]></category>
		<category><![CDATA[IDE]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=16045</guid>

					<description><![CDATA[One of the notable additions in Xojo 2026 Release 1 is that the&#160;DrawControlInLayoutEditor&#160;event is now available for Desktop and iOS/Android projects, giving you more possibilities&#8230;]]></description>
										<content:encoded><![CDATA[
<p>One of the notable additions in Xojo 2026 Release 1 is that the&nbsp;<code>DrawControlInLayoutEditor</code>&nbsp;event is now available for Desktop and iOS/Android projects, giving you more possibilities over how your controls appear in the layout editor.</p>



<p>With this feature you can provide custom drawing for a control at design time, making it easier to visualize your UI without running the project.</p>



<p>If this sounds familiar, it&#8217;s because it brings Desktop and iOS/Android projects closer to what&#8217;s already possible in Web projects with&nbsp;<code>WebSDKUIControl</code>, where custom layout rendering has been available for some time.</p>



<h4 class="wp-block-heading">Why this matters</h4>



<p>Previously your custom Canvas controls would appear as generic placeholders, making it difficult to understand how they would look at runtime. Now you can:</p>



<ul class="wp-block-list">
<li>Render a preview of your control directly in the layout editor</li>



<li>Display dynamic or state-based visuals</li>



<li>Make custom controls much easier to work with at design time</li>
</ul>



<h4 class="wp-block-heading">How it works</h4>



<p>For Desktop projects, you can subclass&nbsp;<code>DesktopUIControl</code>&nbsp;and implement the&nbsp;<code>DrawControlInLayoutEditor</code>&nbsp;event. Your drawing code is executed by the IDE as it renders the control in the layout. For iOS and Android projects, this event is available on&nbsp;<code>MobileUIControl</code>.</p>



<p><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f449.png" alt="👉" class="wp-smiley" style="height: 1em; max-height: 1em;" /> You can also use this event directly with&nbsp;<code>DesktopCanvas</code>&nbsp;and&nbsp;<code>MobileCanvas</code>&nbsp;controls, so you can start drawing in&nbsp;<code>DrawControlInLayoutEditor</code>&nbsp;without needing to subclass anything.</p>



<p>This event gives you the flexibility to draw whatever you need—shapes, text, or even simplified representations of runtime content. For example, a custom media player control could display a play button and timeline, or a chart control could render a sample graph.</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="661" src="https://blog.xojo.com/wp-content/uploads/2026/03/Screenshot-2026-03-24-at-3.03.15-PM-1024x661.png" alt="" class="wp-image-16049" srcset="https://blog.xojo.com/wp-content/uploads/2026/03/Screenshot-2026-03-24-at-3.03.15-PM-1024x661.png 1024w, https://blog.xojo.com/wp-content/uploads/2026/03/Screenshot-2026-03-24-at-3.03.15-PM-300x194.png 300w, https://blog.xojo.com/wp-content/uploads/2026/03/Screenshot-2026-03-24-at-3.03.15-PM-768x496.png 768w, https://blog.xojo.com/wp-content/uploads/2026/03/Screenshot-2026-03-24-at-3.03.15-PM-1536x991.png 1536w, https://blog.xojo.com/wp-content/uploads/2026/03/Screenshot-2026-03-24-at-3.03.15-PM-2048x1322.png 2048w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<h4 class="wp-block-heading">A note about XojoScript limitations</h4>



<p>One important detail to keep in mind is that&nbsp;<code>DrawControlInLayoutEditor</code>&nbsp;runs using XojoScript. This allows the IDE to safely execute your drawing code at design time, but it also means not everything you&#8217;d typically expect to use in Xojo is available, especially when it comes to the graphics APIs.</p>



<p>In practice, most common drawing operations—such as shapes, lines, and text—work as expected. However, in some cases these graphics calls use a slightly different API, as is the case with <code>LinearGradientBrush</code>.</p>



<p><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f449.png" alt="👉" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Also, because this runs as XojoScript, you cannot call other methods from within your <code>DrawControlInLayoutEditor</code>code. To access your control&#8217;s properties, you&#8217;ll need to use the built-in  <code>ColorProperty</code>, <code>BooleanProperty</code>, <code>IntegerProperty</code>, <code>DoubleProperty</code>, and <code>StringProperty</code> methods.</p>



<h4 class="wp-block-heading">Support for more Graphics</h4>



<p>In 2026r1, we&#8217;ve expanded the graphics capabilities available to&nbsp;<code>DrawControlInLayoutEditor</code>, building on what was previously supported for&nbsp;<code>WebSDKUIControl</code>. New additions include support for:</p>



<ul class="wp-block-list">
<li>LinearGradientBrush, PictureBrush, and ShadowBrush</li>



<li>LineDash, LineDashOffset, LineCap, LineJoin, and MiterLimit</li>



<li>Outline</li>



<li>Scale, Rotate, and Translate</li>



<li>SaveState, RestoreState</li>



<li>Color constants (Red, Green, Blue, Yellow etc.)</li>
</ul>



<p>Since XojoScript does not support the&nbsp;<code>Pair</code>&nbsp;type, the&nbsp;<code>LinearGradientBrush</code>&nbsp;API was adapted slightly:</p>



<pre class="wp-block-code"><code>Class LinearGradientBrush

  Sub Constructor()

  Sub AddStop(stop As Double, c As Color)

  Property StartPoint As Point
  Property EndPoint As Point

End Class</code></pre>



<p>The main difference is how the brush is constructed and how stops are added, without needing&nbsp;<code>Pair</code>. With this new API, you can turn a basic graph into something much more visually appealing.</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="661" src="https://blog.xojo.com/wp-content/uploads/2026/03/Screenshot-2026-03-25-at-3.00.07-PM-1024x661.png" alt="" class="wp-image-16075" srcset="https://blog.xojo.com/wp-content/uploads/2026/03/Screenshot-2026-03-25-at-3.00.07-PM-1024x661.png 1024w, https://blog.xojo.com/wp-content/uploads/2026/03/Screenshot-2026-03-25-at-3.00.07-PM-300x194.png 300w, https://blog.xojo.com/wp-content/uploads/2026/03/Screenshot-2026-03-25-at-3.00.07-PM-768x496.png 768w, https://blog.xojo.com/wp-content/uploads/2026/03/Screenshot-2026-03-25-at-3.00.07-PM-1536x991.png 1536w, https://blog.xojo.com/wp-content/uploads/2026/03/Screenshot-2026-03-25-at-3.00.07-PM-2048x1322.png 2048w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<h4 class="wp-block-heading">Turning off this feature</h4>



<p>While many may prefer custom rendering for custom controls, it can become a bottleneck when a large number of controls are rendering content. If you prefer a less resource-intensive experience, you can disable this behavior in Settings → Layout by enabling the Static Rendering option.</p>



<h4 class="wp-block-heading">Finally</h4>



<p>With&nbsp;<code>DrawControlInLayoutEditor</code>&nbsp;now available for Desktop and Mobile projects, you can take advantage of the same benefits Web projects have enjoyed for years. Be sure to check out the new DrawControlInLayoutEditor example project, adapted from the WebSDK → CustomButton example. We hope you enjoy designing and previewing your custom controls with this new event—and yes, it also works in Libraries!</p>



<p><em><em><em>William Yu grew up in Canada learning to program BASIC on a Vic-20. He is Xojo’s resident Windows and Linux engineer, among his many other skills. Some may say he has joined the dark side here in the USA, but he will always be a Canadian at heart.</em></em></em></p>



<ul class="wp-block-social-links has-normal-icon-size is-content-justification-center is-layout-flex wp-container-core-social-links-is-layout-16018d1d wp-block-social-links-is-layout-flex"><li class="wp-social-link wp-social-link-facebook  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.facebook.com/goxojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M12 2C6.5 2 2 6.5 2 12c0 5 3.7 9.1 8.4 9.9v-7H7.9V12h2.5V9.8c0-2.5 1.5-3.9 3.8-3.9 1.1 0 2.2.2 2.2.2v2.5h-1.3c-1.2 0-1.6.8-1.6 1.6V12h2.8l-.4 2.9h-2.3v7C18.3 21.1 22 17 22 12c0-5.5-4.5-10-10-10z"></path></svg><span class="wp-block-social-link-label screen-reader-text">Facebook</span></a></li>

<li class="wp-social-link wp-social-link-x  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://x.com/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M13.982 10.622 20.54 3h-1.554l-5.693 6.618L8.745 3H3.5l6.876 10.007L3.5 21h1.554l6.012-6.989L15.868 21h5.245l-7.131-10.378Zm-2.128 2.474-.697-.997-5.543-7.93H8l4.474 6.4.697.996 5.815 8.318h-2.387l-4.745-6.787Z" /></svg><span class="wp-block-social-link-label screen-reader-text">X</span></a></li>

<li class="wp-social-link wp-social-link-linkedin  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.linkedin.com/company/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M19.7,3H4.3C3.582,3,3,3.582,3,4.3v15.4C3,20.418,3.582,21,4.3,21h15.4c0.718,0,1.3-0.582,1.3-1.3V4.3 C21,3.582,20.418,3,19.7,3z M8.339,18.338H5.667v-8.59h2.672V18.338z M7.004,8.574c-0.857,0-1.549-0.694-1.549-1.548 c0-0.855,0.691-1.548,1.549-1.548c0.854,0,1.547,0.694,1.547,1.548C8.551,7.881,7.858,8.574,7.004,8.574z M18.339,18.338h-2.669 v-4.177c0-0.996-0.017-2.278-1.387-2.278c-1.389,0-1.601,1.086-1.601,2.206v4.249h-2.667v-8.59h2.559v1.174h0.037 c0.356-0.675,1.227-1.387,2.526-1.387c2.703,0,3.203,1.779,3.203,4.092V18.338z"></path></svg><span class="wp-block-social-link-label screen-reader-text">LinkedIn</span></a></li>

<li class="wp-social-link wp-social-link-github  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://github.com/topics/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M12,2C6.477,2,2,6.477,2,12c0,4.419,2.865,8.166,6.839,9.489c0.5,0.09,0.682-0.218,0.682-0.484 c0-0.236-0.009-0.866-0.014-1.699c-2.782,0.602-3.369-1.34-3.369-1.34c-0.455-1.157-1.11-1.465-1.11-1.465 c-0.909-0.62,0.069-0.608,0.069-0.608c1.004,0.071,1.532,1.03,1.532,1.03c0.891,1.529,2.341,1.089,2.91,0.833 c0.091-0.647,0.349-1.086,0.635-1.337c-2.22-0.251-4.555-1.111-4.555-4.943c0-1.091,0.39-1.984,1.03-2.682 C6.546,8.54,6.202,7.524,6.746,6.148c0,0,0.84-0.269,2.75,1.025C10.295,6.95,11.15,6.84,12,6.836 c0.85,0.004,1.705,0.114,2.504,0.336c1.909-1.294,2.748-1.025,2.748-1.025c0.546,1.376,0.202,2.394,0.1,2.646 c0.64,0.699,1.026,1.591,1.026,2.682c0,3.841-2.337,4.687-4.565,4.935c0.359,0.307,0.679,0.917,0.679,1.852 c0,1.335-0.012,2.415-0.012,2.741c0,0.269,0.18,0.579,0.688,0.481C19.138,20.161,22,16.416,22,12C22,6.477,17.523,2,12,2z"></path></svg><span class="wp-block-social-link-label screen-reader-text">GitHub</span></a></li>

<li class="wp-social-link wp-social-link-youtube  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.youtube.com/c/XojoInc" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M21.8,8.001c0,0-0.195-1.378-0.795-1.985c-0.76-0.797-1.613-0.801-2.004-0.847c-2.799-0.202-6.997-0.202-6.997-0.202 h-0.009c0,0-4.198,0-6.997,0.202C4.608,5.216,3.756,5.22,2.995,6.016C2.395,6.623,2.2,8.001,2.2,8.001S2,9.62,2,11.238v1.517 c0,1.618,0.2,3.237,0.2,3.237s0.195,1.378,0.795,1.985c0.761,0.797,1.76,0.771,2.205,0.855c1.6,0.153,6.8,0.201,6.8,0.201 s4.203-0.006,7.001-0.209c0.391-0.047,1.243-0.051,2.004-0.847c0.6-0.607,0.795-1.985,0.795-1.985s0.2-1.618,0.2-3.237v-1.517 C22,9.62,21.8,8.001,21.8,8.001z M9.935,14.594l-0.001-5.62l5.404,2.82L9.935,14.594z"></path></svg><span class="wp-block-social-link-label screen-reader-text">YouTube</span></a></li></ul>



<p class="has-text-align-center has-text-color has-link-color wp-elements-a0a2ac26ad214a49dac577734d259176" style="color:#84bd00"><a href="https://xojo.com/download/" target="_blank" rel="noreferrer noopener">Download Xojo</a></p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Watchpoints in Xojo: A Smarter Way to Track Your Data</title>
		<link>https://blog.xojo.com/2026/03/31/watchpoints-in-xojo-a-smarter-way-to-track-your-data/</link>
		
		<dc:creator><![CDATA[William Yu]]></dc:creator>
		<pubDate>Tue, 31 Mar 2026 13:22:00 +0000</pubDate>
				<category><![CDATA[Cross-Platform]]></category>
		<category><![CDATA[General]]></category>
		<category><![CDATA[Learning]]></category>
		<category><![CDATA[Tips]]></category>
		<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[2026r1]]></category>
		<category><![CDATA[Debugging]]></category>
		<category><![CDATA[Debugging Tools]]></category>
		<category><![CDATA[Remote Debugging]]></category>
		<category><![CDATA[Watchpoints]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=15987</guid>

					<description><![CDATA[Debugging isn’t just about stepping through code anymore, it&#8217;s about understanding how your data behaves over time. With the new watchpoints feature in Xojo, you can&#8230;]]></description>
										<content:encoded><![CDATA[
<p>Debugging isn’t just about stepping through code anymore, it&#8217;s about understanding how your data behaves over time. With the new watchpoints feature in Xojo, you can now monitor variables and object properties more intelligently, without constantly stepping line by line or adding logging just to see when values change.</p>



<h3 class="wp-block-heading">What Are Watchpoints?</h3>



<p>Watchpoints let you pause execution when the value of a variable or property changes. Instead of asking <em>“how did I get here?”</em>, watchpoints help you answer <em>“when did this change?”</em></p>



<p>This is especially useful when:</p>



<ul class="wp-block-list">
<li>A value is being modified unexpectedly</li>



<li>Multiple parts of your code interact with the same object</li>



<li>You’re tracking down subtle state-related bugs</li>
</ul>



<h3 class="wp-block-heading">How Watchpoints Work</h3>



<p>Setting up a watchpoint requires pausing execution where you would like to start monitoring the variable or property of an object.</p>



<figure class="wp-block-image size-large is-style-default"><img loading="lazy" decoding="async" width="1024" height="677" src="https://blog.xojo.com/wp-content/uploads/2026/03/WatchpointSetupClipped-1024x677.jpg" alt="" class="wp-image-16018" srcset="https://blog.xojo.com/wp-content/uploads/2026/03/WatchpointSetupClipped-1024x677.jpg 1024w, https://blog.xojo.com/wp-content/uploads/2026/03/WatchpointSetupClipped-300x198.jpg 300w, https://blog.xojo.com/wp-content/uploads/2026/03/WatchpointSetupClipped-768x508.jpg 768w, https://blog.xojo.com/wp-content/uploads/2026/03/WatchpointSetupClipped.jpg 1446w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<p>In this example, we want to monitor the <code>count</code> variable, so you can right-click it in the variables debugger list and select <strong>Watch</strong> from the context menu.  Once a watchpoint is set on a variable or property, the debugger keeps track of its value during execution. When the value changes, execution pauses and shows the line that triggered the change. Notice that the watchpoint break line is highlighted differently from the current execution line, and a Watchpoints list is now displayed.</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="667" src="https://blog.xojo.com/wp-content/uploads/2026/03/WatchpointBreak-1024x667.png" alt="" class="wp-image-16014" srcset="https://blog.xojo.com/wp-content/uploads/2026/03/WatchpointBreak-1024x667.png 1024w, https://blog.xojo.com/wp-content/uploads/2026/03/WatchpointBreak-300x195.png 300w, https://blog.xojo.com/wp-content/uploads/2026/03/WatchpointBreak-768x500.png 768w, https://blog.xojo.com/wp-content/uploads/2026/03/WatchpointBreak-1536x1000.png 1536w, https://blog.xojo.com/wp-content/uploads/2026/03/WatchpointBreak-2048x1333.png 2048w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<p>This gives you immediate visibility into:</p>



<ul class="wp-block-list">
<li>What code caused the modification</li>



<li>What the previous and new values are</li>



<li>What the surrounding state looks like</li>
</ul>



<h3 class="wp-block-heading">Why This Matters</h3>



<p>Traditionally, tracking down a value change required manually stepping through code or adding temporary logging. Both approaches are time-consuming and error-prone.</p>



<p>Watchpoints eliminate that friction by:</p>



<ul class="wp-block-list">
<li>Reducing the need for repetitive stepping</li>



<li>Highlighting only meaningful changes</li>



<li>Letting you focus on the root cause faster</li>
</ul>



<h3 class="wp-block-heading">Conditional Watchpoints</h3>



<p>Watchpoints in Xojo aren&#8217;t limited to triggering on every change—you can make them conditional. For example, you can break only when a value is equal to, greater than, or less than a specific threshold, or even when it falls within a defined range. For string, both case-sensitive and case-insensitive comparisons are supported. This makes it much easier to focus on the changes that actually matter, especially when a variable updates frequently but only becomes problematic under certain conditions.</p>



<p>To add a condition to a watchpoint, right-click the watched variable or property and choose&nbsp;<strong>Edit Watchpoint Expression</strong> from the context menu.</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="695" src="https://blog.xojo.com/wp-content/uploads/2026/03/WatchpointExpression-1024x695.png" alt="" class="wp-image-16020" srcset="https://blog.xojo.com/wp-content/uploads/2026/03/WatchpointExpression-1024x695.png 1024w, https://blog.xojo.com/wp-content/uploads/2026/03/WatchpointExpression-300x204.png 300w, https://blog.xojo.com/wp-content/uploads/2026/03/WatchpointExpression-768x522.png 768w, https://blog.xojo.com/wp-content/uploads/2026/03/WatchpointExpression.png 1496w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<p>The expression editor adapts based on the type of variable or property you&#8217;re watching, providing hints about what values and conditions you can enter.</p>



<h3 class="wp-block-heading">Handling Object Lifetimes</h3>



<p>One important detail when working with watchpoints is object lifetime.</p>



<p>If a watchpoint is attached to a property of an object that goes out of scope or is destroyed, the debugger can no longer track it. In these cases, Xojo provides feedback through the Messages pane so you know the watchpoint is no longer valid, along with the last known value.</p>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="890" height="180" src="https://blog.xojo.com/wp-content/uploads/2026/03/Screenshot-2026-03-24-at-9.33.52-AM.png" alt="" class="wp-image-16021" srcset="https://blog.xojo.com/wp-content/uploads/2026/03/Screenshot-2026-03-24-at-9.33.52-AM.png 890w, https://blog.xojo.com/wp-content/uploads/2026/03/Screenshot-2026-03-24-at-9.33.52-AM-300x61.png 300w, https://blog.xojo.com/wp-content/uploads/2026/03/Screenshot-2026-03-24-at-9.33.52-AM-768x155.png 768w" sizes="auto, (max-width: 890px) 100vw, 890px" /></figure>



<h3 class="wp-block-heading">What works and what doesn&#8217;t</h3>



<p>You can set watchpoints on most variables and properties, even variants; however, Arrays, Structures, and computed properties are not supported. Code within <code>#pragma DisableBackgroundTasks</code> or <code>#pragma Debug False</code> blocks will not trigger watchpoint breaks. Watchpoints are also not currently available for Android projects.</p>



<h3 class="wp-block-heading">Final Thoughts</h3>



<p>Watchpoints bring a new level of precision to debugging in Xojo. Instead of chasing bugs through code, you can now let the debugger do the work of tracking down exactly where things go wrong.</p>



<p>Give them a try in your next debugging session—you might find yourself solving problems faster than ever!</p>



<p><em><em><em>William Yu grew up in Canada learning to program BASIC on a Vic-20. He is Xojo’s resident Windows and Linux engineer, among his many other skills. Some may say he has joined the dark side here in the USA, but he will always be a Canadian at heart.</em></em></em></p>



<ul class="wp-block-social-links has-normal-icon-size is-content-justification-center is-layout-flex wp-container-core-social-links-is-layout-16018d1d wp-block-social-links-is-layout-flex"><li class="wp-social-link wp-social-link-facebook  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.facebook.com/goxojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M12 2C6.5 2 2 6.5 2 12c0 5 3.7 9.1 8.4 9.9v-7H7.9V12h2.5V9.8c0-2.5 1.5-3.9 3.8-3.9 1.1 0 2.2.2 2.2.2v2.5h-1.3c-1.2 0-1.6.8-1.6 1.6V12h2.8l-.4 2.9h-2.3v7C18.3 21.1 22 17 22 12c0-5.5-4.5-10-10-10z"></path></svg><span class="wp-block-social-link-label screen-reader-text">Facebook</span></a></li>

<li class="wp-social-link wp-social-link-x  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://x.com/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M13.982 10.622 20.54 3h-1.554l-5.693 6.618L8.745 3H3.5l6.876 10.007L3.5 21h1.554l6.012-6.989L15.868 21h5.245l-7.131-10.378Zm-2.128 2.474-.697-.997-5.543-7.93H8l4.474 6.4.697.996 5.815 8.318h-2.387l-4.745-6.787Z" /></svg><span class="wp-block-social-link-label screen-reader-text">X</span></a></li>

<li class="wp-social-link wp-social-link-linkedin  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.linkedin.com/company/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M19.7,3H4.3C3.582,3,3,3.582,3,4.3v15.4C3,20.418,3.582,21,4.3,21h15.4c0.718,0,1.3-0.582,1.3-1.3V4.3 C21,3.582,20.418,3,19.7,3z M8.339,18.338H5.667v-8.59h2.672V18.338z M7.004,8.574c-0.857,0-1.549-0.694-1.549-1.548 c0-0.855,0.691-1.548,1.549-1.548c0.854,0,1.547,0.694,1.547,1.548C8.551,7.881,7.858,8.574,7.004,8.574z M18.339,18.338h-2.669 v-4.177c0-0.996-0.017-2.278-1.387-2.278c-1.389,0-1.601,1.086-1.601,2.206v4.249h-2.667v-8.59h2.559v1.174h0.037 c0.356-0.675,1.227-1.387,2.526-1.387c2.703,0,3.203,1.779,3.203,4.092V18.338z"></path></svg><span class="wp-block-social-link-label screen-reader-text">LinkedIn</span></a></li>

<li class="wp-social-link wp-social-link-github  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://github.com/topics/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M12,2C6.477,2,2,6.477,2,12c0,4.419,2.865,8.166,6.839,9.489c0.5,0.09,0.682-0.218,0.682-0.484 c0-0.236-0.009-0.866-0.014-1.699c-2.782,0.602-3.369-1.34-3.369-1.34c-0.455-1.157-1.11-1.465-1.11-1.465 c-0.909-0.62,0.069-0.608,0.069-0.608c1.004,0.071,1.532,1.03,1.532,1.03c0.891,1.529,2.341,1.089,2.91,0.833 c0.091-0.647,0.349-1.086,0.635-1.337c-2.22-0.251-4.555-1.111-4.555-4.943c0-1.091,0.39-1.984,1.03-2.682 C6.546,8.54,6.202,7.524,6.746,6.148c0,0,0.84-0.269,2.75,1.025C10.295,6.95,11.15,6.84,12,6.836 c0.85,0.004,1.705,0.114,2.504,0.336c1.909-1.294,2.748-1.025,2.748-1.025c0.546,1.376,0.202,2.394,0.1,2.646 c0.64,0.699,1.026,1.591,1.026,2.682c0,3.841-2.337,4.687-4.565,4.935c0.359,0.307,0.679,0.917,0.679,1.852 c0,1.335-0.012,2.415-0.012,2.741c0,0.269,0.18,0.579,0.688,0.481C19.138,20.161,22,16.416,22,12C22,6.477,17.523,2,12,2z"></path></svg><span class="wp-block-social-link-label screen-reader-text">GitHub</span></a></li>

<li class="wp-social-link wp-social-link-youtube  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.youtube.com/c/XojoInc" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M21.8,8.001c0,0-0.195-1.378-0.795-1.985c-0.76-0.797-1.613-0.801-2.004-0.847c-2.799-0.202-6.997-0.202-6.997-0.202 h-0.009c0,0-4.198,0-6.997,0.202C4.608,5.216,3.756,5.22,2.995,6.016C2.395,6.623,2.2,8.001,2.2,8.001S2,9.62,2,11.238v1.517 c0,1.618,0.2,3.237,0.2,3.237s0.195,1.378,0.795,1.985c0.761,0.797,1.76,0.771,2.205,0.855c1.6,0.153,6.8,0.201,6.8,0.201 s4.203-0.006,7.001-0.209c0.391-0.047,1.243-0.051,2.004-0.847c0.6-0.607,0.795-1.985,0.795-1.985s0.2-1.618,0.2-3.237v-1.517 C22,9.62,21.8,8.001,21.8,8.001z M9.935,14.594l-0.001-5.62l5.404,2.82L9.935,14.594z"></path></svg><span class="wp-block-social-link-label screen-reader-text">YouTube</span></a></li></ul>



<p class="has-text-align-center has-text-color has-link-color wp-elements-a0a2ac26ad214a49dac577734d259176" style="color:#84bd00"><a href="https://xojo.com/download/" target="_blank" rel="noreferrer noopener">Download Xojo</a></p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Now Available: Xojo 2026r1</title>
		<link>https://blog.xojo.com/2026/03/31/now-available-xojo-2026r1/</link>
		
		<dc:creator><![CDATA[Xojo]]></dc:creator>
		<pubDate>Tue, 31 Mar 2026 13:20:00 +0000</pubDate>
				<category><![CDATA[General]]></category>
		<category><![CDATA[2026r1]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=16083</guid>

					<description><![CDATA[Xojo 2026r1 is officially out today. It’s our first major update of the year and this post serves as the map for everything new. We’ve&#8230;]]></description>
										<content:encoded><![CDATA[
<p>Xojo 2026r1 is officially out today. It’s our first major update of the year and this post serves as the map for everything new. We’ve packed in over 50 new features and closed out 120+ bugs.</p>



<hr class="wp-block-separator has-alpha-channel-opacity is-style-dots"/>



<div class="wp-block-columns is-layout-flex wp-container-core-columns-is-layout-9d6595d7 wp-block-columns-is-layout-flex">
<div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow">
<h2 class="wp-block-heading">The Debugger gets &#8220;Watchpoints&#8221;</h2>



<p>The biggest workflow change in 2026r1 is the addition of&nbsp;<strong>Watchpoints</strong>. Now, you can tell the debugger to break whenever a specific variable changes or meets a condition you define. It’s a massive time-saver for state-related debugging. <a href="https://blog.xojo.com/2026/03/31/watchpoints-in-xojo-a-smarter-way-to-track-your-data/" target="_blank" rel="noreferrer noopener">Read more: Watchpoints in Xojo – A Smarter Way to Track Your Data</a></p>
</div>



<div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow">
<h2 class="wp-block-heading">Android: Charts and PDFs</h2>



<p>We are continuing to close the gap between Android and our other targets. This release adds the&nbsp;<code>MobileChart</code>&nbsp;control and the&nbsp;<code>MobilePDFViewer</code>&nbsp;to the Android framework. If you’ve been waiting to bring data visualization or document handling to your Android apps, these are ready for prime time. <a href="https://blog.xojo.com/2026/03/31/more-new-features-for-android/" target="_blank" rel="noreferrer noopener">Read more: More New Features for Android</a></p>
</div>
</div>



<div class="wp-block-columns is-layout-flex wp-container-core-columns-is-layout-9d6595d7 wp-block-columns-is-layout-flex">
<div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow">
<h2 class="wp-block-heading">Simplified macOS Signing</h2>



<p>Code signing is rarely fun, so we’ve overhauled how the IDE handles it on macOS. This update introduces Team-Based signing, which does a much better job of detecting your Apple Developer certificates and automating provisioning profiles. It makes the jump to Sandboxing or the App Store a lot less painful. <a href="https://blog.xojo.com/2026/03/31/team-based-signing-arrives-to-macos/" target="_blank" rel="noreferrer noopener">Read more: Team-Based Signing Arrives to macOS</a></p>
</div>



<div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow">
<h2 class="wp-block-heading">Live UI Previews in the IDE</h2>



<p>No more &#8220;placeholder&#8221; boxes for your custom controls. With the new&nbsp;<code>DrawControlInLayoutEditor</code>&nbsp;event, your Desktop and Mobile subclasses can now render their actual UI directly inside the Xojo Layout Editor. It means what you see while designing is much closer to what you see at runtime. <a href="https://blog.xojo.com/2026/03/31/custom-control-rendering-with-drawcontrolinlayouteditor/" target="_blank" rel="noreferrer noopener">Read more: Custom Control Rendering with DrawControlInLayoutEditor</a></p>
</div>
</div>



<div class="wp-block-columns is-layout-flex wp-container-core-columns-is-layout-9d6595d7 wp-block-columns-is-layout-flex">
<div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow">
<h2 class="wp-block-heading">Web and Mobile UI Tweaks</h2>



<p>We’ve added several long-requested UI tools to make your apps more interactive:</p>



<ul class="wp-block-list">
<li><strong>WebSwitch:</strong>&nbsp;A native toggle control for Xojo Web apps.</li>



<li><strong>Barcode Scanning:</strong>&nbsp;Official support for scanning barcodes directly within Web projects.</li>



<li><strong>Native Color Pickers:</strong>&nbsp;We’ve added a&nbsp;<code>WebColorPicker</code>&nbsp;and a&nbsp;<code>MobileColorPicker</code>&nbsp;(for Android) to match the existing desktop and iOS functionality.<br><a href="https://blog.xojo.com/2026/03/31/scan-barcodes-pick-colors-toggle-xojo-web-in-2026r1/" target="_blank" rel="noreferrer noopener">Read more: Scan Barcodes, Pick Colors, and the New WebSwitch</a></li>
</ul>
</div>



<div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow">
<h2 class="wp-block-heading">AI Assistance: Jade Upgraded</h2>



<p><strong>Jade</strong>, Xojo&#8217;s built-in AI assistant, got a significant improvement in this release. It now defaults to&nbsp;<strong>Claude 4.6</strong>, providing much more accurate and context-aware code suggestions. We’ve also added conversation &#8220;compaction,&#8221; which helps the assistant remember long threads without hitting token limits or slowing down.<br><a href="https://blog.xojo.com/2026/03/31/jade-improvements/" target="_blank" rel="noreferrer noopener">Read more: Jade Improvements in 2026r1</a></p>
</div>
</div>



<hr class="wp-block-separator has-alpha-channel-opacity is-style-dots"/>



<h2 class="wp-block-heading">Stability and Modernization</h2>



<p>Under the hood, we’ve updated the Web framework to use Bootstrap v5.3.8 and set the TypeScript target to ES2020. Windows users will notice better WinUI support for&nbsp;<code>DesktopTabPanel</code>&nbsp;and&nbsp;<code>DesktopGroupBox</code>, along with fixes for Dark Mode consistency.</p>



<p>You can find the exhaustive list of every change in the&nbsp;<a href="https://documentation.xojo.com/versions/2026r1/resources/release_notes/2026r1.html" target="_blank" rel="noreferrer noopener">Xojo 2026r1 Release Notes</a>.</p>



<p>Xojo 2026r1 is a free update for everyone.<br><strong><a href="https://www.xojo.com/download" target="_blank" rel="noreferrer noopener">Download Xojo 2026r1 now.</a></strong></p>



<ul class="wp-block-social-links has-normal-icon-size is-content-justification-center is-layout-flex wp-container-core-social-links-is-layout-16018d1d wp-block-social-links-is-layout-flex"><li class="wp-social-link wp-social-link-facebook  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.facebook.com/goxojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M12 2C6.5 2 2 6.5 2 12c0 5 3.7 9.1 8.4 9.9v-7H7.9V12h2.5V9.8c0-2.5 1.5-3.9 3.8-3.9 1.1 0 2.2.2 2.2.2v2.5h-1.3c-1.2 0-1.6.8-1.6 1.6V12h2.8l-.4 2.9h-2.3v7C18.3 21.1 22 17 22 12c0-5.5-4.5-10-10-10z"></path></svg><span class="wp-block-social-link-label screen-reader-text">Facebook</span></a></li>

<li class="wp-social-link wp-social-link-x  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://x.com/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M13.982 10.622 20.54 3h-1.554l-5.693 6.618L8.745 3H3.5l6.876 10.007L3.5 21h1.554l6.012-6.989L15.868 21h5.245l-7.131-10.378Zm-2.128 2.474-.697-.997-5.543-7.93H8l4.474 6.4.697.996 5.815 8.318h-2.387l-4.745-6.787Z" /></svg><span class="wp-block-social-link-label screen-reader-text">X</span></a></li>

<li class="wp-social-link wp-social-link-linkedin  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.linkedin.com/company/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M19.7,3H4.3C3.582,3,3,3.582,3,4.3v15.4C3,20.418,3.582,21,4.3,21h15.4c0.718,0,1.3-0.582,1.3-1.3V4.3 C21,3.582,20.418,3,19.7,3z M8.339,18.338H5.667v-8.59h2.672V18.338z M7.004,8.574c-0.857,0-1.549-0.694-1.549-1.548 c0-0.855,0.691-1.548,1.549-1.548c0.854,0,1.547,0.694,1.547,1.548C8.551,7.881,7.858,8.574,7.004,8.574z M18.339,18.338h-2.669 v-4.177c0-0.996-0.017-2.278-1.387-2.278c-1.389,0-1.601,1.086-1.601,2.206v4.249h-2.667v-8.59h2.559v1.174h0.037 c0.356-0.675,1.227-1.387,2.526-1.387c2.703,0,3.203,1.779,3.203,4.092V18.338z"></path></svg><span class="wp-block-social-link-label screen-reader-text">LinkedIn</span></a></li>

<li class="wp-social-link wp-social-link-github  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://github.com/topics/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M12,2C6.477,2,2,6.477,2,12c0,4.419,2.865,8.166,6.839,9.489c0.5,0.09,0.682-0.218,0.682-0.484 c0-0.236-0.009-0.866-0.014-1.699c-2.782,0.602-3.369-1.34-3.369-1.34c-0.455-1.157-1.11-1.465-1.11-1.465 c-0.909-0.62,0.069-0.608,0.069-0.608c1.004,0.071,1.532,1.03,1.532,1.03c0.891,1.529,2.341,1.089,2.91,0.833 c0.091-0.647,0.349-1.086,0.635-1.337c-2.22-0.251-4.555-1.111-4.555-4.943c0-1.091,0.39-1.984,1.03-2.682 C6.546,8.54,6.202,7.524,6.746,6.148c0,0,0.84-0.269,2.75,1.025C10.295,6.95,11.15,6.84,12,6.836 c0.85,0.004,1.705,0.114,2.504,0.336c1.909-1.294,2.748-1.025,2.748-1.025c0.546,1.376,0.202,2.394,0.1,2.646 c0.64,0.699,1.026,1.591,1.026,2.682c0,3.841-2.337,4.687-4.565,4.935c0.359,0.307,0.679,0.917,0.679,1.852 c0,1.335-0.012,2.415-0.012,2.741c0,0.269,0.18,0.579,0.688,0.481C19.138,20.161,22,16.416,22,12C22,6.477,17.523,2,12,2z"></path></svg><span class="wp-block-social-link-label screen-reader-text">GitHub</span></a></li>

<li class="wp-social-link wp-social-link-youtube  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.youtube.com/c/XojoInc" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M21.8,8.001c0,0-0.195-1.378-0.795-1.985c-0.76-0.797-1.613-0.801-2.004-0.847c-2.799-0.202-6.997-0.202-6.997-0.202 h-0.009c0,0-4.198,0-6.997,0.202C4.608,5.216,3.756,5.22,2.995,6.016C2.395,6.623,2.2,8.001,2.2,8.001S2,9.62,2,11.238v1.517 c0,1.618,0.2,3.237,0.2,3.237s0.195,1.378,0.795,1.985c0.761,0.797,1.76,0.771,2.205,0.855c1.6,0.153,6.8,0.201,6.8,0.201 s4.203-0.006,7.001-0.209c0.391-0.047,1.243-0.051,2.004-0.847c0.6-0.607,0.795-1.985,0.795-1.985s0.2-1.618,0.2-3.237v-1.517 C22,9.62,21.8,8.001,21.8,8.001z M9.935,14.594l-0.001-5.62l5.404,2.82L9.935,14.594z"></path></svg><span class="wp-block-social-link-label screen-reader-text">YouTube</span></a></li></ul>



<p class="has-text-align-center has-text-color has-link-color wp-elements-a0a2ac26ad214a49dac577734d259176" style="color:#84bd00"><a href="https://xojo.com/download/" target="_blank" rel="noreferrer noopener">Download Xojo</a></p>



<p></p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Code Signing on macOS: What Developers Need to Know, Part 2</title>
		<link>https://blog.xojo.com/2026/03/18/code-signing-on-macos-what-developers-need-to-know-part-2/</link>
		
		<dc:creator><![CDATA[Javier Menendez]]></dc:creator>
		<pubDate>Wed, 18 Mar 2026 14:00:00 +0000</pubDate>
				<category><![CDATA[General]]></category>
		<category><![CDATA[Learning]]></category>
		<category><![CDATA[Mac]]></category>
		<category><![CDATA[Security]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[Apple Developer Account]]></category>
		<category><![CDATA[Code Signing]]></category>
		<category><![CDATA[Distribution]]></category>
		<category><![CDATA[macOS]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=15864</guid>

					<description><![CDATA[On the Apple side of code signing with developer certificates, we already know that the required root certificate, acting as the base anchor of the&#8230;]]></description>
										<content:encoded><![CDATA[
<p>On the Apple side of code signing with developer certificates, we already know that the required root certificate, acting as the base anchor of the trust chain, is installed already on our Macs under the System Roots keychain.</p>



<p>But before we can reach our leaf developer certificates,&nbsp;we also need to have the Apple Development Intermediate certificates installed in our keychain. These are typically found in the Login keychain, though they can also be found in the System Roots or System keychains.</p>



<h2 class="wp-block-heading">Installing Apple Developer Intermediate Certificates</h2>



<p>Since Xcode 11.4.1 and later, these can be automatically downloaded and installed in the keychain, but if not, they can also can be downloaded from the <a href="https://www.apple.com/certificateauthority/" target="_blank" rel="noreferrer noopener">Apple PKI</a> webpage. The ones we are interested in are:</p>



<ul class="wp-block-list">
<li>Developer ID &#8211; G2</li>



<li>Worldwide Developer Relations &#8211; G2</li>



<li>Worldwide Developer Relations &#8211; G3</li>



<li>Worldwide Developer Relations &#8211; G4</li>



<li>Worldwide Developer Relations &#8211; G5</li>



<li>Worldwide Developer Relations &#8211; G6</li>
</ul>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p>Note: The Developer ID &#8211; G2 certificate corresponds to the Developer ID Certification Authority. The WWDR certificates (G2–G6) correspond to the Apple Worldwide Developer Relations Certification Authority.</p>
</blockquote>



<p>As you can see from the list, there are several versions (or generations) for the WWDR Intermediate certificate; so, which one should you download? The short answer: it depends.</p>



<p>On February, 7, 2023 the previous WWDR intermediate certificate expired; so Apple decided to rollout a new renewed version that will expire on February 20, 2030. As part of that update Apple issued additional Intermediate certificates to better segment the purpose of different certificates:</p>



<ul class="wp-block-list">
<li>G2: ECDSA signing for Apple Pay.</li>



<li>G3: Software signing and Services.</li>



<li>G4: Features supported by Apple Push Notification Service.</li>



<li>G5: App Store Signing and Services.</li>



<li>G6: ECDSA signing of Software and Services.</li>
</ul>



<p>In practice, G3, G4, and G5 are sufficient for most scenarios.</p>



<h2 class="wp-block-heading">Developer Certificates: The final goal!</h2>



<p>To focus on the subject, what kind of leaf developer certificates are created from these two types of Intermediate certificates? This scheme will help:</p>



<figure class="wp-block-image"><img loading="lazy" decoding="async" width="1644" height="912" src="https://blog.xojo.com/wp-content/uploads/2026/02/Apple-Development-Certificates-Chain-Of-Trust.png" alt="" class="wp-image-15865" srcset="https://blog.xojo.com/wp-content/uploads/2026/02/Apple-Development-Certificates-Chain-Of-Trust.png 1644w, https://blog.xojo.com/wp-content/uploads/2026/02/Apple-Development-Certificates-Chain-Of-Trust-300x166.png 300w, https://blog.xojo.com/wp-content/uploads/2026/02/Apple-Development-Certificates-Chain-Of-Trust-1024x568.png 1024w, https://blog.xojo.com/wp-content/uploads/2026/02/Apple-Development-Certificates-Chain-Of-Trust-768x426.png 768w, https://blog.xojo.com/wp-content/uploads/2026/02/Apple-Development-Certificates-Chain-Of-Trust-1536x852.png 1536w" sizes="auto, (max-width: 1644px) 100vw, 1644px" /></figure>



<p>As you can see from the above diagram, there are four main leaf certificates we will use to sign our macOS apps, based on their prefix:</p>



<ul class="wp-block-list">
<li><strong>Developer ID Application</strong>. Use this one to code sign a macOS app distributed outside the Mac App Store.</li>



<li><strong>Developer ID Installer</strong>. Use this one to code sign the Installer, DMG or .pgk file of a macOS app distributed outside the Mac App Store.</li>



<li><strong>Apple Distribution</strong>. This certificate is required to code sign a macOS app sent to the AppStore Connect for its distribution through the Mac App Store.</li>



<li><strong>3rd Party Mac Developer Installer</strong>. This Certificate is required to code sign the package of the app sent to the AppStore Connect. For example, when using the Publish feature from the Xojo IDE.</li>
</ul>



<h2 class="wp-block-heading">Creating and Installing the Developer Certificates</h2>



<p>As stated in the <a href="https://blog.xojo.com/2026/03/04/code-signing-on-macos-what-developers-need-to-know-part-1/" target="_blank" rel="noreferrer noopener">first article</a> of this series, you need a paid Apple Developer Program membership. Once that’s in place, the easiest way to install these required certificates in your macOS Keychain is through Xcode.</p>



<p>So, if it is the first time you need to install them on a Mac computer:</p>



<ol class="wp-block-list">
<li>Go to Xcode &gt; Preferences.</li>



<li>Select Apple Accounts.</li>



<li>Use your developer credentials to login into your developer account, or select it from the list if you are already logged.</li>



<li>Select the Team from the list.</li>



<li>Click the &#8220;Manage Certificates…&#8221; button.</li>



<li>Click the &#8220;+&#8221; popup menu in the lower-left corner of the resulting window, and select the developer certificate you want to install (all of these if it is the first time you install them).</li>
</ol>



<figure class="wp-block-image"><img loading="lazy" decoding="async" width="468" height="398" src="https://blog.xojo.com/wp-content/uploads/2026/02/Captura-de-pantalla-2026-02-25-a-las-15.53.00.png" alt="" class="wp-image-15866" srcset="https://blog.xojo.com/wp-content/uploads/2026/02/Captura-de-pantalla-2026-02-25-a-las-15.53.00.png 468w, https://blog.xojo.com/wp-content/uploads/2026/02/Captura-de-pantalla-2026-02-25-a-las-15.53.00-300x255.png 300w" sizes="auto, (max-width: 468px) 100vw, 468px" /></figure>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p><strong>Note:</strong> Under the hood, Xcode follows the same process described for installing the developer certificates manually.</p>
</blockquote>



<p>If you prefer to go through the manual process instead:</p>



<ol class="wp-block-list">
<li>Access the <a href="https://developer.apple.com" target="_blank" rel="noreferrer noopener">Apple Developer website</a>.</li>



<li>In <a href="https://developer.apple.com/account/resources" target="_blank" rel="noreferrer noopener">Certificates, Identifiers &amp; Profiles, click Certificates in the sidebar.</a></li>



<li>On the top left, click the add button (+).</li>



<li>Under Software, select Developer ID, then click Continue.
<ul class="wp-block-list">
<li><strong>Developer ID Application</strong>: This certificate is used to code sign your app for distribution outside of the Mac App Store Connect.</li>



<li><strong>Developer ID Installer</strong>: This certificate is used to sign your app’s installer Package for distribution outside of the Mac App Store Connect.</li>



<li><strong>Apple Development</strong>: Used to run and debug apps on macOS during development.</li>



<li><strong>Apple Distribution</strong>: Used to sign apps for submission to App Store Connect.</li>



<li><strong>Mac App Distribution</strong>: Used to sign macOS apps intended to be distributed through the Mac App Store.</li>



<li><strong>Mac Installer Distribution</strong>: Used to send the macOS app to the App Store Connect for TestFlight or distribution through the Mac App Store.</li>
</ul>
</li>



<li>Follow the instructions to <a href="https://developer.apple.com/help/account/certificates/create-a-certificate-signing-request" target="_blank" rel="noreferrer noopener">create a certificate signing request</a>.</li>



<li>Click Choose File.</li>



<li>In the dialog that appears, select the certificate request file (a file with a .certSigningRequest file extension), then click Choose.</li>



<li>Click Continue.</li>



<li>Click Download.</li>



<li>The certificate file (a file with a .cer file extension) appears in your Downloads folder.</li>



<li>To install the certificate in your keychain, double-click the downloaded certificate file. The certificate appears in the My Certificates category in Keychain Access.</li>
</ol>



<h2 class="wp-block-heading">It&#8217;s All About Identities</h2>



<p>While Intermediate and Root certificates only have the Public Key on them, so they can verify other (leaf) certificates, the leaf certificates installed on your macOS Login keychain behave a bit different. Let&#8217;s see how.</p>



<p>Both if you use Xcode or create the CSR request manually to generate the developer certificates, using the Keychain Access app for that, in both of these scenarios <strong>a Private Key will be created and stored locally on your keychain</strong> as part of the process. <strong>Only the public key section of that private key is sent to the Apple servers</strong> so it can be included in the generated developer certificate. Once any of the possible developer certificates is downloaded and installed in the keychain, such certificate will have its private key associated with it:</p>



<figure class="wp-block-image"><img loading="lazy" decoding="async" width="872" height="88" src="https://blog.xojo.com/wp-content/uploads/2026/02/Screenshot-2026-02-25-at-4.20.45-PM.png" alt="" class="wp-image-15867" srcset="https://blog.xojo.com/wp-content/uploads/2026/02/Screenshot-2026-02-25-at-4.20.45-PM.png 872w, https://blog.xojo.com/wp-content/uploads/2026/02/Screenshot-2026-02-25-at-4.20.45-PM-300x30.png 300w, https://blog.xojo.com/wp-content/uploads/2026/02/Screenshot-2026-02-25-at-4.20.45-PM-768x78.png 768w" sizes="auto, (max-width: 872px) 100vw, 872px" /></figure>



<p>The pair of the developer certificate and the associated private key is what is called an Identity.</p>



<h2 class="wp-block-heading">Code signing With Developer Certificates</h2>



<p>In fact, while we often say or hear “code signing with certificates,” the real signing of the app is done with the private key associated with that certificate. The certificate itself (and thus the public key portion of that key pair) is included in the signing process. This allows macOS to verify the signature each time the user runs the app</p>



<p>Do you remember the diagram showing how the &#8220;Ad-Hoc&#8221; code signing process works? Let&#8217;s compare it when the same process is done using a &#8220;Developer ID Application&#8221; Certificate… and, most important, the associated private key:</p>



<figure class="wp-block-image"><img loading="lazy" decoding="async" width="1724" height="812" src="https://blog.xojo.com/wp-content/uploads/2026/02/Apple-Certificate-Signing.png" alt="" class="wp-image-15869" srcset="https://blog.xojo.com/wp-content/uploads/2026/02/Apple-Certificate-Signing.png 1724w, https://blog.xojo.com/wp-content/uploads/2026/02/Apple-Certificate-Signing-300x141.png 300w, https://blog.xojo.com/wp-content/uploads/2026/02/Apple-Certificate-Signing-1024x482.png 1024w, https://blog.xojo.com/wp-content/uploads/2026/02/Apple-Certificate-Signing-768x362.png 768w, https://blog.xojo.com/wp-content/uploads/2026/02/Apple-Certificate-Signing-1536x723.png 1536w" sizes="auto, (max-width: 1724px) 100vw, 1724px" /></figure>



<p>As you can see, in this case the data is cyphered using the private key from the developer certificate and, then, the certificate itself is stored as part of the app itself. So, if for example we build this time an empty Desktop app for macOS using the Developer ID Application, and open the resulting CodeResources file in a text editor we will see something different compared with the Ad-Hoc signed version:</p>



<figure class="wp-block-image"><img loading="lazy" decoding="async" width="1298" height="974" src="https://blog.xojo.com/wp-content/uploads/2026/02/CodeResources_Signed.png" alt="" class="wp-image-15870" srcset="https://blog.xojo.com/wp-content/uploads/2026/02/CodeResources_Signed.png 1298w, https://blog.xojo.com/wp-content/uploads/2026/02/CodeResources_Signed-300x225.png 300w, https://blog.xojo.com/wp-content/uploads/2026/02/CodeResources_Signed-1024x768.png 1024w, https://blog.xojo.com/wp-content/uploads/2026/02/CodeResources_Signed-768x576.png 768w" sizes="auto, (max-width: 1298px) 100vw, 1298px" /></figure>



<p>In this case the field <strong>requirement&nbsp;</strong>associated with each file and hash value is significantly more strict. In fact, it makes reference to the Chain of Trust Gatekeeper is required to follow and validate. In plain English, the highlighted lines come to say something like:</p>



<ol class="wp-block-list">
<li>Hey! make sure there is a <strong>Developer ID Application</strong> certificate (Apple Extension attribute —OID— <em>1.2.840.113635.100.6.1.13&nbsp;</em>for the X.509 certificate), for the developer with a <strong>TeamID</strong> BW7PU32485.</li>



<li>Next, verify such certificate is issued by the &#8220;<strong>Apple Developer ID Certificate Authority</strong>&#8221; (other of the Apple-specific X.509 extension, attribute or OID. In this case: 1.2.840.113635.100.6.2.6).</li>



<li>And finally, go down through the Chain of Trust and verify the previous one with the <strong>Anchor</strong> certificate (Apple Root CA, do you remember?)</li>
</ol>



<p>So far so good. But how we can know if the app meets these requirements; and what about the certificates themselves? Well, it&#8217;s easy to check both using the codesign tool.</p>



<p>Open a Terminal window and type the following command:</p>



<pre class="wp-block-preformatted">codesign --verify -vvv "MyApp.app"</pre>



<p>The output will be something similar to this:</p>



<figure class="wp-block-image"><img loading="lazy" decoding="async" width="2198" height="336" src="https://blog.xojo.com/wp-content/uploads/2026/02/codesign-SatisfiedRequirement.png" alt="" class="wp-image-15871" srcset="https://blog.xojo.com/wp-content/uploads/2026/02/codesign-SatisfiedRequirement.png 2198w, https://blog.xojo.com/wp-content/uploads/2026/02/codesign-SatisfiedRequirement-300x46.png 300w, https://blog.xojo.com/wp-content/uploads/2026/02/codesign-SatisfiedRequirement-1024x157.png 1024w, https://blog.xojo.com/wp-content/uploads/2026/02/codesign-SatisfiedRequirement-768x117.png 768w, https://blog.xojo.com/wp-content/uploads/2026/02/codesign-SatisfiedRequirement-1536x235.png 1536w, https://blog.xojo.com/wp-content/uploads/2026/02/codesign-SatisfiedRequirement-2048x313.png 2048w" sizes="auto, (max-width: 2198px) 100vw, 2198px" /></figure>



<p>As you can see in the highlighted lines, yes, it satisfies the <strong>Designated Requirements</strong> we saw in our CodeResources file! Also, the previous line states that it is valid on disk. That means:</p>



<ul class="wp-block-list">
<li>All of the expected files are present.</li>



<li>There are no extra files.</li>



<li>None of the files have been modified.</li>



<li>A basic trust evaluation of the leaf certificate was successful.</li>



<li>And it satisfies its own Designated Requirements (DR).</li>
</ul>



<p>It is even possible to see the Chain of Trust for the code signature issuing:</p>



<pre class="wp-block-preformatted">codesign --display -vv "MyApp.app"&nbsp;</pre>



<figure class="wp-block-image"><img loading="lazy" decoding="async" width="1222" height="340" src="https://blog.xojo.com/wp-content/uploads/2026/02/Codesign-ChainOfTrust.png" alt="" class="wp-image-15872" srcset="https://blog.xojo.com/wp-content/uploads/2026/02/Codesign-ChainOfTrust.png 1222w, https://blog.xojo.com/wp-content/uploads/2026/02/Codesign-ChainOfTrust-300x83.png 300w, https://blog.xojo.com/wp-content/uploads/2026/02/Codesign-ChainOfTrust-1024x285.png 1024w, https://blog.xojo.com/wp-content/uploads/2026/02/Codesign-ChainOfTrust-768x214.png 768w" sizes="auto, (max-width: 1222px) 100vw, 1222px" /></figure>



<p>And if you are curious enough, it is even possible to extract the embedded certificates stored in the <a href="https://www.ietf.org/rfc/rfc3852.txt" target="_blank" rel="noreferrer noopener">CMS structure within the code signature</a>:</p>



<pre class="wp-block-preformatted">codesign --display --extract-certificates "MyApp.app"</pre>



<p>As result it will, usually, create three files. Take a closer look at the &#8220;Issuer&#8221; and &#8220;Subject&#8221; lines; specially on the Subject line for the OU value (Organizative Unit or, using Apple wording, the TeamID) for the codesign0 file. Do you remember the &#8220;leaf[subject.OU=BW7PU32485]&#8221; data from the CodeResources file?&nbsp;:</p>



<p><strong>codesign0.</strong> This is the file for the Leaf certificate; in our example &#8220;Developer ID Application&#8221;.</p>



<figure class="wp-block-image"><img loading="lazy" decoding="async" width="1820" height="368" src="https://blog.xojo.com/wp-content/uploads/2026/02/codesign-DeveloperIDCertificate.png" alt="" class="wp-image-15873" srcset="https://blog.xojo.com/wp-content/uploads/2026/02/codesign-DeveloperIDCertificate.png 1820w, https://blog.xojo.com/wp-content/uploads/2026/02/codesign-DeveloperIDCertificate-300x61.png 300w, https://blog.xojo.com/wp-content/uploads/2026/02/codesign-DeveloperIDCertificate-1024x207.png 1024w, https://blog.xojo.com/wp-content/uploads/2026/02/codesign-DeveloperIDCertificate-768x155.png 768w, https://blog.xojo.com/wp-content/uploads/2026/02/codesign-DeveloperIDCertificate-1536x311.png 1536w" sizes="auto, (max-width: 1820px) 100vw, 1820px" /></figure>



<p><strong>codesign1.</strong> This one is for the Intermediate Certificate; in our example &#8220;Apple Developer ID Certificate Authority&#8221;.</p>



<figure class="wp-block-image"><img loading="lazy" decoding="async" width="1562" height="366" src="https://blog.xojo.com/wp-content/uploads/2026/02/codesign-IntermediateCertificate.png" alt="" class="wp-image-15874" srcset="https://blog.xojo.com/wp-content/uploads/2026/02/codesign-IntermediateCertificate.png 1562w, https://blog.xojo.com/wp-content/uploads/2026/02/codesign-IntermediateCertificate-300x70.png 300w, https://blog.xojo.com/wp-content/uploads/2026/02/codesign-IntermediateCertificate-1024x240.png 1024w, https://blog.xojo.com/wp-content/uploads/2026/02/codesign-IntermediateCertificate-768x180.png 768w, https://blog.xojo.com/wp-content/uploads/2026/02/codesign-IntermediateCertificate-1536x360.png 1536w" sizes="auto, (max-width: 1562px) 100vw, 1562px" /></figure>



<p><strong>codesign2.</strong> This one is for the Anchor Certificate; in our example &#8220;Apple Root CA&#8221;</p>



<figure class="wp-block-image"><img loading="lazy" decoding="async" width="1274" height="344" src="https://blog.xojo.com/wp-content/uploads/2026/02/codesign-RootCertificate.png" alt="" class="wp-image-15875" srcset="https://blog.xojo.com/wp-content/uploads/2026/02/codesign-RootCertificate.png 1274w, https://blog.xojo.com/wp-content/uploads/2026/02/codesign-RootCertificate-300x81.png 300w, https://blog.xojo.com/wp-content/uploads/2026/02/codesign-RootCertificate-1024x276.png 1024w, https://blog.xojo.com/wp-content/uploads/2026/02/codesign-RootCertificate-768x207.png 768w" sizes="auto, (max-width: 1274px) 100vw, 1274px" /></figure>



<p><br>As shown by the <strong>Issuer</strong> line in the codesign0 file for our “Developer ID Application,” it points to the previous certificate in the trust chain—the Developer ID Certification Authority. The codesign1 file for the extracted Developer ID Certification Authority points to the Apple Certification Authority in its Issuer field. Finally, the codesign1 certificate points to itself because, as the Root Certificate, it serves as the <strong>anchor</strong> for the trust chain.</p>



<h2 class="wp-block-heading">Wrapping up</h2>



<p>In this second article, we delved deeper into how Apple Developer certificates work, how a macOS app is signed (Ad-Hoc or with a specific developer certificate), and how the OS’s security features validate the signing when a user tries to run the app.</p>



<p>In the next article, we will cover more details about signing apps for the two main distribution types: Direct distribution and Mac App Store. We will also discuss what happens when certificates expire and how to troubleshoot the most common issues related to development certificates.</p>



<p><em>Javier Menendez is an engineer at Xojo and has been using Xojo since 1998. He lives in Castellón</em>, <em>Spain and hosts regular Xojo hangouts en español. Ask Javier questions on Twitter at <a href="https://twitter.com/xojoes" target="_blank" rel="noreferrer noopener">@XojoES</a> or on the <a href="https://forum.xojo.com/u/javier_menendez/summary" target="_blank" rel="noreferrer noopener">Xojo Forum</a>.</em></p>



<ul class="wp-block-social-links has-normal-icon-size is-content-justification-center is-layout-flex wp-container-core-social-links-is-layout-16018d1d wp-block-social-links-is-layout-flex"><li class="wp-social-link wp-social-link-facebook  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.facebook.com/goxojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M12 2C6.5 2 2 6.5 2 12c0 5 3.7 9.1 8.4 9.9v-7H7.9V12h2.5V9.8c0-2.5 1.5-3.9 3.8-3.9 1.1 0 2.2.2 2.2.2v2.5h-1.3c-1.2 0-1.6.8-1.6 1.6V12h2.8l-.4 2.9h-2.3v7C18.3 21.1 22 17 22 12c0-5.5-4.5-10-10-10z"></path></svg><span class="wp-block-social-link-label screen-reader-text">Facebook</span></a></li>

<li class="wp-social-link wp-social-link-x  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://x.com/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M13.982 10.622 20.54 3h-1.554l-5.693 6.618L8.745 3H3.5l6.876 10.007L3.5 21h1.554l6.012-6.989L15.868 21h5.245l-7.131-10.378Zm-2.128 2.474-.697-.997-5.543-7.93H8l4.474 6.4.697.996 5.815 8.318h-2.387l-4.745-6.787Z" /></svg><span class="wp-block-social-link-label screen-reader-text">X</span></a></li>

<li class="wp-social-link wp-social-link-linkedin  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.linkedin.com/company/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M19.7,3H4.3C3.582,3,3,3.582,3,4.3v15.4C3,20.418,3.582,21,4.3,21h15.4c0.718,0,1.3-0.582,1.3-1.3V4.3 C21,3.582,20.418,3,19.7,3z M8.339,18.338H5.667v-8.59h2.672V18.338z M7.004,8.574c-0.857,0-1.549-0.694-1.549-1.548 c0-0.855,0.691-1.548,1.549-1.548c0.854,0,1.547,0.694,1.547,1.548C8.551,7.881,7.858,8.574,7.004,8.574z M18.339,18.338h-2.669 v-4.177c0-0.996-0.017-2.278-1.387-2.278c-1.389,0-1.601,1.086-1.601,2.206v4.249h-2.667v-8.59h2.559v1.174h0.037 c0.356-0.675,1.227-1.387,2.526-1.387c2.703,0,3.203,1.779,3.203,4.092V18.338z"></path></svg><span class="wp-block-social-link-label screen-reader-text">LinkedIn</span></a></li>

<li class="wp-social-link wp-social-link-github  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://github.com/topics/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M12,2C6.477,2,2,6.477,2,12c0,4.419,2.865,8.166,6.839,9.489c0.5,0.09,0.682-0.218,0.682-0.484 c0-0.236-0.009-0.866-0.014-1.699c-2.782,0.602-3.369-1.34-3.369-1.34c-0.455-1.157-1.11-1.465-1.11-1.465 c-0.909-0.62,0.069-0.608,0.069-0.608c1.004,0.071,1.532,1.03,1.532,1.03c0.891,1.529,2.341,1.089,2.91,0.833 c0.091-0.647,0.349-1.086,0.635-1.337c-2.22-0.251-4.555-1.111-4.555-4.943c0-1.091,0.39-1.984,1.03-2.682 C6.546,8.54,6.202,7.524,6.746,6.148c0,0,0.84-0.269,2.75,1.025C10.295,6.95,11.15,6.84,12,6.836 c0.85,0.004,1.705,0.114,2.504,0.336c1.909-1.294,2.748-1.025,2.748-1.025c0.546,1.376,0.202,2.394,0.1,2.646 c0.64,0.699,1.026,1.591,1.026,2.682c0,3.841-2.337,4.687-4.565,4.935c0.359,0.307,0.679,0.917,0.679,1.852 c0,1.335-0.012,2.415-0.012,2.741c0,0.269,0.18,0.579,0.688,0.481C19.138,20.161,22,16.416,22,12C22,6.477,17.523,2,12,2z"></path></svg><span class="wp-block-social-link-label screen-reader-text">GitHub</span></a></li>

<li class="wp-social-link wp-social-link-youtube  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.youtube.com/c/XojoInc" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M21.8,8.001c0,0-0.195-1.378-0.795-1.985c-0.76-0.797-1.613-0.801-2.004-0.847c-2.799-0.202-6.997-0.202-6.997-0.202 h-0.009c0,0-4.198,0-6.997,0.202C4.608,5.216,3.756,5.22,2.995,6.016C2.395,6.623,2.2,8.001,2.2,8.001S2,9.62,2,11.238v1.517 c0,1.618,0.2,3.237,0.2,3.237s0.195,1.378,0.795,1.985c0.761,0.797,1.76,0.771,2.205,0.855c1.6,0.153,6.8,0.201,6.8,0.201 s4.203-0.006,7.001-0.209c0.391-0.047,1.243-0.051,2.004-0.847c0.6-0.607,0.795-1.985,0.795-1.985s0.2-1.618,0.2-3.237v-1.517 C22,9.62,21.8,8.001,21.8,8.001z M9.935,14.594l-0.001-5.62l5.404,2.82L9.935,14.594z"></path></svg><span class="wp-block-social-link-label screen-reader-text">YouTube</span></a></li></ul>



<p class="has-text-align-center has-text-color has-link-color wp-elements-a0a2ac26ad214a49dac577734d259176" style="color:#84bd00"><a href="https://xojo.com/download/" target="_blank" rel="noreferrer noopener">Download Xojo</a></p>



<p><strong>Code Signing on macOS: What Developers Need to Know</strong></p>



<ul class="wp-block-list">
<li><a href="https://blog.xojo.com/2026/03/04/code-signing-on-macos-what-developers-need-to-know-part-1/" target="_blank" rel="noreferrer noopener">Part 1, Get Started</a></li>



<li><a href="https://blog.xojo.com/2026/03/18/code-signing-on-macos-what-developers-need-to-know-part-2/" target="_blank" rel="noreferrer noopener">Part 2, Code Signing With Developer Certificates</a></li>



<li><a href="https://blog.xojo.com/2026/03/24/code-signing-on-macos-what-developers-need-to-know-part-3/">Part 3, Entitlements and Provisioning Profiles</a></li>



<li><a href="https://blog.xojo.com/2026/04/07/code-signing-on-macos-what-developers-need-to-know-part-4/" target="_blank" rel="noreferrer noopener">Part 4, How Xojo helps with Certificates, Signing and Distribution</a></li>
</ul>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Your Framework, Your Rules: Why I Use Extends for Everything</title>
		<link>https://blog.xojo.com/2026/03/17/your-framework-your-rules-why-i-use-extends-for-everything/</link>
		
		<dc:creator><![CDATA[Gabriel Ludosanu]]></dc:creator>
		<pubDate>Tue, 17 Mar 2026 15:00:00 +0000</pubDate>
				<category><![CDATA[General]]></category>
		<category><![CDATA[Code Organization]]></category>
		<category><![CDATA[Extends]]></category>
		<category><![CDATA[Extension Methods]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=15904</guid>

					<description><![CDATA[Over the weekend, I was deep into a side project, parsing a massive server log dump. Strings were everywhere: timestamps were mangled, JSON blobs were&#8230;]]></description>
										<content:encoded><![CDATA[
<p>Over the weekend, I was deep into a side project, parsing a massive server log dump. Strings were everywhere: timestamps were mangled, JSON blobs were half-broken&#8230;I kept writing these clunky utility calls, nesting functions inside functions, my code was turning into a sideways pyramid of parentheses.</p>



<p>Then I remembered&nbsp;<code>Extends</code>.</p>



<p>It&#8217;s one of those features that sits quietly in the language. But once it clicks, it changes how you think about utility code entirely. Using Extends, within twenty minutes, my nested mess became readable.</p>



<h2 class="wp-block-heading" id="the-moment-it-clicks">Extends Methods in Practice</h2>



<p>You know the feeling. You&#8217;re writing&nbsp;<code>ParseLogEntry(rawLine)</code>&nbsp;for the hundredth time, and something feels off. The function works. It&#8217;s in your Utilities module (maybe part of a Library?). But every time you call it, there&#8217;s this tiny friction. Why doesn&#8217;t String just&nbsp;<em>know</em>&nbsp;how to parse itself into a log entry? That&#8217;s what&nbsp;<code>Extends</code>&nbsp;fixes.</p>



<p>It lets you teach existing classes new tricks. You write a method in a module, tag the first parameter with&nbsp;<code>Extends</code>, and suddenly&nbsp;<code>String</code>,&nbsp;<code>DateTime</code>,&nbsp;<code>Dictionary</code>&nbsp;(whatever you need) behaves like it always had that method. No subclassing. No wrapper classes. Just the framework, extended to fit&nbsp;<em>your</em>&nbsp;brain.</p>



<h2 class="wp-block-heading" id="why-it-matters">Reading The Code</h2>



<p>Code is read far more than it&#8217;s written. We both know this. But we still write code that reads backwards.</p>



<pre class="wp-block-code"><code>// The old way
Var result As DateTime = ExtractTimestamp(CleanLogEntry(rawLine))

// With Extends
Var result As DateTime = rawLine.CleanLogEntry.ExtractTimestamp</code></pre>



<p>When you&#8217;re debugging at 2 AM, tracing logic through nested function calls is the last thing you want. Extension methods turn that horizontal scan into a vertical one. </p>



<h2 class="wp-block-heading" id="when-i-reach-for-it">When Extends is Exactly Right</h2>



<p>I don&#8217;t use&nbsp;<code>Extends</code>&nbsp;for everything; it&#8217;s not a replacement for proper inheritance or composition. But there are specific moments when it&#8217;s exactly right.</p>



<p><strong>Built-in types that need one more method.</strong>&nbsp;For my log parser, I needed to extract timestamps, clean junk characters, and pull out ISO dates. So, I extended the String class with my custom utilities and made it feel native.</p>



<p><strong>Framework classes you can&#8217;t touch.</strong>&nbsp;You can&#8217;t subclass everything, but <code>Extends</code> can work around things like things third-party plugins, legacy code.</p>



<p><strong>APIs you wish existed.</strong>&nbsp;I&#8217;ve lost count of how many times I&#8217;ve wanted a property or method on a framework class that just isn&#8217;t there.&nbsp;<code>Extends</code>&nbsp;lets me do just that.</p>



<p>For practical examples like email validation, URL validation, and dictionary helpers, check out this&nbsp;<a href="https://blog.xojo.com/2020/06/03/using-class-extensions-to-validate-email-and-url-data/">article</a>&nbsp;that walks you through real implementations. If you want code you can copy into your project today, it&#8217;s a good place to start.</p>



<h2 class="wp-block-heading" id="a-few-gotchas">A Few Things To Keep In Mind</h2>



<p><strong>Nil doesn&#8217;t forgive.</strong>&nbsp;Call an extension on a Nil object and you&#8217;ll get a&nbsp;<code>NilObjectException</code>&nbsp;before your method even runs. The extension sits on the right side of the dot. That object needs to exist.</p>



<p><strong>No override.</strong>&nbsp;You can&#8217;t replace built-in methods. If you try creating an extension with the same name as an existing method, the compiler will use the original. That&#8217;s a good thing; it means you can&#8217;t accidentally break framework behavior.</p>



<p><strong>No properties.</strong>&nbsp;Extensions add behavior, not state. If you need to store data, you still need a subclass or a wrapper.</p>



<p><strong>Stay organized.</strong>&nbsp;Put extensions in well-named modules like&nbsp;<code>LogParsingExtensions</code>&nbsp;or&nbsp;<code>StringHelpers</code>. Six months from now, you&#8217;ll want to know where that&nbsp;<code>.ExtractTimestamp</code>&nbsp;method came from.</p>



<p><strong>Dependencies can hide.</strong>&nbsp;Extension methods live in modules and behave like native methods, so it&#8217;s not always obvious which module a class depends on. Good naming helps.</p>



<h2 class="wp-block-heading" id="try-it">Trying Extends</h2>



<p>If you&#8217;ve never written an extension method, take five minutes. Add a module to your project and create a method like this:</p>



<pre class="wp-block-code"><code>Public Function ExtractFirstISODate(<strong>Extends source As String</strong>) As DateTime
  Var rx As New RegEx
  rx.SearchPattern = "(\d{4}-\d{2}-\d{2})&#91;Tt]?(\d{2}:\d{2}:\d{2})"
  
  Var match As RegExMatch = rx.Search(source)
  If match &lt;&gt; Nil And match.SubExpressionCount &gt; 1 Then
    Var datePart As String = match.SubExpressionString(1)
    Var timePart As String = match.SubExpressionString(2)
    Var isoString As String = datePart + " " + timePart
    
    Try
      Return DateTime.FromString(isoString)
    Catch err As RuntimeException
      Return Nil
    End Try
  End If
  Return Nil
End Function</code></pre>



<p>Now you can call it directly on any string:</p>



<pre class="wp-block-code"><code>Var logLine As String = "&#91;2025-08-14T14:32:15] ERROR: Connection timeout"

Var timestamp As DateTime = logLine.<strong>ExtractFirstISODate</strong>

If timestamp &lt;&gt; Nil Then
  MessageBox("Found timestamp: " + timestamp.ToString)
Else
  MessageBox("No valid timestamp found")
End If</code></pre>



<p>That&#8217;s it. No utility class to instantiate. No module name to remember. Just&nbsp;<code>stringVar.ExtractFirstISODate</code>.</p>



<p>For more complete examples, check out the <a href="https://documentation.xojo.com/getting_started/using_the_xojo_language/modules.html#getting-started-using-the-xojo-language-modules-extension-methods" target="_blank" rel="noreferrer noopener">Extension Methods topic</a> in the Xojo Documentation as well as the <a href="https://forum.xojo.com/c/code-sharing/62" data-type="link" data-id="https://forum.xojo.com/c/code-sharing/62" target="_blank" rel="noreferrer noopener">Code Sharing Forum</a>.</p>



<p><em>Gabriel is a digital marketing enthusiast who loves coding with Xojo to create cool software tools for any platform. He is always eager to learn and share new ideas!</em></p>



<ul class="wp-block-social-links has-normal-icon-size is-content-justification-center is-layout-flex wp-container-core-social-links-is-layout-16018d1d wp-block-social-links-is-layout-flex"><li class="wp-social-link wp-social-link-facebook  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.facebook.com/goxojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M12 2C6.5 2 2 6.5 2 12c0 5 3.7 9.1 8.4 9.9v-7H7.9V12h2.5V9.8c0-2.5 1.5-3.9 3.8-3.9 1.1 0 2.2.2 2.2.2v2.5h-1.3c-1.2 0-1.6.8-1.6 1.6V12h2.8l-.4 2.9h-2.3v7C18.3 21.1 22 17 22 12c0-5.5-4.5-10-10-10z"></path></svg><span class="wp-block-social-link-label screen-reader-text">Facebook</span></a></li>

<li class="wp-social-link wp-social-link-x  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://x.com/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M13.982 10.622 20.54 3h-1.554l-5.693 6.618L8.745 3H3.5l6.876 10.007L3.5 21h1.554l6.012-6.989L15.868 21h5.245l-7.131-10.378Zm-2.128 2.474-.697-.997-5.543-7.93H8l4.474 6.4.697.996 5.815 8.318h-2.387l-4.745-6.787Z" /></svg><span class="wp-block-social-link-label screen-reader-text">X</span></a></li>

<li class="wp-social-link wp-social-link-linkedin  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.linkedin.com/company/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M19.7,3H4.3C3.582,3,3,3.582,3,4.3v15.4C3,20.418,3.582,21,4.3,21h15.4c0.718,0,1.3-0.582,1.3-1.3V4.3 C21,3.582,20.418,3,19.7,3z M8.339,18.338H5.667v-8.59h2.672V18.338z M7.004,8.574c-0.857,0-1.549-0.694-1.549-1.548 c0-0.855,0.691-1.548,1.549-1.548c0.854,0,1.547,0.694,1.547,1.548C8.551,7.881,7.858,8.574,7.004,8.574z M18.339,18.338h-2.669 v-4.177c0-0.996-0.017-2.278-1.387-2.278c-1.389,0-1.601,1.086-1.601,2.206v4.249h-2.667v-8.59h2.559v1.174h0.037 c0.356-0.675,1.227-1.387,2.526-1.387c2.703,0,3.203,1.779,3.203,4.092V18.338z"></path></svg><span class="wp-block-social-link-label screen-reader-text">LinkedIn</span></a></li>

<li class="wp-social-link wp-social-link-github  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://github.com/topics/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M12,2C6.477,2,2,6.477,2,12c0,4.419,2.865,8.166,6.839,9.489c0.5,0.09,0.682-0.218,0.682-0.484 c0-0.236-0.009-0.866-0.014-1.699c-2.782,0.602-3.369-1.34-3.369-1.34c-0.455-1.157-1.11-1.465-1.11-1.465 c-0.909-0.62,0.069-0.608,0.069-0.608c1.004,0.071,1.532,1.03,1.532,1.03c0.891,1.529,2.341,1.089,2.91,0.833 c0.091-0.647,0.349-1.086,0.635-1.337c-2.22-0.251-4.555-1.111-4.555-4.943c0-1.091,0.39-1.984,1.03-2.682 C6.546,8.54,6.202,7.524,6.746,6.148c0,0,0.84-0.269,2.75,1.025C10.295,6.95,11.15,6.84,12,6.836 c0.85,0.004,1.705,0.114,2.504,0.336c1.909-1.294,2.748-1.025,2.748-1.025c0.546,1.376,0.202,2.394,0.1,2.646 c0.64,0.699,1.026,1.591,1.026,2.682c0,3.841-2.337,4.687-4.565,4.935c0.359,0.307,0.679,0.917,0.679,1.852 c0,1.335-0.012,2.415-0.012,2.741c0,0.269,0.18,0.579,0.688,0.481C19.138,20.161,22,16.416,22,12C22,6.477,17.523,2,12,2z"></path></svg><span class="wp-block-social-link-label screen-reader-text">GitHub</span></a></li>

<li class="wp-social-link wp-social-link-youtube  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.youtube.com/c/XojoInc" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M21.8,8.001c0,0-0.195-1.378-0.795-1.985c-0.76-0.797-1.613-0.801-2.004-0.847c-2.799-0.202-6.997-0.202-6.997-0.202 h-0.009c0,0-4.198,0-6.997,0.202C4.608,5.216,3.756,5.22,2.995,6.016C2.395,6.623,2.2,8.001,2.2,8.001S2,9.62,2,11.238v1.517 c0,1.618,0.2,3.237,0.2,3.237s0.195,1.378,0.795,1.985c0.761,0.797,1.76,0.771,2.205,0.855c1.6,0.153,6.8,0.201,6.8,0.201 s4.203-0.006,7.001-0.209c0.391-0.047,1.243-0.051,2.004-0.847c0.6-0.607,0.795-1.985,0.795-1.985s0.2-1.618,0.2-3.237v-1.517 C22,9.62,21.8,8.001,21.8,8.001z M9.935,14.594l-0.001-5.62l5.404,2.82L9.935,14.594z"></path></svg><span class="wp-block-social-link-label screen-reader-text">YouTube</span></a></li></ul>



<p class="has-text-align-center has-text-color has-link-color wp-elements-a0a2ac26ad214a49dac577734d259176" style="color:#84bd00"><a href="https://xojo.com/download/" target="_blank" rel="noreferrer noopener">Download Xojo</a></p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Optimizing Xojo Code, Part 5: Threads and UserInterfaceUpdate</title>
		<link>https://blog.xojo.com/2026/03/02/optimizing-xojo-code-part-5-threads-and-userinterfaceupdate/</link>
		
		<dc:creator><![CDATA[Gabriel Ludosanu]]></dc:creator>
		<pubDate>Mon, 02 Mar 2026 23:43:13 +0000</pubDate>
				<category><![CDATA[Fun]]></category>
		<category><![CDATA[General]]></category>
		<category><![CDATA[Learning]]></category>
		<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[Multithreaded Applications]]></category>
		<category><![CDATA[Threading]]></category>
		<category><![CDATA[Threads]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=15847</guid>

					<description><![CDATA[In&#160;Part 1, we learned why tight loops with&#160;DoEvents&#160;freeze your UI.&#160;Part 2&#160;showed us Timer controls.&#160;Part 3&#160;moved timers into code.&#160;Part 4&#160;simplified scheduling with&#160;CallLater. But timers have a&#8230;]]></description>
										<content:encoded><![CDATA[
<p>In&nbsp;<a href="https://blog.xojo.com/2025/11/20/optimizing-xojo-code-part-1-getting-started/">Part 1</a>, we learned why tight loops with&nbsp;<code>DoEvents</code>&nbsp;freeze your UI.&nbsp;<a href="https://blog.xojo.com/2025/11/25/optimizing-xojo-code-part-2-using-a-timer-to-keep-the-ui-responsive/">Part 2</a>&nbsp;showed us Timer controls.&nbsp;<a href="https://blog.xojo.com/2026/01/14/optimizing-xojo-code-part-3-programmatic-timers-and-addhandler/">Part 3</a>&nbsp;moved timers into code.&nbsp;<a href="https://blog.xojo.com/2026/02/02/optimizing-xojo-code-part-4-timer-calllater/">Part 4</a>&nbsp;simplified scheduling with&nbsp;<code>CallLater</code>.</p>



<p>But timers have a limit: they still run on the UI thread. If your background work is genuinely heavy (database queries, file I/O, complex calculations), a timer won&#8217;t save you. You need actual background processing and that&#8217;s where threads come in.</p>



<h2 class="wp-block-heading" id="the-core-idea-threads">The Core Idea: Threads</h2>



<p>A thread is a separate execution path that runs outside the UI thread. While your thread does the heavy lifting, the UI stays responsive to clicks, typing, scrolling. When your thread finishes a chunk of work, it notifies the UI thread via&nbsp;<code>UserInterfaceUpdate</code>, and only that callback runs on the main thread.</p>



<p>The rule is simple: threads cannot touch UI controls directly. If you try, you get a crash.&nbsp;<code>UserInterfaceUpdate</code>&nbsp;is your bridge.</p>



<p>For a deeper dive into how Xojo&#8217;s threading model works under the hood, including cooperative vs. preemptive threading, see&nbsp;<a href="https://blog.xojo.com/2024/10/01/cooperative-to-preemptive-weaving-new-threads-into-your-apps/" target="_blank" rel="noreferrer noopener">Cooperative to Preemptive: Weaving New Threads Into Your Apps</a>.</p>



<h2 class="wp-block-heading" id="looking-at-the-code">Let&#8217;s Code</h2>



<p><strong>Prerequisites:</strong>&nbsp;Add a&nbsp;<code>StatusLabel</code>&nbsp;(DesktopLabel), a&nbsp;<code>DesktopButton</code>, and a&nbsp;<code>Thread</code>&nbsp;control. Also define:</p>



<pre class="wp-block-code"><code>kCountTo As Integer = 100</code></pre>



<h3 class="wp-block-heading" id="the-thread-control">The Thread Control</h3>



<p>Drag a&nbsp;<code>Thread</code>&nbsp;from the library into your window and name it&nbsp;<code>BackgroundWorker</code>.</p>



<h3 class="wp-block-heading" id="the-button-start-the-thread">The Button (Start the Thread)</h3>



<p>Place this in the&nbsp;<code>Pressed</code>&nbsp;event of a button:</p>



<pre class="wp-block-code"><code>Sub Pressed()
  If BackgroundWorker.ThreadState = Thread.ThreadStates.NotRunning Then
    BackgroundWorker.Start
  End If
End Sub</code></pre>



<p>This checks if the thread is already running. If not, start it. This prevents multiple threads from piling up if someone clicks fast.</p>



<h3 class="wp-block-heading" id="the-run-method-background-work">The Thread.Run Method (Background Work)</h3>



<p>Implement the&nbsp;<code>Run</code>&nbsp;method on your Thread:</p>



<pre class="wp-block-code"><code>Sub Run()
  For i As Integer = 0 To kCountTo
    
    ' Do background work here. No UI access allowed.
    ' It can be: database query, file read, API call, pretty much anything that might block "freeze" the UI of the app
    
    ' Prepare a Dictionary payload for the UI
    Var info As New Dictionary
    info.Value("progress") = i
    info.Value("message") = "working"
    Me.AddUserInterfaceUpdate(info)
    
    ' Sleep (optional)
    Thread.SleepCurrent(10)   // Sleep 10 ms
  Next
End Sub</code></pre>



<p>The key line is&nbsp;<code>Me.AddUserInterfaceUpdate(info)</code>. This queues data for the UI thread to process. Each call adds one item to a queue, and the UI thread drains it in&nbsp;<code>UserInterfaceUpdate</code>.</p>



<h3 class="wp-block-heading" id="the-userinterfaceupdate-method-ui-sync">The Thread.UserInterfaceUpdate Method (UI Sync)</h3>



<p>Implement this event to handle updates from the thread:</p>



<pre class="wp-block-code"><code>Sub UserInterfaceUpdate(data() As Dictionary)
  ' Runs on the main UI thread. Safe to update controls here.
  
  ' Guard against empty or malformed data
  If data = Nil Or data.Count &lt; 0 Then Return
  
  Var d As Dictionary = data(0)
  
  ' Extract the progress value safely
  Var progress As Integer = 0
  If d.HasKey("progress") Then
    progress = d.Value("progress").IntegerValue
  End If
  
  ' Update the UI
  StatusLabel.Text = progress.ToString
  
  ' Mark completion when we hit the target
  If progress &gt;= kCountTo Then
    StatusLabel.Text = "done"
  End If
End Sub</code></pre>



<p><strong>Important notes:</strong></p>



<ul class="wp-block-list">
<li><code>data()</code>&nbsp;is an array of Dictionaries.</li>



<li>Always check&nbsp;<code>HasKey</code>&nbsp;before accessing a value to avoid runtime errors.</li>



<li>Use&nbsp;<code>.IntegerValue</code>&nbsp;(or&nbsp;<code>.StringValue</code>, etc.) to safely extract values.</li>



<li>This runs on the UI thread, so it is safe to update&nbsp;<code>StatusLabel</code>&nbsp;and any other visual controls.</li>
</ul>



<h2 class="wp-block-heading" id="how-it-works">How It Works</h2>



<ol class="wp-block-list">
<li><strong>Button press:</strong>&nbsp;Click the button and the thread starts.</li>



<li><strong>Background loop:</strong>&nbsp;The thread iterates from 0 to&nbsp;<code>kCountTo</code>, sleeping 10 ms each step. After each step, it queues an update.</li>



<li><strong>Responsiveness:</strong>&nbsp;While the thread works, you can still interact with the rest of your application. No freezing.</li>
</ol>



<h2 class="wp-block-heading" id="a-note-on-thread-safety">A Note on Thread Safety</h2>



<p>Threads are powerful but risky if misused. Here is the boundary:</p>



<ul class="wp-block-list">
<li><strong>Safe in Run():</strong>&nbsp;Anything that doesn&#8217;t touch UI controls. File I/O, database queries, calculations, network calls.</li>



<li><strong>Unsafe in Run():</strong>&nbsp;Reading or writing UI control properties directly.&nbsp;<code>StatusLabel.Text = ...</code>&nbsp;is a no no!</li>



<li><strong>Safe in UserInterfaceUpdate():</strong>&nbsp;All UI control access. This runs on the main thread.</li>
</ul>



<p>If you forget this rule and try to update a label from inside&nbsp;<code>Run()</code>, your app will crash with a <a href="https://documentation.xojo.com/api/language/runtime.html#runtime">ThreadAccessingUIException</a>. Instead pass data through&nbsp;<code>AddUserInterfaceUpdate</code>.</p>



<h2 class="wp-block-heading" id="when-to-use-threads-vs-timers">When to Use Threads vs. Timers</h2>



<p>Use timers for:</p>



<ul class="wp-block-list">
<li>Short, frequent tasks (10-50 ms ticks).</li>



<li>Simple progress updates.</li>



<li>Cases where you are just deferring work a bit.</li>
</ul>



<p>Use threads for:</p>



<ul class="wp-block-list">
<li>Long-running operations (seconds, minutes, hours).</li>



<li>Genuinely blocking work (I/O, network, heavy calculations).</li>



<li>Multiple independent background tasks.</li>
</ul>



<p>In this series, we moved from blocking the UI to using timers on the UI thread, then to actual background threads. Each approach solves a different problem.</p>



<h2 class="wp-block-heading" id="wrapping-up">Wrapping Up</h2>



<p>Threads are the heavy artillery of responsive design. They run independent of the UI and communicate safely via&nbsp;<code>UserInterfaceUpdate</code>. Once you grasp the boundary between thread code and UI code, you can build applications that never freeze, no matter how much work is happening behind the scenes.</p>



<p>See the&nbsp;<a href="https://documentation.xojo.com/api/language/threading/thread.html">Thread documentation</a>&nbsp;for more details on priority, stack size, and advanced patterns.</p>



<p>Until then, happy threading!</p>



<p><em>Gabriel is a digital marketing enthusiast who loves coding with Xojo to create cool software tools for any platform. He is always eager to learn and share new ideas!</em></p>



<ul class="wp-block-social-links has-normal-icon-size is-content-justification-center is-layout-flex wp-container-core-social-links-is-layout-16018d1d wp-block-social-links-is-layout-flex"><li class="wp-social-link wp-social-link-facebook  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.facebook.com/goxojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M12 2C6.5 2 2 6.5 2 12c0 5 3.7 9.1 8.4 9.9v-7H7.9V12h2.5V9.8c0-2.5 1.5-3.9 3.8-3.9 1.1 0 2.2.2 2.2.2v2.5h-1.3c-1.2 0-1.6.8-1.6 1.6V12h2.8l-.4 2.9h-2.3v7C18.3 21.1 22 17 22 12c0-5.5-4.5-10-10-10z"></path></svg><span class="wp-block-social-link-label screen-reader-text">Facebook</span></a></li>

<li class="wp-social-link wp-social-link-x  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://x.com/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M13.982 10.622 20.54 3h-1.554l-5.693 6.618L8.745 3H3.5l6.876 10.007L3.5 21h1.554l6.012-6.989L15.868 21h5.245l-7.131-10.378Zm-2.128 2.474-.697-.997-5.543-7.93H8l4.474 6.4.697.996 5.815 8.318h-2.387l-4.745-6.787Z" /></svg><span class="wp-block-social-link-label screen-reader-text">X</span></a></li>

<li class="wp-social-link wp-social-link-linkedin  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.linkedin.com/company/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M19.7,3H4.3C3.582,3,3,3.582,3,4.3v15.4C3,20.418,3.582,21,4.3,21h15.4c0.718,0,1.3-0.582,1.3-1.3V4.3 C21,3.582,20.418,3,19.7,3z M8.339,18.338H5.667v-8.59h2.672V18.338z M7.004,8.574c-0.857,0-1.549-0.694-1.549-1.548 c0-0.855,0.691-1.548,1.549-1.548c0.854,0,1.547,0.694,1.547,1.548C8.551,7.881,7.858,8.574,7.004,8.574z M18.339,18.338h-2.669 v-4.177c0-0.996-0.017-2.278-1.387-2.278c-1.389,0-1.601,1.086-1.601,2.206v4.249h-2.667v-8.59h2.559v1.174h0.037 c0.356-0.675,1.227-1.387,2.526-1.387c2.703,0,3.203,1.779,3.203,4.092V18.338z"></path></svg><span class="wp-block-social-link-label screen-reader-text">LinkedIn</span></a></li>

<li class="wp-social-link wp-social-link-github  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://github.com/topics/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M12,2C6.477,2,2,6.477,2,12c0,4.419,2.865,8.166,6.839,9.489c0.5,0.09,0.682-0.218,0.682-0.484 c0-0.236-0.009-0.866-0.014-1.699c-2.782,0.602-3.369-1.34-3.369-1.34c-0.455-1.157-1.11-1.465-1.11-1.465 c-0.909-0.62,0.069-0.608,0.069-0.608c1.004,0.071,1.532,1.03,1.532,1.03c0.891,1.529,2.341,1.089,2.91,0.833 c0.091-0.647,0.349-1.086,0.635-1.337c-2.22-0.251-4.555-1.111-4.555-4.943c0-1.091,0.39-1.984,1.03-2.682 C6.546,8.54,6.202,7.524,6.746,6.148c0,0,0.84-0.269,2.75,1.025C10.295,6.95,11.15,6.84,12,6.836 c0.85,0.004,1.705,0.114,2.504,0.336c1.909-1.294,2.748-1.025,2.748-1.025c0.546,1.376,0.202,2.394,0.1,2.646 c0.64,0.699,1.026,1.591,1.026,2.682c0,3.841-2.337,4.687-4.565,4.935c0.359,0.307,0.679,0.917,0.679,1.852 c0,1.335-0.012,2.415-0.012,2.741c0,0.269,0.18,0.579,0.688,0.481C19.138,20.161,22,16.416,22,12C22,6.477,17.523,2,12,2z"></path></svg><span class="wp-block-social-link-label screen-reader-text">GitHub</span></a></li>

<li class="wp-social-link wp-social-link-youtube  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.youtube.com/c/XojoInc" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M21.8,8.001c0,0-0.195-1.378-0.795-1.985c-0.76-0.797-1.613-0.801-2.004-0.847c-2.799-0.202-6.997-0.202-6.997-0.202 h-0.009c0,0-4.198,0-6.997,0.202C4.608,5.216,3.756,5.22,2.995,6.016C2.395,6.623,2.2,8.001,2.2,8.001S2,9.62,2,11.238v1.517 c0,1.618,0.2,3.237,0.2,3.237s0.195,1.378,0.795,1.985c0.761,0.797,1.76,0.771,2.205,0.855c1.6,0.153,6.8,0.201,6.8,0.201 s4.203-0.006,7.001-0.209c0.391-0.047,1.243-0.051,2.004-0.847c0.6-0.607,0.795-1.985,0.795-1.985s0.2-1.618,0.2-3.237v-1.517 C22,9.62,21.8,8.001,21.8,8.001z M9.935,14.594l-0.001-5.62l5.404,2.82L9.935,14.594z"></path></svg><span class="wp-block-social-link-label screen-reader-text">YouTube</span></a></li></ul>



<p class="has-text-align-center has-text-color has-link-color wp-elements-a0a2ac26ad214a49dac577734d259176" style="color:#84bd00"><a href="https://xojo.com/download/" target="_blank" rel="noreferrer noopener">Download Xojo</a></p>



<p><strong>Optimizing Code Series:</strong></p>



<ul class="wp-block-list">
<li><a href="https://blog.xojo.com/2025/11/20/optimizing-xojo-code-part-1-getting-started/" target="_blank" rel="noreferrer noopener">Optimizing Xojo Code, Part 1: Getting Started</a></li>



<li><a href="https://blog.xojo.com/2025/11/25/optimizing-xojo-code-part-2-using-a-timer-to-keep-the-ui-responsive/" target="_blank" rel="noreferrer noopener">Optimizing Xojo Code, Part 2: Using a Timer to Keep the UI Responsive</a></li>



<li><a href="https://blog.xojo.com/2026/01/14/optimizing-xojo-code-part-3-programmatic-timers-and-addhandler/" target="_blank" rel="noreferrer noopener">Optimizing Xojo Code, Part 3: Programmatic Timers and AddHandler</a></li>



<li><a href="https://blog.xojo.com/2026/02/02/optimizing-xojo-code-part-4-timer-calllater/" target="_blank" rel="noreferrer noopener">Optimizing Xojo Code, Part 4: Timer.CallLater</a></li>



<li><a href="https://blog.xojo.com/2026/03/02/optimizing-xojo-code-part-5-threads-and-userinterfaceupdate/" target="_blank" rel="noreferrer noopener">Optimizing Xojo Code, Part 5: Threads and UserInterfaceUpdate</a></li>
</ul>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Optimizing Xojo Code, Part 4: Timer.CallLater</title>
		<link>https://blog.xojo.com/2026/02/02/optimizing-xojo-code-part-4-timer-calllater/</link>
		
		<dc:creator><![CDATA[Gabriel Ludosanu]]></dc:creator>
		<pubDate>Mon, 02 Feb 2026 21:25:28 +0000</pubDate>
				<category><![CDATA[Fun]]></category>
		<category><![CDATA[General]]></category>
		<category><![CDATA[Learning]]></category>
		<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[CallLater]]></category>
		<category><![CDATA[CancelCallLater]]></category>
		<category><![CDATA[Developer Challenge]]></category>
		<category><![CDATA[Timers]]></category>
		<category><![CDATA[UI Responsiveness]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=15786</guid>

					<description><![CDATA[In&#160;Part 1&#160;of this series, we looked at a common but discouraged approach using a tight loop with&#160;DoEvents&#160;to keep the UI from freezing. In&#160;Part 2, we&#8230;]]></description>
										<content:encoded><![CDATA[
<p>In&nbsp;<a href="https://blog.xojo.com/2025/11/20/optimizing-xojo-code-part-1-getting-started/">Part 1</a>&nbsp;of this series, we looked at a common but discouraged approach using a tight loop with&nbsp;<code>DoEvents</code>&nbsp;to keep the UI from freezing. In&nbsp;<a href="https://blog.xojo.com/2025/11/25/optimizing-xojo-code-part-2-using-a-timer-to-keep-the-ui-responsive/">Part 2</a>, we explored a better alternative by replacing that loop with a Timer control dragged onto a Window. In&nbsp;<a href="https://blog.xojo.com/2026/01/14/optimizing-xojo-code-part-3-programmatic-timers-and-addhandler/">Part 3</a>, we advanced to creating Timers programmatically with&nbsp;<code>AddHandler</code>&nbsp;for use in classes and modules.</p>



<p>Now, for even simpler one-off or chained delayed tasks, Xojo offers&nbsp;<code>Timer.CallLater</code>: no Timer instance required.</p>



<h2 class="wp-block-heading" id="the-strategy-timercalllater">The Strategy: Timer.CallLater</h2>



<p><code>Timer.CallLater(milliseconds, AddressOf MethodName, arg As Variant)</code>&nbsp;schedules your method to run after the specified delay on the main UI thread. Pass data via the Variant parameter. To chain calls (like our countdown), re-call it from within the method. Use&nbsp;<code>Timer.CancelCallLater(AddressOf MethodName)</code>&nbsp;to abort pending calls.</p>



<p>For full details, see the&nbsp;<a href="https://documentation.xojo.com/api/language/timer.html" target="_blank" rel="noreferrer noopener">Timer documentation</a>.</p>



<h2 class="wp-block-heading" id="looking-at-the-code">Looking at the Code</h2>



<p>Prerequisites: Add a <code>StatusLabel</code> (DesktopLabel control) and a constant <code>kCountTo As Integer = 20000</code>.</p>



<p>Let&#8217;s look at how we implement this.</p>



<h3 class="wp-block-heading" id="the-setup-button-pressed">The Setup (Button Pressed)</h3>



<p>Place the following code in the&nbsp;<code>Pressed</code>&nbsp;event handler of a button control:</p>



<pre class="wp-block-code"><code>Sub Pressed()
  Timer.CancelCallLater(AddressOf UpdateProgress)
  
  StatusLabel.Text = "0"
  
  Timer.CallLater(100, AddressOf UpdateProgress, 100)
End Sub</code></pre>



<h3 class="wp-block-heading" id="the-handler-recursive-chain">The Handler (Recursive Chain)</h3>



<p>Create the following method that handles the recursive chain of delayed updates:</p>



<pre class="wp-block-code"><code>Sub UpdateProgress(elapsedMs As Variant)
  Var elapsed As Integer = elapsedMs.IntegerValue
  
  If elapsed &gt;= kCountTo Then

    StatusLabel.Text = "done"

  Else

    StatusLabel.Text = elapsed.ToString
    Timer.CallLater(100, AddressOf UpdateProgress, elapsed + 100)

  End If
End Sub</code></pre>



<p><strong>Crucial Note:</strong>&nbsp;The handler method must accept a&nbsp;<code>Variant</code>&nbsp;parameter to receive the argument passed to&nbsp;<code>CallLater</code>. Always use type-safe extraction like&nbsp;<code>.IntegerValue</code>.</p>



<h2 class="wp-block-heading" id="how-it-works">How It Works</h2>



<ol class="wp-block-list">
<li>Initial Schedule: The button cancels any pending calls and schedules the first <code>UpdateProgress</code> after 100ms, passing <code>100</code> as the elapsed time (just in case we like pressing a button multiple times quickly).</li>



<li>Recursion: Each call updates the UI and, if not finished, schedules the next one 100ms in the future with incremented elapsed time.</li>



<li>Automatic Management: No Timer properties or handlers to manage; Xojo handles scheduling and cleanup.</li>



<li>Cancellation: Ensures only one chain runs at a time.</li>
</ol>



<h2 class="wp-block-heading" id="wrapping-up">Wrapping Up</h2>



<p><code>Timer.CallLater</code>&nbsp;shines for delayed UI updates or chained tasks without the overhead of Timer objects. It&#8217;s concise, safe, and powerful for responsive apps.</p>



<p>In Part 5, we&#8217;ll tackle true background processing with&nbsp;<code>Threads</code>&nbsp;and&nbsp;<code>UserInterfaceUpdate</code>.</p>



<p>Until then, happy coding!</p>



<p><em>Gabriel is a digital marketing enthusiast who loves coding with Xojo to create cool software tools for any platform. He is always eager to learn and share new ideas!</em></p>



<ul class="wp-block-social-links has-normal-icon-size is-content-justification-center is-layout-flex wp-container-core-social-links-is-layout-16018d1d wp-block-social-links-is-layout-flex"><li class="wp-social-link wp-social-link-facebook  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.facebook.com/goxojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M12 2C6.5 2 2 6.5 2 12c0 5 3.7 9.1 8.4 9.9v-7H7.9V12h2.5V9.8c0-2.5 1.5-3.9 3.8-3.9 1.1 0 2.2.2 2.2.2v2.5h-1.3c-1.2 0-1.6.8-1.6 1.6V12h2.8l-.4 2.9h-2.3v7C18.3 21.1 22 17 22 12c0-5.5-4.5-10-10-10z"></path></svg><span class="wp-block-social-link-label screen-reader-text">Facebook</span></a></li>

<li class="wp-social-link wp-social-link-x  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://x.com/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M13.982 10.622 20.54 3h-1.554l-5.693 6.618L8.745 3H3.5l6.876 10.007L3.5 21h1.554l6.012-6.989L15.868 21h5.245l-7.131-10.378Zm-2.128 2.474-.697-.997-5.543-7.93H8l4.474 6.4.697.996 5.815 8.318h-2.387l-4.745-6.787Z" /></svg><span class="wp-block-social-link-label screen-reader-text">X</span></a></li>

<li class="wp-social-link wp-social-link-linkedin  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.linkedin.com/company/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M19.7,3H4.3C3.582,3,3,3.582,3,4.3v15.4C3,20.418,3.582,21,4.3,21h15.4c0.718,0,1.3-0.582,1.3-1.3V4.3 C21,3.582,20.418,3,19.7,3z M8.339,18.338H5.667v-8.59h2.672V18.338z M7.004,8.574c-0.857,0-1.549-0.694-1.549-1.548 c0-0.855,0.691-1.548,1.549-1.548c0.854,0,1.547,0.694,1.547,1.548C8.551,7.881,7.858,8.574,7.004,8.574z M18.339,18.338h-2.669 v-4.177c0-0.996-0.017-2.278-1.387-2.278c-1.389,0-1.601,1.086-1.601,2.206v4.249h-2.667v-8.59h2.559v1.174h0.037 c0.356-0.675,1.227-1.387,2.526-1.387c2.703,0,3.203,1.779,3.203,4.092V18.338z"></path></svg><span class="wp-block-social-link-label screen-reader-text">LinkedIn</span></a></li>

<li class="wp-social-link wp-social-link-github  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://github.com/topics/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M12,2C6.477,2,2,6.477,2,12c0,4.419,2.865,8.166,6.839,9.489c0.5,0.09,0.682-0.218,0.682-0.484 c0-0.236-0.009-0.866-0.014-1.699c-2.782,0.602-3.369-1.34-3.369-1.34c-0.455-1.157-1.11-1.465-1.11-1.465 c-0.909-0.62,0.069-0.608,0.069-0.608c1.004,0.071,1.532,1.03,1.532,1.03c0.891,1.529,2.341,1.089,2.91,0.833 c0.091-0.647,0.349-1.086,0.635-1.337c-2.22-0.251-4.555-1.111-4.555-4.943c0-1.091,0.39-1.984,1.03-2.682 C6.546,8.54,6.202,7.524,6.746,6.148c0,0,0.84-0.269,2.75,1.025C10.295,6.95,11.15,6.84,12,6.836 c0.85,0.004,1.705,0.114,2.504,0.336c1.909-1.294,2.748-1.025,2.748-1.025c0.546,1.376,0.202,2.394,0.1,2.646 c0.64,0.699,1.026,1.591,1.026,2.682c0,3.841-2.337,4.687-4.565,4.935c0.359,0.307,0.679,0.917,0.679,1.852 c0,1.335-0.012,2.415-0.012,2.741c0,0.269,0.18,0.579,0.688,0.481C19.138,20.161,22,16.416,22,12C22,6.477,17.523,2,12,2z"></path></svg><span class="wp-block-social-link-label screen-reader-text">GitHub</span></a></li>

<li class="wp-social-link wp-social-link-youtube  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.youtube.com/c/XojoInc" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M21.8,8.001c0,0-0.195-1.378-0.795-1.985c-0.76-0.797-1.613-0.801-2.004-0.847c-2.799-0.202-6.997-0.202-6.997-0.202 h-0.009c0,0-4.198,0-6.997,0.202C4.608,5.216,3.756,5.22,2.995,6.016C2.395,6.623,2.2,8.001,2.2,8.001S2,9.62,2,11.238v1.517 c0,1.618,0.2,3.237,0.2,3.237s0.195,1.378,0.795,1.985c0.761,0.797,1.76,0.771,2.205,0.855c1.6,0.153,6.8,0.201,6.8,0.201 s4.203-0.006,7.001-0.209c0.391-0.047,1.243-0.051,2.004-0.847c0.6-0.607,0.795-1.985,0.795-1.985s0.2-1.618,0.2-3.237v-1.517 C22,9.62,21.8,8.001,21.8,8.001z M9.935,14.594l-0.001-5.62l5.404,2.82L9.935,14.594z"></path></svg><span class="wp-block-social-link-label screen-reader-text">YouTube</span></a></li></ul>



<p class="has-text-align-center has-text-color has-link-color wp-elements-a0a2ac26ad214a49dac577734d259176" style="color:#84bd00"><a href="https://xojo.com/download/" target="_blank" rel="noreferrer noopener">Download Xojo</a></p>



<p><strong>Optimizing Code Series:</strong></p>



<ul class="wp-block-list">
<li><a href="https://blog.xojo.com/2025/11/20/optimizing-xojo-code-part-1-getting-started/" target="_blank" rel="noreferrer noopener">Optimizing Xojo Code, Part 1: Getting Started</a></li>



<li><a href="https://blog.xojo.com/2025/11/25/optimizing-xojo-code-part-2-using-a-timer-to-keep-the-ui-responsive/" target="_blank" rel="noreferrer noopener">Optimizing Xojo Code, Part 2: Using a Timer to Keep the UI Responsive</a></li>



<li><a href="https://blog.xojo.com/2026/01/14/optimizing-xojo-code-part-3-programmatic-timers-and-addhandler/" target="_blank" rel="noreferrer noopener">Optimizing Xojo Code, Part 3: Programmatic Timers and AddHandler</a></li>



<li><a href="https://blog.xojo.com/2026/02/02/optimizing-xojo-code-part-4-timer-calllater/" target="_blank" rel="noreferrer noopener">Optimizing Xojo Code, Part 4: Timer.CallLater</a></li>



<li><a href="https://blog.xojo.com/2026/03/02/optimizing-xojo-code-part-5-threads-and-userinterfaceupdate/" target="_blank" rel="noreferrer noopener">Optimizing Xojo Code, Part 5: Threads and UserInterfaceUpdate</a></li>
</ul>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Xojo + XAML + Goto = &#x1f525;</title>
		<link>https://blog.xojo.com/2026/01/22/xojo-xaml-goto/</link>
		
		<dc:creator><![CDATA[William Yu]]></dc:creator>
		<pubDate>Thu, 22 Jan 2026 20:50:59 +0000</pubDate>
				<category><![CDATA[Desktop]]></category>
		<category><![CDATA[Fun]]></category>
		<category><![CDATA[General]]></category>
		<category><![CDATA[Learning]]></category>
		<category><![CDATA[Tips]]></category>
		<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[Windows]]></category>
		<category><![CDATA[Animation]]></category>
		<category><![CDATA[DesktopXAMLContainer]]></category>
		<category><![CDATA[XAML]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=15790</guid>

					<description><![CDATA[For decades, Goto has been treated as a programming faux pas—something to avoid at all costs. Like most rules though, there are exceptions. The Goto&#8230;]]></description>
										<content:encoded><![CDATA[
<p>For decades, Goto has been treated as a programming faux pas—something to avoid at all costs. Like most rules though, there are exceptions. The Goto I’m talking about here is one of them… and it can quite literally light your app on fire—programmatically speaking.</p>



<p>One of the hidden gems in <a href="https://xojo.com/download/" target="_blank" rel="noreferrer noopener">Xojo 2025r3</a> is support for XAML transitions, which makes it possible to add lightweight animations to your UI without writing any custom animation code in Xojo. Instead, you define visual states in XAML and let the XAML engine handle the animation for you.</p>



<p>At a high level, the workflow looks like this:</p>



<ol class="wp-block-list">
<li>Define one or more&nbsp;<strong>VisualStates</strong>&nbsp;in XAML.</li>



<li>Attach transitions to those states (for example, moving or fading an element).</li>



<li>From Xojo code, switch between states using&nbsp;<code>Invoke("GotoState", ...)</code>.</li>
</ol>



<p><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f4a1.png" alt="💡" class="wp-smiley" style="height: 1em; max-height: 1em;" />&nbsp;<strong>Pro Tip</strong><br><code>DesktopXAMLContainer</code>&nbsp;subscribes to&nbsp;<code>Operator_Lookup</code>, so you don’t have to call&nbsp;<code>Invoke</code>&nbsp;directly. Instead of writing<code> XAMLContainer1.Invoke("GotoState", "WhichState")</code>, you can simply call <code>XAMLContainer1.GotoState("WhichState")</code>.</p>



<h3 class="wp-block-heading">Visual States in XAML</h3>



<p>A&nbsp;<em>VisualState</em>&nbsp;represents a named configuration of UI properties. When you transition from one state to another, XAML can automatically animate the change.</p>



<p>Below is a simple example that animates a fire emoji <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f525.png" alt="🔥" class="wp-smiley" style="height: 1em; max-height: 1em;" /> moving upward, similar to a candle flame flickering or burning upward.</p>



<h3 class="wp-block-heading">Example XAML</h3>



<p>This example uses a&nbsp;<code>TextBlock</code>&nbsp;to display the fire emoji and animates its vertical position with a&nbsp;<code>TranslateTransform</code>. Note that visual states must be defined on a control, so we attach them to a&nbsp;<code>UserControl</code>, allowing it to participate in&nbsp;<code>GotoState</code>&nbsp;transitions.</p>



<pre class="wp-block-preformatted">&lt;UserControl&gt;<br>  &lt;Grid&gt;<br>    &lt;VisualStateManager.VisualStateGroups&gt;<br>      &lt;VisualStateGroup Name="FlameStates"&gt;<br><br>        &lt;VisualState Name="Bottom"&gt;<br>          &lt;Storyboard&gt;<br>            &lt;DoubleAnimation<br>              Storyboard.TargetName="FlameTransform"<br>              Storyboard.TargetProperty="Y"<br>              To="40"<br>              Duration="0:0:1" /&gt;<br>          &lt;/Storyboard&gt;<br>        &lt;/VisualState&gt;<br><br>        &lt;VisualState Name="Top"&gt;<br>          &lt;Storyboard&gt;<br>            &lt;DoubleAnimation<br>              Storyboard.TargetName="FlameTransform"<br>              Storyboard.TargetProperty="Y"<br>              To="-100"<br>              Duration="0:0:1" /&gt;<br>          &lt;/Storyboard&gt;<br>        &lt;/VisualState&gt;<br><br>      &lt;/VisualStateGroup&gt;<br>    &lt;/VisualStateManager.VisualStateGroups&gt;<br><br>    &lt;TextBlock<br>      Text="<img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f525.png" alt="🔥" class="wp-smiley" style="height: 1em; max-height: 1em;" />"<br>      FontSize="32"<br>      HorizontalAlignment="Center"<br>      VerticalAlignment="Bottom"&gt;<br><br>      &lt;TextBlock.RenderTransform&gt;<br>        &lt;TranslateTransform Name="FlameTransform" /&gt;<br>      &lt;/TextBlock.RenderTransform&gt;<br><br>    &lt;/TextBlock&gt;<br>  &lt;/Grid&gt;<br>&lt;/UserControl&gt;</pre>



<p>In this XAML:</p>



<ul class="wp-block-list">
<li>The&nbsp;<code>VisualStateGroup</code>&nbsp;named&nbsp;<strong>FlameStates</strong>&nbsp;contains two states:
<ul class="wp-block-list">
<li><strong>Bottom</strong>&nbsp;– moves the emoji downward.</li>



<li><strong>Top</strong>&nbsp;– moves the emoji upward.</li>
</ul>
</li>



<li>The&nbsp;<code>DoubleAnimation</code>&nbsp;targets the&nbsp;<code>Y</code>&nbsp;property of a&nbsp;<code>TranslateTransform</code>.</li>



<li>The transition duration is handled entirely by XAML.</li>
</ul>



<h3 class="wp-block-heading">Triggering the Transition from Xojo</h3>



<p>Once the visual states are defined, switching between them from Xojo is straightforward. Assuming this XAML is hosted in a&nbsp;<code>XAMLContainer</code>&nbsp;named&nbsp;<code>XAMLContainer1</code>, you can trigger the animation like this:</p>



<pre class="wp-block-code"><code>XAMLContainer1.GotoState("Top")</code></pre>



<p>And to move it back down:</p>



<pre class="wp-block-code"><code>XAMLContainer1.GotoState("Bottom")</code></pre>



<h3 class="wp-block-heading">Why This Is Powerful</h3>



<p>What makes this feature especially useful is that:</p>



<ul class="wp-block-list">
<li>The animation logic stays in XAML, where it naturally belongs.</li>



<li>Xojo code remains clean and declarative—just tell the UI&nbsp;<em>which state</em>&nbsp;to go to.</li>



<li>More complex effects (opacity, scaling, rotation, easing functions) can be added without changing any Xojo code.</li>
</ul>



<p>Here&#8217;s a more interesting variation, where the flames drift upward rather than moving in a straight line:</p>



<pre class="wp-block-code"><code>&lt;UserControl&gt;
  &lt;Grid Width="160" Height="240"&gt;

    &lt;!-- Fire emoji 1 --&gt;
    &lt;TextBlock Name="Fire1"
           Text="&#x1f525;"
           FontSize="32"
           VerticalAlignment="Bottom"
           HorizontalAlignment="Center"&gt;
      &lt;TextBlock.RenderTransform&gt;
        &lt;TranslateTransform Name="Move1"/&gt;
      &lt;/TextBlock.RenderTransform&gt;
    &lt;/TextBlock&gt;

    &lt;!-- Fire emoji 2 --&gt;
    &lt;TextBlock Name="Fire2"
           Text="&#x1f525;"
           FontSize="26"
           VerticalAlignment="Bottom"
           HorizontalAlignment="Center"
           Margin="20,0,0,0"
           Opacity="0.8"&gt;
      &lt;TextBlock.RenderTransform&gt;
        &lt;TranslateTransform Name="Move2"/&gt;
      &lt;/TextBlock.RenderTransform&gt;
    &lt;/TextBlock&gt;

    &lt;!-- Fire emoji 3 --&gt;
    &lt;TextBlock Name="Fire3"
           Text="&#x1f525;"
           FontSize="22"
           VerticalAlignment="Bottom"
           HorizontalAlignment="Center"
           Margin="-20,0,0,0"
           Opacity="0.7"&gt;
      &lt;TextBlock.RenderTransform&gt;
        &lt;TranslateTransform Name="Move3"/&gt;
      &lt;/TextBlock.RenderTransform&gt;
    &lt;/TextBlock&gt;

    &lt;VisualStateManager.VisualStateGroups&gt;
      &lt;VisualStateGroup Name="FireStates"&gt;

        &lt;VisualState Name="Off"/&gt;

        &lt;VisualState Name="On"&gt;
          &lt;Storyboard RepeatBehavior="Forever"&gt;

            &lt;!-- Fire 1 --&gt;
            &lt;DoubleAnimation Storyboard.TargetName="Move1"
                     Storyboard.TargetProperty="Y"
                     From="0"
                     To="-180"
                     Duration="0:0:1.2"/&gt;

            &lt;DoubleAnimation Storyboard.TargetName="Move1"
                     Storyboard.TargetProperty="X"
                     From="0"
                     To="10"
                     Duration="0:0:0.6"
                     AutoReverse="True"/&gt;

            &lt;!-- Fire 2 --&gt;
            &lt;DoubleAnimation Storyboard.TargetName="Move2"
                     Storyboard.TargetProperty="Y"
                     From="0"
                     To="-160"
                     Duration="0:0:1.0"
                     BeginTime="0:0:0.3"/&gt;

            &lt;DoubleAnimation Storyboard.TargetName="Move2"
                     Storyboard.TargetProperty="X"
                     From="0"
                     To="-12"
                     Duration="0:0:0.5"
                     AutoReverse="True"/&gt;

            &lt;!-- Fire 3 --&gt;
            &lt;DoubleAnimation Storyboard.TargetName="Move3"
                     Storyboard.TargetProperty="Y"
                     From="0"
                     To="-140"
                     Duration="0:0:1.4"
                     BeginTime="0:0:0.15"/&gt;

            &lt;DoubleAnimation Storyboard.TargetName="Move3"
                     Storyboard.TargetProperty="X"
                     From="0"
                     To="8"
                     Duration="0:0:0.7"
                     AutoReverse="True"/&gt;

          &lt;/Storyboard&gt;
        &lt;/VisualState&gt;

      &lt;/VisualStateGroup&gt;
    &lt;/VisualStateManager.VisualStateGroups&gt;

  &lt;/Grid&gt;
&lt;/UserControl&gt;</code></pre>



<p>To light up the flames we&#8217;ll simply invoke the &#8220;On&#8221; state:</p>



<pre class="wp-block-code"><code>XAMLContainer1.GotoState("On")</code></pre>



<figure class="wp-block-video"><video height="720" style="aspect-ratio: 1280 / 720;" width="1280" controls loop src="https://blog.xojo.com/wp-content/uploads/2026/01/XAMLFire.mp4" playsinline></video></figure>



<p>For subtle UI polish—like animated indicators, highlights, or playful effects such as this candle flame—XAML transitions provide a surprisingly powerful new tool in Xojo.</p>



<p><em><em><em>William Yu grew up in Canada learning to program BASIC on a Vic-20. He is Xojo’s resident Windows and Linux engineer, among his many other skills. Some may say he has joined the dark side here in the USA, but he will always be a Canadian at heart.</em></em></em></p>



<ul class="wp-block-social-links has-normal-icon-size is-content-justification-center is-layout-flex wp-container-core-social-links-is-layout-16018d1d wp-block-social-links-is-layout-flex"><li class="wp-social-link wp-social-link-facebook  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.facebook.com/goxojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M12 2C6.5 2 2 6.5 2 12c0 5 3.7 9.1 8.4 9.9v-7H7.9V12h2.5V9.8c0-2.5 1.5-3.9 3.8-3.9 1.1 0 2.2.2 2.2.2v2.5h-1.3c-1.2 0-1.6.8-1.6 1.6V12h2.8l-.4 2.9h-2.3v7C18.3 21.1 22 17 22 12c0-5.5-4.5-10-10-10z"></path></svg><span class="wp-block-social-link-label screen-reader-text">Facebook</span></a></li>

<li class="wp-social-link wp-social-link-x  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://x.com/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M13.982 10.622 20.54 3h-1.554l-5.693 6.618L8.745 3H3.5l6.876 10.007L3.5 21h1.554l6.012-6.989L15.868 21h5.245l-7.131-10.378Zm-2.128 2.474-.697-.997-5.543-7.93H8l4.474 6.4.697.996 5.815 8.318h-2.387l-4.745-6.787Z" /></svg><span class="wp-block-social-link-label screen-reader-text">X</span></a></li>

<li class="wp-social-link wp-social-link-linkedin  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.linkedin.com/company/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M19.7,3H4.3C3.582,3,3,3.582,3,4.3v15.4C3,20.418,3.582,21,4.3,21h15.4c0.718,0,1.3-0.582,1.3-1.3V4.3 C21,3.582,20.418,3,19.7,3z M8.339,18.338H5.667v-8.59h2.672V18.338z M7.004,8.574c-0.857,0-1.549-0.694-1.549-1.548 c0-0.855,0.691-1.548,1.549-1.548c0.854,0,1.547,0.694,1.547,1.548C8.551,7.881,7.858,8.574,7.004,8.574z M18.339,18.338h-2.669 v-4.177c0-0.996-0.017-2.278-1.387-2.278c-1.389,0-1.601,1.086-1.601,2.206v4.249h-2.667v-8.59h2.559v1.174h0.037 c0.356-0.675,1.227-1.387,2.526-1.387c2.703,0,3.203,1.779,3.203,4.092V18.338z"></path></svg><span class="wp-block-social-link-label screen-reader-text">LinkedIn</span></a></li>

<li class="wp-social-link wp-social-link-github  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://github.com/topics/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M12,2C6.477,2,2,6.477,2,12c0,4.419,2.865,8.166,6.839,9.489c0.5,0.09,0.682-0.218,0.682-0.484 c0-0.236-0.009-0.866-0.014-1.699c-2.782,0.602-3.369-1.34-3.369-1.34c-0.455-1.157-1.11-1.465-1.11-1.465 c-0.909-0.62,0.069-0.608,0.069-0.608c1.004,0.071,1.532,1.03,1.532,1.03c0.891,1.529,2.341,1.089,2.91,0.833 c0.091-0.647,0.349-1.086,0.635-1.337c-2.22-0.251-4.555-1.111-4.555-4.943c0-1.091,0.39-1.984,1.03-2.682 C6.546,8.54,6.202,7.524,6.746,6.148c0,0,0.84-0.269,2.75,1.025C10.295,6.95,11.15,6.84,12,6.836 c0.85,0.004,1.705,0.114,2.504,0.336c1.909-1.294,2.748-1.025,2.748-1.025c0.546,1.376,0.202,2.394,0.1,2.646 c0.64,0.699,1.026,1.591,1.026,2.682c0,3.841-2.337,4.687-4.565,4.935c0.359,0.307,0.679,0.917,0.679,1.852 c0,1.335-0.012,2.415-0.012,2.741c0,0.269,0.18,0.579,0.688,0.481C19.138,20.161,22,16.416,22,12C22,6.477,17.523,2,12,2z"></path></svg><span class="wp-block-social-link-label screen-reader-text">GitHub</span></a></li>

<li class="wp-social-link wp-social-link-youtube  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.youtube.com/c/XojoInc" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M21.8,8.001c0,0-0.195-1.378-0.795-1.985c-0.76-0.797-1.613-0.801-2.004-0.847c-2.799-0.202-6.997-0.202-6.997-0.202 h-0.009c0,0-4.198,0-6.997,0.202C4.608,5.216,3.756,5.22,2.995,6.016C2.395,6.623,2.2,8.001,2.2,8.001S2,9.62,2,11.238v1.517 c0,1.618,0.2,3.237,0.2,3.237s0.195,1.378,0.795,1.985c0.761,0.797,1.76,0.771,2.205,0.855c1.6,0.153,6.8,0.201,6.8,0.201 s4.203-0.006,7.001-0.209c0.391-0.047,1.243-0.051,2.004-0.847c0.6-0.607,0.795-1.985,0.795-1.985s0.2-1.618,0.2-3.237v-1.517 C22,9.62,21.8,8.001,21.8,8.001z M9.935,14.594l-0.001-5.62l5.404,2.82L9.935,14.594z"></path></svg><span class="wp-block-social-link-label screen-reader-text">YouTube</span></a></li></ul>



<p class="has-text-align-center has-text-color has-link-color wp-elements-a0a2ac26ad214a49dac577734d259176" style="color:#84bd00"><a href="https://xojo.com/download/" target="_blank" rel="noreferrer noopener">Download Xojo</a></p>
]]></content:encoded>
					
		
		<enclosure url="https://blog.xojo.com/wp-content/uploads/2026/01/XAMLFire.mp4" length="177770" type="video/mp4" />

			</item>
		<item>
		<title>Optimizing Xojo Code, Part 3: Programmatic Timers and AddHandler</title>
		<link>https://blog.xojo.com/2026/01/14/optimizing-xojo-code-part-3-programmatic-timers-and-addhandler/</link>
		
		<dc:creator><![CDATA[Gabriel Ludosanu]]></dc:creator>
		<pubDate>Wed, 14 Jan 2026 16:27:11 +0000</pubDate>
				<category><![CDATA[Fun]]></category>
		<category><![CDATA[General]]></category>
		<category><![CDATA[Learning]]></category>
		<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[AddHandler]]></category>
		<category><![CDATA[Code Optimization]]></category>
		<category><![CDATA[Developer Challenge]]></category>
		<category><![CDATA[Timers]]></category>
		<category><![CDATA[UI Responsiveness]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=15768</guid>

					<description><![CDATA[In&#160;Part 1&#160;of this Optimizing Xojo Code series, we looked at a working but discouraged approach using a tight loop with&#160;DoEvents&#160;to keep the UI from freezing.&#8230;]]></description>
										<content:encoded><![CDATA[
<p>In&nbsp;<a href="https://blog.xojo.com/2025/11/20/optimizing-xojo-code-part-1-getting-started/">Part 1</a>&nbsp;of this Optimizing Xojo Code series, we looked at a working but discouraged approach using a tight loop with&nbsp;<code>DoEvents</code>&nbsp;to keep the UI from freezing. In&nbsp;<a href="https://blog.xojo.com/2025/11/25/optimizing-xojo-code-part-2-using-a-timer-to-keep-the-ui-responsive/">Part 2</a>, we explored a better alternative by replacing that loop with a Timer control dragged onto a DesktopWindow. This is a simple and effective solution that takes advantage of Xojo’s object-oriented nature.</p>



<p>But what if you need a timer inside a Class or a Module where you can&#8217;t drop a visual control?</p>



<h2 class="wp-block-heading" id="the-strategy-addhandler">The Strategy: AddHandler</h2>



<p>When you use a Timer control from the library, you double-click it to add an&nbsp;<code>Action</code>&nbsp;event. When we create a Timer in code, we don&#8217;t have a &#8220;code editor&#8221; for it in the same way. Instead, we use the&nbsp;<code>AddHandler</code>&nbsp;command to tell Xojo: &#8220;When this timer fires its Action event, run this specific method instead.&#8221;</p>



<h2 class="wp-block-heading" id="looking-at-the-code">Looking at the Code</h2>



<p>Let&#8217;s look at how we implement this. In our example project, we have a button that initializes our timer and a separate method to handle the &#8220;ticks.&#8221;</p>



<h3 class="wp-block-heading" id="the-setup-opening-the-gate">The Setup</h3>



<p>First, we define a property on our window (or class) to hold our timer:&nbsp;<code>mWaitTimer As Timer</code></p>



<p>Then, in the&nbsp;<strong>Pressed</strong>&nbsp;event of our button, we instantiate it:</p>



<pre class="wp-block-code"><code>Sub Pressed() Handles Pressed
  ' 1. Cleanup
  If mWaitTimer &lt;&gt; Nil Then
    mWaitTimer.RunMode = Timer.RunModes.Off
    mWaitTimer = Nil
  End If
  
  ' 2. Initialization
  mElapsedMs = 0
  StatusLabel.Text = "0"
  
  ' 3. Create the dynamic timer
  mWaitTimer = New Timer
  mWaitTimer.Period = 100 ' 100 ms tick
  mWaitTimer.RunMode = Timer.RunModes.Multiple
  
  ' 4. The Magic: Link the Action event to our WaitTick method
  AddHandler mWaitTimer.Action, AddressOf WaitTick
End Sub</code></pre>



<h3 class="wp-block-heading" id="the-handler-doing-the-work">The Handler (Doing the Work)</h3>



<p>Now, let&#8217;s create the method named&nbsp;<code>WaitTick</code>.&nbsp;<strong>Crucial Note:</strong>&nbsp;When using&nbsp;<code>AddHandler</code>&nbsp;for a Timer, the first parameter of your receiving method must be of the type&nbsp;<code>Timer</code>&nbsp;so it knows which object triggered it.</p>



<pre class="wp-block-code"><code>Sub WaitTick(t As Timer)
  mElapsedMs = mElapsedMs + t.Period
  
  If mElapsedMs &gt;= kCountTo Then
    ' Achievement unlocked! Stop the timer and clean up
    t.RunMode = Timer.RunModes.Off
    StatusLabel.Text = "done"
    
    ' It's good practice to remove the handler when done
    RemoveHandler t.Action, AddressOf WaitTick
  Else
    StatusLabel.Text = mElapsedMs.ToString
  End If
End Sub</code></pre>



<h2 class="wp-block-heading" id="how-it-works">How It Works</h2>



<ol class="wp-block-list">
<li><strong>New Timer:</strong>&nbsp;We create a new instance of the Timer class in memory.</li>



<li><strong>AddHandler:</strong>&nbsp;This command connects the&nbsp;<code>Action</code>&nbsp;event of our new timer to the&nbsp;<code>WaitTick</code>&nbsp;method. The&nbsp;<code>AddressOf</code>&nbsp;operator tells Xojo the memory location of the code we want to run.</li>



<li><strong>Passing the Object:</strong>&nbsp;Because&nbsp;<code>WaitTick</code>&nbsp;receives&nbsp;<code>t As Timer</code>&nbsp;as a parameter, you can actually use the same handler for multiple different timers and knows exactly which one is calling for attention.</li>
</ol>



<h2 class="wp-block-heading" id="wrapping-up">Wrapping Up</h2>



<p>By moving your Timers into code, you take a significant step toward writing more modular Xojo applications. You’ve moved the logic from &#8220;Global UI state&#8221; into &#8220;Managed Code execution.&#8221;</p>



<p>In the upcoming Part 4, we’ll look at a shortcut that makes one-off background tasks a breeze:&nbsp;<code>Timer.CallLater</code>.</p>



<p>Until then, happy coding and don&#8217;t forget to add your own solution in the <a href="https://forum.xojo.com/" data-type="link" data-id="https://forum.xojo.com/" target="_blank" rel="noreferrer noopener">Xojo Forum</a>!</p>



<p><em>Gabriel is a digital marketing enthusiast who loves coding with Xojo to create cool software tools for any platform. He is always eager to learn and share new ideas!</em></p>



<ul class="wp-block-social-links has-normal-icon-size is-content-justification-center is-layout-flex wp-container-core-social-links-is-layout-16018d1d wp-block-social-links-is-layout-flex"><li class="wp-social-link wp-social-link-facebook  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.facebook.com/goxojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M12 2C6.5 2 2 6.5 2 12c0 5 3.7 9.1 8.4 9.9v-7H7.9V12h2.5V9.8c0-2.5 1.5-3.9 3.8-3.9 1.1 0 2.2.2 2.2.2v2.5h-1.3c-1.2 0-1.6.8-1.6 1.6V12h2.8l-.4 2.9h-2.3v7C18.3 21.1 22 17 22 12c0-5.5-4.5-10-10-10z"></path></svg><span class="wp-block-social-link-label screen-reader-text">Facebook</span></a></li>

<li class="wp-social-link wp-social-link-x  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://x.com/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M13.982 10.622 20.54 3h-1.554l-5.693 6.618L8.745 3H3.5l6.876 10.007L3.5 21h1.554l6.012-6.989L15.868 21h5.245l-7.131-10.378Zm-2.128 2.474-.697-.997-5.543-7.93H8l4.474 6.4.697.996 5.815 8.318h-2.387l-4.745-6.787Z" /></svg><span class="wp-block-social-link-label screen-reader-text">X</span></a></li>

<li class="wp-social-link wp-social-link-linkedin  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.linkedin.com/company/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M19.7,3H4.3C3.582,3,3,3.582,3,4.3v15.4C3,20.418,3.582,21,4.3,21h15.4c0.718,0,1.3-0.582,1.3-1.3V4.3 C21,3.582,20.418,3,19.7,3z M8.339,18.338H5.667v-8.59h2.672V18.338z M7.004,8.574c-0.857,0-1.549-0.694-1.549-1.548 c0-0.855,0.691-1.548,1.549-1.548c0.854,0,1.547,0.694,1.547,1.548C8.551,7.881,7.858,8.574,7.004,8.574z M18.339,18.338h-2.669 v-4.177c0-0.996-0.017-2.278-1.387-2.278c-1.389,0-1.601,1.086-1.601,2.206v4.249h-2.667v-8.59h2.559v1.174h0.037 c0.356-0.675,1.227-1.387,2.526-1.387c2.703,0,3.203,1.779,3.203,4.092V18.338z"></path></svg><span class="wp-block-social-link-label screen-reader-text">LinkedIn</span></a></li>

<li class="wp-social-link wp-social-link-github  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://github.com/topics/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M12,2C6.477,2,2,6.477,2,12c0,4.419,2.865,8.166,6.839,9.489c0.5,0.09,0.682-0.218,0.682-0.484 c0-0.236-0.009-0.866-0.014-1.699c-2.782,0.602-3.369-1.34-3.369-1.34c-0.455-1.157-1.11-1.465-1.11-1.465 c-0.909-0.62,0.069-0.608,0.069-0.608c1.004,0.071,1.532,1.03,1.532,1.03c0.891,1.529,2.341,1.089,2.91,0.833 c0.091-0.647,0.349-1.086,0.635-1.337c-2.22-0.251-4.555-1.111-4.555-4.943c0-1.091,0.39-1.984,1.03-2.682 C6.546,8.54,6.202,7.524,6.746,6.148c0,0,0.84-0.269,2.75,1.025C10.295,6.95,11.15,6.84,12,6.836 c0.85,0.004,1.705,0.114,2.504,0.336c1.909-1.294,2.748-1.025,2.748-1.025c0.546,1.376,0.202,2.394,0.1,2.646 c0.64,0.699,1.026,1.591,1.026,2.682c0,3.841-2.337,4.687-4.565,4.935c0.359,0.307,0.679,0.917,0.679,1.852 c0,1.335-0.012,2.415-0.012,2.741c0,0.269,0.18,0.579,0.688,0.481C19.138,20.161,22,16.416,22,12C22,6.477,17.523,2,12,2z"></path></svg><span class="wp-block-social-link-label screen-reader-text">GitHub</span></a></li>

<li class="wp-social-link wp-social-link-youtube  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.youtube.com/c/XojoInc" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M21.8,8.001c0,0-0.195-1.378-0.795-1.985c-0.76-0.797-1.613-0.801-2.004-0.847c-2.799-0.202-6.997-0.202-6.997-0.202 h-0.009c0,0-4.198,0-6.997,0.202C4.608,5.216,3.756,5.22,2.995,6.016C2.395,6.623,2.2,8.001,2.2,8.001S2,9.62,2,11.238v1.517 c0,1.618,0.2,3.237,0.2,3.237s0.195,1.378,0.795,1.985c0.761,0.797,1.76,0.771,2.205,0.855c1.6,0.153,6.8,0.201,6.8,0.201 s4.203-0.006,7.001-0.209c0.391-0.047,1.243-0.051,2.004-0.847c0.6-0.607,0.795-1.985,0.795-1.985s0.2-1.618,0.2-3.237v-1.517 C22,9.62,21.8,8.001,21.8,8.001z M9.935,14.594l-0.001-5.62l5.404,2.82L9.935,14.594z"></path></svg><span class="wp-block-social-link-label screen-reader-text">YouTube</span></a></li></ul>



<p class="has-text-align-center has-text-color has-link-color wp-elements-a0a2ac26ad214a49dac577734d259176" style="color:#84bd00"><a href="https://xojo.com/download/" target="_blank" rel="noreferrer noopener">Download Xojo</a></p>



<p><strong>Optimizing Code Series:</strong></p>



<ul class="wp-block-list">
<li><a href="https://blog.xojo.com/2025/11/20/optimizing-xojo-code-part-1-getting-started/" target="_blank" rel="noreferrer noopener">Optimizing Xojo Code, Part 1: Getting Started</a></li>



<li><a href="https://blog.xojo.com/2025/11/25/optimizing-xojo-code-part-2-using-a-timer-to-keep-the-ui-responsive/" target="_blank" rel="noreferrer noopener">Optimizing Xojo Code, Part 2: Using a Timer to Keep the UI Responsive</a></li>



<li><a href="https://blog.xojo.com/2026/01/14/optimizing-xojo-code-part-3-programmatic-timers-and-addhandler/" target="_blank" rel="noreferrer noopener">Optimizing Xojo Code, Part 3: Programmatic Timers and AddHandler</a></li>



<li><a href="https://blog.xojo.com/2026/02/02/optimizing-xojo-code-part-4-timer-calllater/" target="_blank" rel="noreferrer noopener">Optimizing Xojo Code, Part 4: Timer.CallLater</a></li>



<li><a href="https://blog.xojo.com/2026/03/02/optimizing-xojo-code-part-5-threads-and-userinterfaceupdate/" target="_blank" rel="noreferrer noopener">Optimizing Xojo Code, Part 5: Threads and UserInterfaceUpdate</a></li>
</ul>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>When Doing More Is Faster: A Curious Xojo Performance Test</title>
		<link>https://blog.xojo.com/2026/01/05/when-doing-more-is-faster-a-curious-xojo-performance-test/</link>
		
		<dc:creator><![CDATA[Geoff Perlman]]></dc:creator>
		<pubDate>Mon, 05 Jan 2026 20:45:13 +0000</pubDate>
				<category><![CDATA[General]]></category>
		<category><![CDATA[ARM]]></category>
		<category><![CDATA[ARM64]]></category>
		<category><![CDATA[Performance]]></category>
		<category><![CDATA[Performance Tuning]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=15751</guid>

					<description><![CDATA[I ran across something recently that had me truly scratching my head. My goal was to measure how much extra time it would take for&#8230;]]></description>
										<content:encoded><![CDATA[
<p>I ran across something recently that had me truly scratching my head. My goal was to measure how much extra time it would take for some additional functionality I wished to add to a project. The initial code was performing a query on a table in a database and then looping through the RowSet returned to populate five columns of a DesktopListBox with each row from the RowSet. I created a new project to test a simple form of the code. I added some code to measure the performance in microseconds. Next, I created an identical test except this time there was an extra line of code inside the loop that assigned a DatabaseRow from the RowSet to the row&#8217;s RowTag. This was the extra functionality I wanted. The tests would show me the cost of this functionality in terms of performance.</p>



<h2 class="wp-block-heading">Test 1</h2>



<pre class="wp-block-code"><code>Var rs As rowset = SQLiteDatabase1.SelectSQL("SELECT invoices.invoiceno, invoices.invoicedate, invoices.invoiceamount, customers.firstname, customers.lastname FROM Invoices JOIN Customers ON invoices.customerid = customers.id")
Results1.RemoveAllRows
Var grandTotal As Integer
Var totalIterations As Integer  = 10
For i As Integer = 1 To totalIterations
  Var start As Integer = System.Microseconds
  For Each row As databaserow In rs
    ListBox1.AddRow(rs.Column("InvoiceNo"), rs.Column("lastname"), rs.Column("firstname"), rs.Column("InvoiceDate"), rs.Column("InvoiceAmount"))
  Next
  Var stop As Integer = System.Microseconds
  Var total As Integer = stop - start
  grandTotal = grandTotal + total
  Results1.AddRow("Test " + i.ToString + ": " + total.ToString)
Next
Var avg As Integer = grandTotal / totalIterations
results1.AddRow("Average: " + avg.ToString)</code></pre>



<h2 class="wp-block-heading">Test 2</h2>



<pre class="wp-block-code"><code>Var rs As rowset = SQLiteDatabase1.SelectSQL("SELECT invoices.invoiceno, invoices.invoicedate, invoices.invoiceamount, customers.firstname, customers.lastname FROM Invoices JOIN Customers ON invoices.customerid = customers.id")
Results2.RemoveAllRows
Var grandTotal As Integer
Var totalIterations As Integer  = 10
For i As Integer = 1 To totalIterations
  Var start As Integer = System.Microseconds
  For Each row As databaserow In rs
    ListBox1.AddRow(rs.Column("InvoiceNo"), rs.Column("lastname"), rs.Column("firstname"), rs.Column("InvoiceDate"), rs.Column("InvoiceAmount"))
    <strong>ListBox1.RowTagAt(ListBox1.LastAddedRowIndex) = row</strong>
  Next
  Var stop As Integer = System.Microseconds
  Var total As Integer = stop - start
  grandTotal = grandTotal + total
  Results2.AddRow("Test " + i.ToString + ": " + total.ToString)
Next
Var avg As Integer = grandTotal / totalIterations
results2.AddRow("Average: " + avg.ToString)</code></pre>



<p>I assumed the second test would take longer since it&#8217;s doing the extra step of assigning the row to the RowTag property. However, when I ran the test, something curious occurred. The second test, rather than taking more time to complete, took <em>less</em>. This made no sense to me. It&#8217;s doing <em>more</em> so it should take longer. It&#8217;s not logical that asking it to do more would result in the task taking less time. After examining my code, I could not find any issues with it.</p>



<p>I modified the code to run each test 10 times then compute the average of all 10 tests. Depending on the run, the average time for Test 2 was nearly always shorter. Occasionally the average for Test 1 would be shorter than Test 2 but rarely. In fact, on my M4-based MacBook Pro, Test 2&#8217;s average was, in most cases, anywhere from 5% to 25% faster than Test 1. Next I tested it on an M1-based MacBook Pro with similar results. Then I tested it on an x86-based PC running Windows 11. This time Test 2 was slightly slower than Test 1 as I had been expecting from the beginning. Last but not least, I tested on Windows 11 running via Parallels on my MacBook Pro, compiling for ARM-64. In this test, Test 2 was indeed faster. I tried running these tests by changing the order (Test 1 then Test 2 followed by Test 2 then Test 1) and by quitting between runs. None of that seemed to matter.</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="693" src="https://blog.xojo.com/wp-content/uploads/2026/01/CleanShot-2026-01-05-at-13.37.10@2x-1024x693.png" alt="" class="wp-image-15752" srcset="https://blog.xojo.com/wp-content/uploads/2026/01/CleanShot-2026-01-05-at-13.37.10@2x-1024x693.png 1024w, https://blog.xojo.com/wp-content/uploads/2026/01/CleanShot-2026-01-05-at-13.37.10@2x-300x203.png 300w, https://blog.xojo.com/wp-content/uploads/2026/01/CleanShot-2026-01-05-at-13.37.10@2x-768x520.png 768w, https://blog.xojo.com/wp-content/uploads/2026/01/CleanShot-2026-01-05-at-13.37.10@2x-1536x1040.png 1536w, https://blog.xojo.com/wp-content/uploads/2026/01/CleanShot-2026-01-05-at-13.37.10@2x.png 1628w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="693" src="https://blog.xojo.com/wp-content/uploads/2026/01/CleanShot-2026-01-05-at-13.37.17@2x-1024x693.png" alt="" class="wp-image-15753" srcset="https://blog.xojo.com/wp-content/uploads/2026/01/CleanShot-2026-01-05-at-13.37.17@2x-1024x693.png 1024w, https://blog.xojo.com/wp-content/uploads/2026/01/CleanShot-2026-01-05-at-13.37.17@2x-300x203.png 300w, https://blog.xojo.com/wp-content/uploads/2026/01/CleanShot-2026-01-05-at-13.37.17@2x-768x520.png 768w, https://blog.xojo.com/wp-content/uploads/2026/01/CleanShot-2026-01-05-at-13.37.17@2x-1536x1040.png 1536w, https://blog.xojo.com/wp-content/uploads/2026/01/CleanShot-2026-01-05-at-13.37.17@2x.png 1628w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<p>The difference appears to be ARM. It could be the compiler or the CPU. Our Director of Engineering, Travis Hill, suspects that perhaps something like the branch predictor in the CPU is hopping a <em>tiny</em> bit faster because of the extra assignment and thus can better predict the next operation with the For Each loop. That could be. The timing is in microseconds so the difference is so small that for my purposes, it doesn&#8217;t matter. However, that it&#8217;s faster to do more work in this case is fascinating and unexpected.</p>



<p>In any case, it&#8217;s interesting to see code behave in a way that is so counterintuitive. Asking the method to do more, at least on ARM-based machines, caused the method to take less time.</p>



<p><em>Geoff Perlman is the Founder and CEO of Xojo. When he’s not leading the Xojo team he can be found playing drums in Austin, Texas and spending time with his family.</em></p>



<ul class="wp-block-social-links has-normal-icon-size is-content-justification-center is-layout-flex wp-container-core-social-links-is-layout-16018d1d wp-block-social-links-is-layout-flex"><li class="wp-social-link wp-social-link-facebook  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.facebook.com/goxojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M12 2C6.5 2 2 6.5 2 12c0 5 3.7 9.1 8.4 9.9v-7H7.9V12h2.5V9.8c0-2.5 1.5-3.9 3.8-3.9 1.1 0 2.2.2 2.2.2v2.5h-1.3c-1.2 0-1.6.8-1.6 1.6V12h2.8l-.4 2.9h-2.3v7C18.3 21.1 22 17 22 12c0-5.5-4.5-10-10-10z"></path></svg><span class="wp-block-social-link-label screen-reader-text">Facebook</span></a></li>

<li class="wp-social-link wp-social-link-x  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://x.com/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M13.982 10.622 20.54 3h-1.554l-5.693 6.618L8.745 3H3.5l6.876 10.007L3.5 21h1.554l6.012-6.989L15.868 21h5.245l-7.131-10.378Zm-2.128 2.474-.697-.997-5.543-7.93H8l4.474 6.4.697.996 5.815 8.318h-2.387l-4.745-6.787Z" /></svg><span class="wp-block-social-link-label screen-reader-text">X</span></a></li>

<li class="wp-social-link wp-social-link-linkedin  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.linkedin.com/company/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M19.7,3H4.3C3.582,3,3,3.582,3,4.3v15.4C3,20.418,3.582,21,4.3,21h15.4c0.718,0,1.3-0.582,1.3-1.3V4.3 C21,3.582,20.418,3,19.7,3z M8.339,18.338H5.667v-8.59h2.672V18.338z M7.004,8.574c-0.857,0-1.549-0.694-1.549-1.548 c0-0.855,0.691-1.548,1.549-1.548c0.854,0,1.547,0.694,1.547,1.548C8.551,7.881,7.858,8.574,7.004,8.574z M18.339,18.338h-2.669 v-4.177c0-0.996-0.017-2.278-1.387-2.278c-1.389,0-1.601,1.086-1.601,2.206v4.249h-2.667v-8.59h2.559v1.174h0.037 c0.356-0.675,1.227-1.387,2.526-1.387c2.703,0,3.203,1.779,3.203,4.092V18.338z"></path></svg><span class="wp-block-social-link-label screen-reader-text">LinkedIn</span></a></li>

<li class="wp-social-link wp-social-link-github  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://github.com/topics/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M12,2C6.477,2,2,6.477,2,12c0,4.419,2.865,8.166,6.839,9.489c0.5,0.09,0.682-0.218,0.682-0.484 c0-0.236-0.009-0.866-0.014-1.699c-2.782,0.602-3.369-1.34-3.369-1.34c-0.455-1.157-1.11-1.465-1.11-1.465 c-0.909-0.62,0.069-0.608,0.069-0.608c1.004,0.071,1.532,1.03,1.532,1.03c0.891,1.529,2.341,1.089,2.91,0.833 c0.091-0.647,0.349-1.086,0.635-1.337c-2.22-0.251-4.555-1.111-4.555-4.943c0-1.091,0.39-1.984,1.03-2.682 C6.546,8.54,6.202,7.524,6.746,6.148c0,0,0.84-0.269,2.75,1.025C10.295,6.95,11.15,6.84,12,6.836 c0.85,0.004,1.705,0.114,2.504,0.336c1.909-1.294,2.748-1.025,2.748-1.025c0.546,1.376,0.202,2.394,0.1,2.646 c0.64,0.699,1.026,1.591,1.026,2.682c0,3.841-2.337,4.687-4.565,4.935c0.359,0.307,0.679,0.917,0.679,1.852 c0,1.335-0.012,2.415-0.012,2.741c0,0.269,0.18,0.579,0.688,0.481C19.138,20.161,22,16.416,22,12C22,6.477,17.523,2,12,2z"></path></svg><span class="wp-block-social-link-label screen-reader-text">GitHub</span></a></li>

<li class="wp-social-link wp-social-link-youtube  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.youtube.com/c/XojoInc" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M21.8,8.001c0,0-0.195-1.378-0.795-1.985c-0.76-0.797-1.613-0.801-2.004-0.847c-2.799-0.202-6.997-0.202-6.997-0.202 h-0.009c0,0-4.198,0-6.997,0.202C4.608,5.216,3.756,5.22,2.995,6.016C2.395,6.623,2.2,8.001,2.2,8.001S2,9.62,2,11.238v1.517 c0,1.618,0.2,3.237,0.2,3.237s0.195,1.378,0.795,1.985c0.761,0.797,1.76,0.771,2.205,0.855c1.6,0.153,6.8,0.201,6.8,0.201 s4.203-0.006,7.001-0.209c0.391-0.047,1.243-0.051,2.004-0.847c0.6-0.607,0.795-1.985,0.795-1.985s0.2-1.618,0.2-3.237v-1.517 C22,9.62,21.8,8.001,21.8,8.001z M9.935,14.594l-0.001-5.62l5.404,2.82L9.935,14.594z"></path></svg><span class="wp-block-social-link-label screen-reader-text">YouTube</span></a></li></ul>



<p class="has-text-align-center has-text-color has-link-color wp-elements-a0a2ac26ad214a49dac577734d259176" style="color:#84bd00"><a href="https://xojo.com/download/" target="_blank" rel="noreferrer noopener">Download Xojo</a></p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Introducing Jade, the Xojo AI Assistant</title>
		<link>https://blog.xojo.com/2025/12/09/introducing-jade-the-xojo-ai-assistant/</link>
		
		<dc:creator><![CDATA[Paul Lefebvre]]></dc:creator>
		<pubDate>Tue, 09 Dec 2025 16:31:26 +0000</pubDate>
				<category><![CDATA[General]]></category>
		<category><![CDATA[Tips]]></category>
		<category><![CDATA[2025r3]]></category>
		<category><![CDATA[AI]]></category>
		<category><![CDATA[AI Code Generation]]></category>
		<category><![CDATA[Beginner Tips]]></category>
		<category><![CDATA[Development]]></category>
		<category><![CDATA[Jade]]></category>
		<category><![CDATA[Xojo Programming Language]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=15548</guid>

					<description><![CDATA[With Xojo 2025 Release 3, we are introducing Jade, an AI assistant for Xojo. This initial version is primarily for asking general Xojo-related questions and&#8230;]]></description>
										<content:encoded><![CDATA[
<p>With Xojo 2025 Release 3, we are introducing Jade, an AI assistant for Xojo. This initial version is primarily for asking general Xojo-related questions and can be used as an alternative to the documentation.</p>



<h2 class="wp-block-heading">Getting Started</h2>



<p>Jade uses Anthropic Claude as its engine, so before using Jade, you first need to sign up for an Anthropic API key to access Claude. You can do this from the <a href="https://console.anthropic.com" target="_blank" rel="noreferrer noopener">Anthropic Claude Console</a>.</p>



<p>From there you can create your account. After you&#8217;ve done that, you will want to get an API key to use with Xojo. Click on the &#8220;API keys&#8221; tab to see existing keys and create new ones. Click the &#8220;Create Key&#8221; button to generate a new key. In the dialog, give it a name to indicate its purpose.</p>



<figure class="wp-block-image size-full is-resized"><img loading="lazy" decoding="async" width="920" height="666" src="https://blog.xojo.com/wp-content/uploads/2025/11/Create-in-Workspace-®.png" alt="" class="wp-image-15551" style="width:381px;height:auto" srcset="https://blog.xojo.com/wp-content/uploads/2025/11/Create-in-Workspace-®.png 920w, https://blog.xojo.com/wp-content/uploads/2025/11/Create-in-Workspace-®-300x217.png 300w, https://blog.xojo.com/wp-content/uploads/2025/11/Create-in-Workspace-®-768x556.png 768w" sizes="auto, (max-width: 920px) 100vw, 920px" /></figure>



<p>When you click Add, the actual key will be shown. Copy it to the clipboard.</p>



<figure class="wp-block-image size-full is-resized"><img loading="lazy" decoding="async" width="922" height="658" src="https://blog.xojo.com/wp-content/uploads/2025/11/Keep-a-record-of-the-key-below.-You-wont-be-able-to-view-it.png" alt="" class="wp-image-15552" style="width:390px;height:auto" srcset="https://blog.xojo.com/wp-content/uploads/2025/11/Keep-a-record-of-the-key-below.-You-wont-be-able-to-view-it.png 922w, https://blog.xojo.com/wp-content/uploads/2025/11/Keep-a-record-of-the-key-below.-You-wont-be-able-to-view-it-300x214.png 300w, https://blog.xojo.com/wp-content/uploads/2025/11/Keep-a-record-of-the-key-below.-You-wont-be-able-to-view-it-768x548.png 768w" sizes="auto, (max-width: 922px) 100vw, 922px" /></figure>



<p>Note that you cannot see the key again after closing that dialog, but you can always create a new key at any time.</p>



<p>Now go to Xojo Settings and in the General tab, paste it into the &#8220;Anthropic API Key&#8221; field.</p>



<figure class="wp-block-image size-large is-resized"><img loading="lazy" decoding="async" width="1024" height="748" src="https://blog.xojo.com/wp-content/uploads/2025/11/4E41D4E3-6D1F-494E-B830-8FB73DC944FB-1024x748.jpeg" alt="" class="wp-image-15559" style="width:670px;height:auto" srcset="https://blog.xojo.com/wp-content/uploads/2025/11/4E41D4E3-6D1F-494E-B830-8FB73DC944FB-1024x748.jpeg 1024w, https://blog.xojo.com/wp-content/uploads/2025/11/4E41D4E3-6D1F-494E-B830-8FB73DC944FB-300x219.jpeg 300w, https://blog.xojo.com/wp-content/uploads/2025/11/4E41D4E3-6D1F-494E-B830-8FB73DC944FB-768x561.jpeg 768w, https://blog.xojo.com/wp-content/uploads/2025/11/4E41D4E3-6D1F-494E-B830-8FB73DC944FB-1536x1122.jpeg 1536w, https://blog.xojo.com/wp-content/uploads/2025/11/4E41D4E3-6D1F-494E-B830-8FB73DC944FB.jpeg 1624w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<p>Go back to the Claude Console and click on the Billing tab to buy credits. Interacting with Jade requires credits. The amount of credits used depends on the complexity of your interactions. Until you get used to Jade and credit usage, you’ll probably want to start with a small amount, like $5, and disable auto-reload.</p>



<figure class="wp-block-image size-large is-resized"><img loading="lazy" decoding="async" width="1024" height="302" src="https://blog.xojo.com/wp-content/uploads/2025/11/CleanShot-2025-11-24-at-14.19.55@2x-1024x302.png" alt="" class="wp-image-15560" style="width:625px;height:auto" srcset="https://blog.xojo.com/wp-content/uploads/2025/11/CleanShot-2025-11-24-at-14.19.55@2x-1024x302.png 1024w, https://blog.xojo.com/wp-content/uploads/2025/11/CleanShot-2025-11-24-at-14.19.55@2x-300x88.png 300w, https://blog.xojo.com/wp-content/uploads/2025/11/CleanShot-2025-11-24-at-14.19.55@2x-768x226.png 768w, https://blog.xojo.com/wp-content/uploads/2025/11/CleanShot-2025-11-24-at-14.19.55@2x-1536x453.png 1536w, https://blog.xojo.com/wp-content/uploads/2025/11/CleanShot-2025-11-24-at-14.19.55@2x-2048x604.png 2048w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<h2 class="wp-block-heading">Using Jade</h2>


<div class="wp-block-image">
<figure class="alignright size-full"><img loading="lazy" decoding="async" width="48" height="48" src="https://blog.xojo.com/wp-content/uploads/2025/11/Assistant@3x.png" alt="" class="wp-image-15556"/></figure>
</div>


<p>To use Jade, select Help-&gt;Ask Jade or click the Ask Jade button in the toolbar. You’ll get some short introductory text. Note: Using Jade requires an internet connection.</p>



<figure class="wp-block-image size-large is-resized"><img loading="lazy" decoding="async" width="1024" height="982" src="https://blog.xojo.com/wp-content/uploads/2025/11/DF74EF37-BA6B-4A56-B933-0339A00359A2-1024x982.jpeg" alt="" class="wp-image-15558" style="width:668px;height:auto" srcset="https://blog.xojo.com/wp-content/uploads/2025/11/DF74EF37-BA6B-4A56-B933-0339A00359A2-1024x982.jpeg 1024w, https://blog.xojo.com/wp-content/uploads/2025/11/DF74EF37-BA6B-4A56-B933-0339A00359A2-300x288.jpeg 300w, https://blog.xojo.com/wp-content/uploads/2025/11/DF74EF37-BA6B-4A56-B933-0339A00359A2-768x736.jpeg 768w, https://blog.xojo.com/wp-content/uploads/2025/11/DF74EF37-BA6B-4A56-B933-0339A00359A2-1536x1473.jpeg 1536w, https://blog.xojo.com/wp-content/uploads/2025/11/DF74EF37-BA6B-4A56-B933-0339A00359A2.jpeg 2044w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<p>You interact with Jade similarly to a chat app by typing prompts in the conversation area (bottom section) and pressing Send. Jade will think for a moment and then display its response.</p>



<figure class="wp-block-image size-large is-resized"><img loading="lazy" decoding="async" width="1024" height="982" src="https://blog.xojo.com/wp-content/uploads/2025/11/DFF0253D-0333-46DD-9780-8A0322F652C0-1024x982.jpeg" alt="" class="wp-image-15562" style="width:680px;height:auto" srcset="https://blog.xojo.com/wp-content/uploads/2025/11/DFF0253D-0333-46DD-9780-8A0322F652C0-1024x982.jpeg 1024w, https://blog.xojo.com/wp-content/uploads/2025/11/DFF0253D-0333-46DD-9780-8A0322F652C0-300x288.jpeg 300w, https://blog.xojo.com/wp-content/uploads/2025/11/DFF0253D-0333-46DD-9780-8A0322F652C0-768x736.jpeg 768w, https://blog.xojo.com/wp-content/uploads/2025/11/DFF0253D-0333-46DD-9780-8A0322F652C0-1536x1473.jpeg 1536w, https://blog.xojo.com/wp-content/uploads/2025/11/DFF0253D-0333-46DD-9780-8A0322F652C0.jpeg 2044w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<p>If Jade’s response includes Xojo source code you can click one of the buttons above the code block to copy the code to the clipboard or to directly insert it into the active code editor.</p>



<figure class="wp-block-image size-large is-resized"><img loading="lazy" decoding="async" width="1010" height="1024" src="https://blog.xojo.com/wp-content/uploads/2025/11/99B34DEE-DD4E-47E6-A565-FD1437B9D552-1010x1024.jpeg" alt="" class="wp-image-15563" style="width:678px;height:auto" srcset="https://blog.xojo.com/wp-content/uploads/2025/11/99B34DEE-DD4E-47E6-A565-FD1437B9D552-1010x1024.jpeg 1010w, https://blog.xojo.com/wp-content/uploads/2025/11/99B34DEE-DD4E-47E6-A565-FD1437B9D552-296x300.jpeg 296w, https://blog.xojo.com/wp-content/uploads/2025/11/99B34DEE-DD4E-47E6-A565-FD1437B9D552-768x779.jpeg 768w, https://blog.xojo.com/wp-content/uploads/2025/11/99B34DEE-DD4E-47E6-A565-FD1437B9D552-1515x1536.jpeg 1515w, https://blog.xojo.com/wp-content/uploads/2025/11/99B34DEE-DD4E-47E6-A565-FD1437B9D552-2020x2048.jpeg 2020w" sizes="auto, (max-width: 1010px) 100vw, 1010px" /></figure>



<p>When interacting with Jade, keep in mind that although it remembers the context from the current conversation, it has no knowledge of prior conversations. Click the &#8220;Start Over&#8221; button to clear things and start a new conversation. Starting a new conversation is useful when switching to a different topic as it prevents Jade from relying on information you previously discussed that is no longer relevant.</p>



<p>The Export button saves the current Jade conversation to a JSON file which is a great way to save information you want to retain and refer to later.</p>



<h2 class="wp-block-heading">Other Tips</h2>



<ul class="wp-block-list">
<li>Jade currently uses Claude Sonnet 4, but this may change as newer models become available.</li>



<li>The only thing Jade knows about your project is what type it is (Desktop, Web, iOS, etc.). If you want Jade to offer suggestions based on your code, you will need to copy/paste the relevant code into the Jade conversation area.</li>



<li>Your Jade conversation is restored when the IDE restarts. If you get errors, ensure that you have valid internet access, that the API key is valid and you have a positive credit amount.</li>
</ul>



<h2 class="wp-block-heading">Wrap</h2>



<p>We hope you find Jade helpful with your Xojo development. Remember, Jade in Xojo 2025r3 is the first version of an AI assistant for Xojo and will improve over time. In subsequent releases we expect to add more capabilities and project integration. Read more about <a href="https://documentation.xojo.com/getting_started/using_the_ide/ask_jade.html" target="_blank" rel="noreferrer noopener">Jade</a> in Xojo&#8217;s Documentation.</p>



<p><em>Paul learned to program in BASIC at age 13 and has programmed in more languages than he remembers, with Xojo being an obvious favorite. When not working on Xojo, you can find him talking about retrocomputing at <a href="https://goto10.substack.com" target="_blank" rel="noreferrer noopener">Goto 10</a> and </em>on Mastodon @lefebvre@hachyderm.io.</p>



<ul class="wp-block-social-links has-normal-icon-size is-content-justification-center is-layout-flex wp-container-core-social-links-is-layout-16018d1d wp-block-social-links-is-layout-flex"><li class="wp-social-link wp-social-link-facebook  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.facebook.com/goxojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M12 2C6.5 2 2 6.5 2 12c0 5 3.7 9.1 8.4 9.9v-7H7.9V12h2.5V9.8c0-2.5 1.5-3.9 3.8-3.9 1.1 0 2.2.2 2.2.2v2.5h-1.3c-1.2 0-1.6.8-1.6 1.6V12h2.8l-.4 2.9h-2.3v7C18.3 21.1 22 17 22 12c0-5.5-4.5-10-10-10z"></path></svg><span class="wp-block-social-link-label screen-reader-text">Facebook</span></a></li>

<li class="wp-social-link wp-social-link-x  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://x.com/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M13.982 10.622 20.54 3h-1.554l-5.693 6.618L8.745 3H3.5l6.876 10.007L3.5 21h1.554l6.012-6.989L15.868 21h5.245l-7.131-10.378Zm-2.128 2.474-.697-.997-5.543-7.93H8l4.474 6.4.697.996 5.815 8.318h-2.387l-4.745-6.787Z" /></svg><span class="wp-block-social-link-label screen-reader-text">X</span></a></li>

<li class="wp-social-link wp-social-link-linkedin  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.linkedin.com/company/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M19.7,3H4.3C3.582,3,3,3.582,3,4.3v15.4C3,20.418,3.582,21,4.3,21h15.4c0.718,0,1.3-0.582,1.3-1.3V4.3 C21,3.582,20.418,3,19.7,3z M8.339,18.338H5.667v-8.59h2.672V18.338z M7.004,8.574c-0.857,0-1.549-0.694-1.549-1.548 c0-0.855,0.691-1.548,1.549-1.548c0.854,0,1.547,0.694,1.547,1.548C8.551,7.881,7.858,8.574,7.004,8.574z M18.339,18.338h-2.669 v-4.177c0-0.996-0.017-2.278-1.387-2.278c-1.389,0-1.601,1.086-1.601,2.206v4.249h-2.667v-8.59h2.559v1.174h0.037 c0.356-0.675,1.227-1.387,2.526-1.387c2.703,0,3.203,1.779,3.203,4.092V18.338z"></path></svg><span class="wp-block-social-link-label screen-reader-text">LinkedIn</span></a></li>

<li class="wp-social-link wp-social-link-github  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://github.com/topics/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M12,2C6.477,2,2,6.477,2,12c0,4.419,2.865,8.166,6.839,9.489c0.5,0.09,0.682-0.218,0.682-0.484 c0-0.236-0.009-0.866-0.014-1.699c-2.782,0.602-3.369-1.34-3.369-1.34c-0.455-1.157-1.11-1.465-1.11-1.465 c-0.909-0.62,0.069-0.608,0.069-0.608c1.004,0.071,1.532,1.03,1.532,1.03c0.891,1.529,2.341,1.089,2.91,0.833 c0.091-0.647,0.349-1.086,0.635-1.337c-2.22-0.251-4.555-1.111-4.555-4.943c0-1.091,0.39-1.984,1.03-2.682 C6.546,8.54,6.202,7.524,6.746,6.148c0,0,0.84-0.269,2.75,1.025C10.295,6.95,11.15,6.84,12,6.836 c0.85,0.004,1.705,0.114,2.504,0.336c1.909-1.294,2.748-1.025,2.748-1.025c0.546,1.376,0.202,2.394,0.1,2.646 c0.64,0.699,1.026,1.591,1.026,2.682c0,3.841-2.337,4.687-4.565,4.935c0.359,0.307,0.679,0.917,0.679,1.852 c0,1.335-0.012,2.415-0.012,2.741c0,0.269,0.18,0.579,0.688,0.481C19.138,20.161,22,16.416,22,12C22,6.477,17.523,2,12,2z"></path></svg><span class="wp-block-social-link-label screen-reader-text">GitHub</span></a></li>

<li class="wp-social-link wp-social-link-youtube  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.youtube.com/c/XojoInc" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M21.8,8.001c0,0-0.195-1.378-0.795-1.985c-0.76-0.797-1.613-0.801-2.004-0.847c-2.799-0.202-6.997-0.202-6.997-0.202 h-0.009c0,0-4.198,0-6.997,0.202C4.608,5.216,3.756,5.22,2.995,6.016C2.395,6.623,2.2,8.001,2.2,8.001S2,9.62,2,11.238v1.517 c0,1.618,0.2,3.237,0.2,3.237s0.195,1.378,0.795,1.985c0.761,0.797,1.76,0.771,2.205,0.855c1.6,0.153,6.8,0.201,6.8,0.201 s4.203-0.006,7.001-0.209c0.391-0.047,1.243-0.051,2.004-0.847c0.6-0.607,0.795-1.985,0.795-1.985s0.2-1.618,0.2-3.237v-1.517 C22,9.62,21.8,8.001,21.8,8.001z M9.935,14.594l-0.001-5.62l5.404,2.82L9.935,14.594z"></path></svg><span class="wp-block-social-link-label screen-reader-text">YouTube</span></a></li></ul>



<p class="has-text-align-center has-text-color has-link-color wp-elements-a0a2ac26ad214a49dac577734d259176" style="color:#84bd00"><a href="https://xojo.com/download/" target="_blank" rel="noreferrer noopener">Download Xojo</a></p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Toward the Future with WinUI</title>
		<link>https://blog.xojo.com/2025/12/09/toward-the-future-with-winui/</link>
		
		<dc:creator><![CDATA[William Yu]]></dc:creator>
		<pubDate>Tue, 09 Dec 2025 16:30:10 +0000</pubDate>
				<category><![CDATA[Desktop]]></category>
		<category><![CDATA[General]]></category>
		<category><![CDATA[Windows]]></category>
		<category><![CDATA[2025r3]]></category>
		<category><![CDATA[DesktopXAMLContainer]]></category>
		<category><![CDATA[WinUI]]></category>
		<category><![CDATA[XAML]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=15618</guid>

					<description><![CDATA[Keeping up with innovation can be challenging, especially when new technologies don&#8217;t always align neatly with what came before. Microsoft works hard to find a&#8230;]]></description>
										<content:encoded><![CDATA[
<p>Keeping up with innovation can be challenging, especially when new technologies don&#8217;t always align neatly with what came before. Microsoft works hard to find a balance, they experiment, iterate, and refine to discover what their users really want.</p>



<p>We&#8217;re taking a similar approach with our WinUI transition. We began with the <a href="https://blog.xojo.com/2023/08/09/doing-more-with-desktopxamlcontainer/" target="_blank" rel="noreferrer noopener">DesktopXAMLContainer</a> and are continuing by updating our <a href="https://blog.xojo.com/2025/07/08/a-xaml-driven-ui/" target="_blank" rel="noreferrer noopener">Win32 controls to their WinUI counterparts</a>, aiming for steady progress without disrupting existing workflows.</p>



<h3 class="wp-block-heading">What can you look forward to in 2025r3?</h3>



<p>We&#8217;ve expanded our WinUI offerings in this release with a broader set of updated controls. While 2025r2 introduced only a handful of WinUI-backed controls, 2025r3 builds on that foundation by updating a much larger group, including: BevelButton, Label, UpDownArrow, DateTimePicker, ComboBox, PopupMenu, RadioGroup, SegmentedButton, DisclosureTriangle, MoviePlayer, SearchField, TextField, and TextArea.</p>



<h3 class="wp-block-heading">What are the benefits of using WinUI?</h3>



<p>Win32 controls have been the foundation for many Windows apps, but WinUI introduces capabilities that traditional Win32 controls don&#8217;t have. Here&#8217;s a comparison to highlight some of the differences:</p>



<div class="wp-block-columns is-layout-flex wp-container-core-columns-is-layout-9d6595d7 wp-block-columns-is-layout-flex">
<div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow">
<div class="wp-block-media-text is-stacked-on-mobile" style="grid-template-columns:20% auto"><figure class="wp-block-media-text__media"><img loading="lazy" decoding="async" width="84" height="33" src="https://blog.xojo.com/wp-content/uploads/2025/12/Win32Label.png" alt="" class="wp-image-15619 size-full"/></figure><div class="wp-block-media-text__content">
<p>A Win32 DesktopLabel with a colored emoji is rendered in black and white.</p>
</div></div>
</div>



<div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow">
<div class="wp-block-media-text is-stacked-on-mobile" style="grid-template-columns:20% auto"><figure class="wp-block-media-text__media"><img loading="lazy" decoding="async" width="79" height="32" src="https://blog.xojo.com/wp-content/uploads/2025/12/WinUILabel-1.png" alt="" class="wp-image-15627 size-full"/></figure><div class="wp-block-media-text__content">
<p>Compared to the WinUI version with a colored emoji.</p>
</div></div>
</div>
</div>



<div class="wp-block-columns is-layout-flex wp-container-core-columns-is-layout-9d6595d7 wp-block-columns-is-layout-flex">
<div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow">
<div class="wp-block-media-text is-stacked-on-mobile" style="grid-template-columns:30% auto"><figure class="wp-block-media-text__media"><img loading="lazy" decoding="async" width="167" height="49" src="https://blog.xojo.com/wp-content/uploads/2025/12/Win32TextField.png" alt="" class="wp-image-15628 size-full"/></figure><div class="wp-block-media-text__content">
<p>A Win32 DesktopTextField containing right-to-left text isn&#8217;t automatically recognized as such, so it renders left-to-right.</p>
</div></div>
</div>



<div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow">
<div class="wp-block-media-text is-stacked-on-mobile" style="grid-template-columns:30% auto"><figure class="wp-block-media-text__media"><img loading="lazy" decoding="async" width="167" height="49" src="https://blog.xojo.com/wp-content/uploads/2025/12/WinUITextField.png" alt="" class="wp-image-15629 size-full"/></figure><div class="wp-block-media-text__content">
<p>Compared to the WinUI version which can automatically detect right-to-left text and formats accordingly.</p>
</div></div>
</div>
</div>



<div class="wp-block-columns is-layout-flex wp-container-core-columns-is-layout-9d6595d7 wp-block-columns-is-layout-flex">
<div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow">
<div class="wp-block-media-text is-stacked-on-mobile" style="grid-template-columns:30% auto"><figure class="wp-block-media-text__media"><img loading="lazy" decoding="async" width="167" height="49" src="https://blog.xojo.com/wp-content/uploads/2025/12/Win32PasswordField.png" alt="" class="wp-image-15631 size-full"/></figure><div class="wp-block-media-text__content">
<p>A password field (via DesktopTextField) with primitive support on Win32.</p>
</div></div>
</div>



<div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow">
<div class="wp-block-media-text is-stacked-on-mobile" style="grid-template-columns:30% auto"><figure class="wp-block-media-text__media"><img loading="lazy" decoding="async" width="167" height="49" src="https://blog.xojo.com/wp-content/uploads/2025/12/WinUIPasswordField.png" alt="" class="wp-image-15632 size-full"/></figure><div class="wp-block-media-text__content">
<p>An actual WinUI version of their PasswordBox control with a preview widget.</p>
</div></div>
</div>
</div>



<div class="wp-block-columns is-layout-flex wp-container-core-columns-is-layout-9d6595d7 wp-block-columns-is-layout-flex">
<div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow">
<div class="wp-block-media-text is-stacked-on-mobile" style="grid-template-columns:30% auto"><figure class="wp-block-media-text__media"><img loading="lazy" decoding="async" width="179" height="203" src="https://blog.xojo.com/wp-content/uploads/2025/12/Win32ComboBox.png" alt="" class="wp-image-15633 size-full"/></figure><div class="wp-block-media-text__content">
<p>A Win32 DesktopComboBox which does not support separators.</p>
</div></div>
</div>



<div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow">
<div class="wp-block-media-text is-stacked-on-mobile" style="grid-template-columns:30% auto"><figure class="wp-block-media-text__media"><img loading="lazy" decoding="async" width="189" height="356" src="https://blog.xojo.com/wp-content/uploads/2025/12/WinUIComboBox.png" alt="" class="wp-image-15634 size-full" srcset="https://blog.xojo.com/wp-content/uploads/2025/12/WinUIComboBox.png 189w, https://blog.xojo.com/wp-content/uploads/2025/12/WinUIComboBox-159x300.png 159w" sizes="auto, (max-width: 189px) 100vw, 189px" /></figure><div class="wp-block-media-text__content">
<p>A more modern looking WinUI version with built-in support for separators. </p>
</div></div>
</div>
</div>



<div class="wp-block-columns is-layout-flex wp-container-core-columns-is-layout-9d6595d7 wp-block-columns-is-layout-flex">
<div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow">
<div class="wp-block-media-text is-stacked-on-mobile"><figure class="wp-block-media-text__media"><img loading="lazy" decoding="async" width="372" height="297" src="https://blog.xojo.com/wp-content/uploads/2025/12/Win32CalendarDatePicker.png" alt="" class="wp-image-15635 size-full" srcset="https://blog.xojo.com/wp-content/uploads/2025/12/Win32CalendarDatePicker.png 372w, https://blog.xojo.com/wp-content/uploads/2025/12/Win32CalendarDatePicker-300x240.png 300w" sizes="auto, (max-width: 372px) 100vw, 372px" /></figure><div class="wp-block-media-text__content">
<p>A Win32 DesktopDateTimePicker with a dropdown calendar, but does not support dark mode.</p>
</div></div>
</div>



<div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow">
<div class="wp-block-media-text is-stacked-on-mobile"><figure class="wp-block-media-text__media"><img loading="lazy" decoding="async" width="463" height="542" src="https://blog.xojo.com/wp-content/uploads/2025/12/WinUICalendarDatePicker.png" alt="" class="wp-image-15636 size-full" srcset="https://blog.xojo.com/wp-content/uploads/2025/12/WinUICalendarDatePicker.png 463w, https://blog.xojo.com/wp-content/uploads/2025/12/WinUICalendarDatePicker-256x300.png 256w" sizes="auto, (max-width: 463px) 100vw, 463px" /></figure><div class="wp-block-media-text__content">
<p>A more modern looking WinUI version that also supports dark mode.</p>
</div></div>
</div>
</div>



<div class="wp-block-columns is-layout-flex wp-container-core-columns-is-layout-9d6595d7 wp-block-columns-is-layout-flex">
<div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow">
<div class="wp-block-media-text is-stacked-on-mobile"><figure class="wp-block-media-text__media"><img loading="lazy" decoding="async" width="576" height="350" src="https://blog.xojo.com/wp-content/uploads/2025/12/Win32DarkModeGlitches.png" alt="" class="wp-image-15637 size-full" srcset="https://blog.xojo.com/wp-content/uploads/2025/12/Win32DarkModeGlitches.png 576w, https://blog.xojo.com/wp-content/uploads/2025/12/Win32DarkModeGlitches-300x182.png 300w" sizes="auto, (max-width: 576px) 100vw, 576px" /></figure><div class="wp-block-media-text__content">
<p>Win32 dark mode support is limited.</p>
</div></div>
</div>



<div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow">
<div class="wp-block-media-text is-stacked-on-mobile"><figure class="wp-block-media-text__media"><img loading="lazy" decoding="async" width="472" height="600" src="https://blog.xojo.com/wp-content/uploads/2025/12/WinUIDarkMode.png" alt="" class="wp-image-15638 size-full" srcset="https://blog.xojo.com/wp-content/uploads/2025/12/WinUIDarkMode.png 472w, https://blog.xojo.com/wp-content/uploads/2025/12/WinUIDarkMode-236x300.png 236w" sizes="auto, (max-width: 472px) 100vw, 472px" /></figure><div class="wp-block-media-text__content">
<p>WinUI dark mode support is easier on the eyes.</p>
</div></div>
</div>
</div>



<div class="wp-block-columns is-layout-flex wp-container-core-columns-is-layout-9d6595d7 wp-block-columns-is-layout-flex">
<div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow">
<div class="wp-block-media-text is-stacked-on-mobile"><figure class="wp-block-media-text__media"><img loading="lazy" decoding="async" width="642" height="554" src="https://blog.xojo.com/wp-content/uploads/2025/12/Win32MoviePlayer.png" alt="" class="wp-image-15639 size-full" srcset="https://blog.xojo.com/wp-content/uploads/2025/12/Win32MoviePlayer.png 642w, https://blog.xojo.com/wp-content/uploads/2025/12/Win32MoviePlayer-300x259.png 300w" sizes="auto, (max-width: 642px) 100vw, 642px" /></figure><div class="wp-block-media-text__content">
<p>The Win32 DesktopMoviePlayer is very dated.</p>
</div></div>
</div>



<div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow">
<div class="wp-block-media-text is-stacked-on-mobile"><figure class="wp-block-media-text__media"><img loading="lazy" decoding="async" width="642" height="554" src="https://blog.xojo.com/wp-content/uploads/2025/12/WinUIMoviePlayer.png" alt="" class="wp-image-15640 size-full" srcset="https://blog.xojo.com/wp-content/uploads/2025/12/WinUIMoviePlayer.png 642w, https://blog.xojo.com/wp-content/uploads/2025/12/WinUIMoviePlayer-300x259.png 300w" sizes="auto, (max-width: 642px) 100vw, 642px" /></figure><div class="wp-block-media-text__content">
<p>WinUI has a much more modern look and feel.</p>
</div></div>
</div>
</div>



<h3 class="wp-block-heading">Opt-in to WinUI</h3>



<p>If you&#8217;d like to preview how your apps look and feel with WinUI controls, open the Windows build settings and check the options under the Advanced widget tab. Selecting&nbsp;<strong>“Use WinUI”</strong>&nbsp;applies WinUI styling to your desktop controls while keeping them scaled to your existing Win32 control bounds. Opting into&nbsp;<strong>“Native Control Sizes”</strong>&nbsp;gives you a more accurate representation of a true WinUI app, using the larger default font size and correspondingly larger controls.</p>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="433" height="381" src="https://blog.xojo.com/wp-content/uploads/2025/12/WinUIBuildSettings.png" alt="" class="wp-image-15641" srcset="https://blog.xojo.com/wp-content/uploads/2025/12/WinUIBuildSettings.png 433w, https://blog.xojo.com/wp-content/uploads/2025/12/WinUIBuildSettings-300x264.png 300w" sizes="auto, (max-width: 433px) 100vw, 433px" /></figure>



<h3 class="wp-block-heading">More Work Ahead</h3>



<p>As we continue down this path, we&#8217;re uncovering pain points that developers face when using WinUI controls in a Win32 environment—challenges Microsoft is no doubt familiar with as well. It will take time before we can fully move away from Win32 controls/windows and embrace WinUI, but we&#8217;re steadily heading in that direction. Thanks for joining us on this experience, more to come!</p>



<p><em><em><em>William Yu grew up in Canada learning to program BASIC on a Vic-20. He is Xojo’s resident Windows and Linux engineer, among his many other skills. Some may say he has joined the dark side here in the USA, but he will always be a Canadian at heart.</em></em></em></p>



<ul class="wp-block-social-links has-normal-icon-size is-content-justification-center is-layout-flex wp-container-core-social-links-is-layout-16018d1d wp-block-social-links-is-layout-flex"><li class="wp-social-link wp-social-link-facebook  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.facebook.com/goxojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M12 2C6.5 2 2 6.5 2 12c0 5 3.7 9.1 8.4 9.9v-7H7.9V12h2.5V9.8c0-2.5 1.5-3.9 3.8-3.9 1.1 0 2.2.2 2.2.2v2.5h-1.3c-1.2 0-1.6.8-1.6 1.6V12h2.8l-.4 2.9h-2.3v7C18.3 21.1 22 17 22 12c0-5.5-4.5-10-10-10z"></path></svg><span class="wp-block-social-link-label screen-reader-text">Facebook</span></a></li>

<li class="wp-social-link wp-social-link-x  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://x.com/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M13.982 10.622 20.54 3h-1.554l-5.693 6.618L8.745 3H3.5l6.876 10.007L3.5 21h1.554l6.012-6.989L15.868 21h5.245l-7.131-10.378Zm-2.128 2.474-.697-.997-5.543-7.93H8l4.474 6.4.697.996 5.815 8.318h-2.387l-4.745-6.787Z" /></svg><span class="wp-block-social-link-label screen-reader-text">X</span></a></li>

<li class="wp-social-link wp-social-link-linkedin  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.linkedin.com/company/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M19.7,3H4.3C3.582,3,3,3.582,3,4.3v15.4C3,20.418,3.582,21,4.3,21h15.4c0.718,0,1.3-0.582,1.3-1.3V4.3 C21,3.582,20.418,3,19.7,3z M8.339,18.338H5.667v-8.59h2.672V18.338z M7.004,8.574c-0.857,0-1.549-0.694-1.549-1.548 c0-0.855,0.691-1.548,1.549-1.548c0.854,0,1.547,0.694,1.547,1.548C8.551,7.881,7.858,8.574,7.004,8.574z M18.339,18.338h-2.669 v-4.177c0-0.996-0.017-2.278-1.387-2.278c-1.389,0-1.601,1.086-1.601,2.206v4.249h-2.667v-8.59h2.559v1.174h0.037 c0.356-0.675,1.227-1.387,2.526-1.387c2.703,0,3.203,1.779,3.203,4.092V18.338z"></path></svg><span class="wp-block-social-link-label screen-reader-text">LinkedIn</span></a></li>

<li class="wp-social-link wp-social-link-github  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://github.com/topics/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M12,2C6.477,2,2,6.477,2,12c0,4.419,2.865,8.166,6.839,9.489c0.5,0.09,0.682-0.218,0.682-0.484 c0-0.236-0.009-0.866-0.014-1.699c-2.782,0.602-3.369-1.34-3.369-1.34c-0.455-1.157-1.11-1.465-1.11-1.465 c-0.909-0.62,0.069-0.608,0.069-0.608c1.004,0.071,1.532,1.03,1.532,1.03c0.891,1.529,2.341,1.089,2.91,0.833 c0.091-0.647,0.349-1.086,0.635-1.337c-2.22-0.251-4.555-1.111-4.555-4.943c0-1.091,0.39-1.984,1.03-2.682 C6.546,8.54,6.202,7.524,6.746,6.148c0,0,0.84-0.269,2.75,1.025C10.295,6.95,11.15,6.84,12,6.836 c0.85,0.004,1.705,0.114,2.504,0.336c1.909-1.294,2.748-1.025,2.748-1.025c0.546,1.376,0.202,2.394,0.1,2.646 c0.64,0.699,1.026,1.591,1.026,2.682c0,3.841-2.337,4.687-4.565,4.935c0.359,0.307,0.679,0.917,0.679,1.852 c0,1.335-0.012,2.415-0.012,2.741c0,0.269,0.18,0.579,0.688,0.481C19.138,20.161,22,16.416,22,12C22,6.477,17.523,2,12,2z"></path></svg><span class="wp-block-social-link-label screen-reader-text">GitHub</span></a></li>

<li class="wp-social-link wp-social-link-youtube  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.youtube.com/c/XojoInc" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M21.8,8.001c0,0-0.195-1.378-0.795-1.985c-0.76-0.797-1.613-0.801-2.004-0.847c-2.799-0.202-6.997-0.202-6.997-0.202 h-0.009c0,0-4.198,0-6.997,0.202C4.608,5.216,3.756,5.22,2.995,6.016C2.395,6.623,2.2,8.001,2.2,8.001S2,9.62,2,11.238v1.517 c0,1.618,0.2,3.237,0.2,3.237s0.195,1.378,0.795,1.985c0.761,0.797,1.76,0.771,2.205,0.855c1.6,0.153,6.8,0.201,6.8,0.201 s4.203-0.006,7.001-0.209c0.391-0.047,1.243-0.051,2.004-0.847c0.6-0.607,0.795-1.985,0.795-1.985s0.2-1.618,0.2-3.237v-1.517 C22,9.62,21.8,8.001,21.8,8.001z M9.935,14.594l-0.001-5.62l5.404,2.82L9.935,14.594z"></path></svg><span class="wp-block-social-link-label screen-reader-text">YouTube</span></a></li></ul>



<p class="has-text-align-center has-text-color has-link-color wp-elements-a0a2ac26ad214a49dac577734d259176" style="color:#84bd00"><a href="https://xojo.com/download/" target="_blank" rel="noreferrer noopener">Download Xojo</a></p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Xojo 2025r2.1: Publishing macOS Apps Under Tahoe</title>
		<link>https://blog.xojo.com/2025/10/14/xojo-2025r2-1-publishing-macos-apps-under-tahoe/</link>
		
		<dc:creator><![CDATA[Javier Menendez]]></dc:creator>
		<pubDate>Tue, 14 Oct 2025 21:20:03 +0000</pubDate>
				<category><![CDATA[General]]></category>
		<category><![CDATA[Mac]]></category>
		<category><![CDATA[Tips]]></category>
		<category><![CDATA[Apple]]></category>
		<category><![CDATA[macOS Tahoe]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=15445</guid>

					<description><![CDATA[macOS 26 is in the wild, and many Xojo users have likely updated their Macs to the latest version. While Xojo 2025r2.1 is compatible and&#8230;]]></description>
										<content:encoded><![CDATA[
<p><a href="https://blog.xojo.com/2025/09/15/xojo-support-for-macos-26-and-ios-26/" target="_blank" rel="noreferrer noopener">macOS 26 is in the wild</a>, and many Xojo users have likely updated their Macs to the latest version. While Xojo 2025r2.1 is compatible and can build apps that run under the latest macOS, the <a href="https://blog.xojo.com/2025/03/25/how-to-publish-macos-and-ios-apps-to-the-app-store-directly-from-xojo/" target="_blank" rel="noreferrer noopener">Publish feature</a> depends on certain tools provided by Xcode. Unfortunately, one of these tools has undergone a significant change in the latest Xcode release, causing the Publish feature to no longer function correctly.</p>



<span id="more-15445"></span>



<p>There are two possible solutions:</p>



<ul class="wp-block-list">
<li><strong>If your Mac still runs under macOS 15.7 Sequoia</strong> (or an earlier macOS version supported by Xojo&#8217;s Publish feature) with Xcode 26 installed,  you can restore Publish feature compatibility by installing Xcode 16.4.x and making that version the active one in your toolchain (especially if you have multiple Xcode versions installed).</li>



<li><strong>If your Mac is running macOS 26.x Tahoe</strong> with Xcode 26 installed, Xojo&#8217;s Publish feature for macOS apps won&#8217;t work as expected, specifically when it attempts to retrieve the AppID from the App Store Connect. The good news is that by the time this error occurs, your app has already been successfully compiled and the .pkg file created. You can use Apple’s <a href="https://www.google.com/url?sa=t&amp;source=web&amp;rct=j&amp;opi=89978449&amp;url=https://apps.apple.com/us/app/transporter/id1450874784%3Fmt%3D12&amp;ved=2ahUKEwiitNb4mo-QAxWphv0HHc48DjQQFnoECBcQAQ&amp;usg=AOvVaw2lhxdNCd0mHUPXUYrhF8U_" target="_blank" rel="noreferrer noopener">Transporter app</a> to complete the final step of uploading the .pkg file to App Store Connect.</li>
</ul>



<p>This issue has been fixed and the solution will be included in Xojo 2025r3. The update also improves how the App ID is retrieved by relying on the available provider listing. This rare issue could affect users whose Apple ID is associated with multiple publishing services, for example, if the same Apple ID is used for both app development and podcast publishing.</p>



<p>Once Xojo 2025r3 is released, the Publish feature will work as before on macOS Sequoia (and previous supported macOS versions), and it will also function properly with the new Xcode 26 toolchain &#8211; whether installed on Sequoia or on the latest macOS 26. Read more about Xojo Support for macOS 26 and iOS 26 on the <a href="https://blog.xojo.com/2025/09/15/xojo-support-for-macos-26-and-ios-26/" target="_blank" rel="noreferrer noopener">Xojo Blog</a>.</p>



<p><em>Javier Menendez is an engineer at Xojo and has been using Xojo since 1998. He lives in Castellón</em>, <em>Spain and hosts regular Xojo hangouts en español. Ask Javier questions on Twitter at <a href="https://twitter.com/xojoes" target="_blank" rel="noreferrer noopener">@XojoES</a> or on the <a href="https://forum.xojo.com/u/javier_menendez/summary" target="_blank" rel="noreferrer noopener">Xojo Forum</a>.</em></p>



<ul class="wp-block-social-links has-normal-icon-size is-content-justification-center is-layout-flex wp-container-core-social-links-is-layout-16018d1d wp-block-social-links-is-layout-flex"><li class="wp-social-link wp-social-link-facebook  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.facebook.com/goxojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M12 2C6.5 2 2 6.5 2 12c0 5 3.7 9.1 8.4 9.9v-7H7.9V12h2.5V9.8c0-2.5 1.5-3.9 3.8-3.9 1.1 0 2.2.2 2.2.2v2.5h-1.3c-1.2 0-1.6.8-1.6 1.6V12h2.8l-.4 2.9h-2.3v7C18.3 21.1 22 17 22 12c0-5.5-4.5-10-10-10z"></path></svg><span class="wp-block-social-link-label screen-reader-text">Facebook</span></a></li>

<li class="wp-social-link wp-social-link-x  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://x.com/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M13.982 10.622 20.54 3h-1.554l-5.693 6.618L8.745 3H3.5l6.876 10.007L3.5 21h1.554l6.012-6.989L15.868 21h5.245l-7.131-10.378Zm-2.128 2.474-.697-.997-5.543-7.93H8l4.474 6.4.697.996 5.815 8.318h-2.387l-4.745-6.787Z" /></svg><span class="wp-block-social-link-label screen-reader-text">X</span></a></li>

<li class="wp-social-link wp-social-link-linkedin  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.linkedin.com/company/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M19.7,3H4.3C3.582,3,3,3.582,3,4.3v15.4C3,20.418,3.582,21,4.3,21h15.4c0.718,0,1.3-0.582,1.3-1.3V4.3 C21,3.582,20.418,3,19.7,3z M8.339,18.338H5.667v-8.59h2.672V18.338z M7.004,8.574c-0.857,0-1.549-0.694-1.549-1.548 c0-0.855,0.691-1.548,1.549-1.548c0.854,0,1.547,0.694,1.547,1.548C8.551,7.881,7.858,8.574,7.004,8.574z M18.339,18.338h-2.669 v-4.177c0-0.996-0.017-2.278-1.387-2.278c-1.389,0-1.601,1.086-1.601,2.206v4.249h-2.667v-8.59h2.559v1.174h0.037 c0.356-0.675,1.227-1.387,2.526-1.387c2.703,0,3.203,1.779,3.203,4.092V18.338z"></path></svg><span class="wp-block-social-link-label screen-reader-text">LinkedIn</span></a></li>

<li class="wp-social-link wp-social-link-github  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://github.com/topics/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M12,2C6.477,2,2,6.477,2,12c0,4.419,2.865,8.166,6.839,9.489c0.5,0.09,0.682-0.218,0.682-0.484 c0-0.236-0.009-0.866-0.014-1.699c-2.782,0.602-3.369-1.34-3.369-1.34c-0.455-1.157-1.11-1.465-1.11-1.465 c-0.909-0.62,0.069-0.608,0.069-0.608c1.004,0.071,1.532,1.03,1.532,1.03c0.891,1.529,2.341,1.089,2.91,0.833 c0.091-0.647,0.349-1.086,0.635-1.337c-2.22-0.251-4.555-1.111-4.555-4.943c0-1.091,0.39-1.984,1.03-2.682 C6.546,8.54,6.202,7.524,6.746,6.148c0,0,0.84-0.269,2.75,1.025C10.295,6.95,11.15,6.84,12,6.836 c0.85,0.004,1.705,0.114,2.504,0.336c1.909-1.294,2.748-1.025,2.748-1.025c0.546,1.376,0.202,2.394,0.1,2.646 c0.64,0.699,1.026,1.591,1.026,2.682c0,3.841-2.337,4.687-4.565,4.935c0.359,0.307,0.679,0.917,0.679,1.852 c0,1.335-0.012,2.415-0.012,2.741c0,0.269,0.18,0.579,0.688,0.481C19.138,20.161,22,16.416,22,12C22,6.477,17.523,2,12,2z"></path></svg><span class="wp-block-social-link-label screen-reader-text">GitHub</span></a></li>

<li class="wp-social-link wp-social-link-youtube  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.youtube.com/c/XojoInc" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M21.8,8.001c0,0-0.195-1.378-0.795-1.985c-0.76-0.797-1.613-0.801-2.004-0.847c-2.799-0.202-6.997-0.202-6.997-0.202 h-0.009c0,0-4.198,0-6.997,0.202C4.608,5.216,3.756,5.22,2.995,6.016C2.395,6.623,2.2,8.001,2.2,8.001S2,9.62,2,11.238v1.517 c0,1.618,0.2,3.237,0.2,3.237s0.195,1.378,0.795,1.985c0.761,0.797,1.76,0.771,2.205,0.855c1.6,0.153,6.8,0.201,6.8,0.201 s4.203-0.006,7.001-0.209c0.391-0.047,1.243-0.051,2.004-0.847c0.6-0.607,0.795-1.985,0.795-1.985s0.2-1.618,0.2-3.237v-1.517 C22,9.62,21.8,8.001,21.8,8.001z M9.935,14.594l-0.001-5.62l5.404,2.82L9.935,14.594z"></path></svg><span class="wp-block-social-link-label screen-reader-text">YouTube</span></a></li></ul>



<p class="has-text-align-center has-text-color has-link-color wp-elements-a0a2ac26ad214a49dac577734d259176" style="color:#84bd00"><a href="https://xojo.com/download/" target="_blank" rel="noreferrer noopener">Download Xojo</a></p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>RegEx Examples: 10 Practical Patterns You Can Copy and Paste</title>
		<link>https://blog.xojo.com/2025/09/18/regex-examples-10-practical-patterns-you-can-copy-and-paste/</link>
		
		<dc:creator><![CDATA[Gabriel Ludosanu]]></dc:creator>
		<pubDate>Thu, 18 Sep 2025 11:00:00 +0000</pubDate>
				<category><![CDATA[General]]></category>
		<category><![CDATA[Tips]]></category>
		<category><![CDATA[Code Snippets]]></category>
		<category><![CDATA[Data Extraction]]></category>
		<category><![CDATA[RegEx]]></category>
		<category><![CDATA[Text Processing]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=15351</guid>

					<description><![CDATA[Looking for RegEx examples you can drop straight into your project? This practical cheat sheet focuses on the most searched tasks, such as find/replace, extracting&#8230;]]></description>
										<content:encoded><![CDATA[
<p>Looking for RegEx examples you can drop straight into your project? This practical cheat sheet focuses on the most searched tasks, such as find/replace, extracting values, lookahead/lookbehind, and non-greedy matches, using Xojo’s RegEx class with concise, ready-to-run snippets. Copy, paste, ship.</p>



<h2 class="wp-block-heading" id="setup-3-lines-you’ll-reuse">Setup (3 lines you’ll reuse)</h2>



<pre class="wp-block-code"><code>Var re As New RegEx
Var opt As New RegExOptions
re.Options = opt</code></pre>



<h2 class="wp-block-heading" id="replace-all-occurrences-word-boundary">1) Replace all occurrences (word boundary)</h2>



<p>Goal: a → the (whole word)</p>



<pre class="wp-block-code"><code>Var re As New RegEx
Var opt As New RegExOptions
opt.ReplaceAllMatches = True
re.Options = opt

re.SearchPattern = "\ba\b"
re.ReplacementPattern = "the"
MessageBox(re.Replace("a bus on a street in a town"))
' the bus on the street in the town</code></pre>



<h2 class="wp-block-heading" id="strip-html-tags">2) Strip HTML tags</h2>



<pre class="wp-block-code"><code>Var re As New RegEx
Var opt As New RegExOptions
opt.ReplaceAllMatches = True
re.Options = opt

re.SearchPattern = "&lt;&#91;^&lt;>]+>"
re.ReplacementPattern = ""
MessageBox(re.Replace("&lt;p>Hello &lt;b>world&lt;/b>.&lt;/p>"))
' Hello world.</code></pre>



<h2 class="wp-block-heading" id="extract-the-first-number-capture-groups">3) Extract the first number (capture groups)</h2>



<pre class="wp-block-code"><code>re.SearchPattern = "(\d+)"
Var m As RegExMatch = re.Search("Order #12345 shipped")
If m &lt;> Nil Then MessageBox(m.SubExpressionString(1)) ' 12345</code></pre>



<h2 class="wp-block-heading" id="reformat-dates-with-1-2-3">4) Reformat dates with $1, $2, $3</h2>



<p>Goal: YYYY-MM-DD → DD/MM/YYYY</p>



<pre class="wp-block-code"><code>Var re As New RegEx
Var opt As New RegExOptions
opt.ReplaceAllMatches = True
re.Options = opt

re.SearchPattern = "(\d{4})-(\d{2})-(\d{2})"
re.ReplacementPattern = "$3/$2/$1"
MessageBox(re.Replace("Due: 2025-09-09 and 2025-12-31"))
' Due: 09/09/2025 and 31/12/2025</code></pre>



<h2 class="wp-block-heading" id="find-all-words-simple-iterator">5) Find all words (simple iterator)</h2>



<pre class="wp-block-code"><code>re.SearchPattern = "\w+"
Var match As RegExMatch = re.Search("one two three")
While match &lt;> Nil
  System.DebugLog(match.SubExpressionString(0))
  match = re.Search ' continues from last position
Wend</code></pre>



<h2 class="wp-block-heading" id="replace-only-the-second-occurrence">6) Replace only the second occurrence</h2>



<pre class="wp-block-code"><code>Var s As String = "a bus drove on a street in a town"
re.SearchPattern = "\ba\b"
re.ReplacementPattern = "the"

Var first As RegExMatch = re.Search(s) ' find first
If first &lt;> Nil Then
  s = re.Replace ' replaces the next match only
End If

MessageBox(s)
' a bus drove on the street in a town</code></pre>



<h2 class="wp-block-heading" id="lookarounds">7) Lookarounds</h2>



<p>Match “foo” not followed by “bar”</p>



<pre class="wp-block-code"><code>re.SearchPattern = "foo(?!bar)"</code></pre>



<h3 class="wp-block-heading" id="negative-lookahead-match-only-http-not-https-urls">7.1 Negative lookahead: match only http (not https) URLs</h3>



<pre class="wp-block-code"><code>Var re As New RegEx
re.SearchPattern = "http(?!s)://\S+" ' http:// not followed by s
Var txt As String = "http://a.com and https://b.com"
Var m As RegExMatch = re.Search(txt)
While m &lt;> Nil
  System.DebugLog(m.SubExpressionString(0)) ' http://a.com
  m = re.Search
Wend</code></pre>



<h3 class="wp-block-heading" id="positive-lookbehind--optional-decimals-amounts-right-after-">7.2 Positive lookbehind + optional decimals: amounts right after $</h3>



<pre class="wp-block-code"><code>Var re As New RegEx
re.SearchPattern = "(?&lt;=\$)\d+(?:\.\d{2})?" ' $123 or $123.45 → capture just the number
Var txt As String = "Total: $19.99, Tax: $2"
Var m As RegExMatch = re.Search(txt)
While m &lt;> Nil
  System.DebugLog(m.SubExpressionString(0)) ' 19.99, 2
  m = re.Search
Wend</code></pre>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p>Tip:</p>



<ul class="wp-block-list">
<li>Fixed‑width only for look‑behind: avoid quantifiers like +, * inside (?&lt;=…)/(?&lt;!…).</li>



<li>Use lookarounds when you need context to the left/right but don’t want it included in the match or replacement.</li>
</ul>
</blockquote>



<h2 class="wp-block-heading" id="smallest-span-between-tags-non‑greedy">8) Smallest span between tags (non‑greedy)</h2>



<pre class="wp-block-code"><code>re.SearchPattern = "&lt;b>.+?&lt;/b>" ' or: opt.Greedy = False</code></pre>



<h2 class="wp-block-heading" id="extract-emails-simple-demo">9) Extract emails (simple demo)</h2>



<pre class="wp-block-code"><code>re.SearchPattern = "&#91;A-Za-z0-9._%+-]+@&#91;A-Za-z0-9.-]+\.&#91;A-Za-z]{2,}"
Var em As RegExMatch = re.Search("Contact: me@example.com")
If em &lt;> Nil Then MessageBox(em.SubExpressionString(0)) ' me@example.com</code></pre>



<h2 class="wp-block-heading" id="start-at-character-position-n-utf‑8-safe">10) Start at character position N (UTF‑8 safe)</h2>



<pre class="wp-block-code"><code>Var t As String = "ąβç sample"
Var charPos As Integer = 5 ' 1-based character index
re.SearchPattern = "\w+"
re.SearchStartPosition = t.Left(charPos - 1).Bytes ' convert char index → byte offset
Var mm As RegExMatch = re.Search(t)
If mm &lt;> Nil Then System.DebugLog(mm.SubExpressionString(0))</code></pre>



<h2 class="wp-block-heading" id="quick-replacement-references">Quick replacement references</h2>



<ul class="wp-block-list">
<li><strong>$&amp;</strong>&nbsp;= entire match (This reference represents the&nbsp;<em>exact</em>&nbsp;piece of text that your regular expression found. It’s incredibly useful if you want to add something before or after the matched text without changing the match itself.)</li>



<li><strong>$1…$50</strong>&nbsp;= captured groups (Regular expressions allow you to define specific “groups” within your match by enclosing parts of your pattern in parentheses&nbsp;<code>()</code>. Each set of parentheses creates a captured group.)</li>



<li><strong>$`</strong>&nbsp;= text before the match (This special reference represents&nbsp;<em>all</em>&nbsp;the text in your original string that appears&nbsp;<em>before</em>&nbsp;the part your regular expression matched. It’s handy if you want to keep the beginning of the string intact while making a change in the middle.)</li>



<li><strong>$’</strong>&nbsp;= text after the match (This refers to&nbsp;<em>all</em>&nbsp;the text in your original string that comes&nbsp;<em>after</em>&nbsp;the current match. It’s useful for preserving the end of the string.)</li>
</ul>



<h2 class="wp-block-heading" id="options-you’ll-use-most">Options you’ll use most</h2>



<pre class="wp-block-code"><code>opt.ReplaceAllMatches = True  ' global replace
opt.CaseSensitive = True      ' default is False
opt.DotMatchAll = True        ' make . match newlines
opt.Greedy = False            ' prefer shortest matches
opt.TreatTargetAsOneLine = True ' ^ and $ match whole string</code></pre>



<h2 class="wp-block-heading" id="common-gotchas">Common gotchas</h2>



<ul class="wp-block-list">
<li>Greediness: “.+” can overmatch; use .+? or set Greedy = False.</li>



<li>Case sensitivity: default searches are case‑insensitive; enable CaseSensitive when exact case matters.</li>



<li>UTF‑8: SearchStartPosition is byte‑based; convert character index to bytes (see example ↑).</li>



<li>Lookbehind must be fixed‑width.</li>



<li>Iteration: After the first Search(targetString), call re.Search with no args to continue.</li>
</ul>



<h2 class="wp-block-heading" id="wrap‑up">Wrap‑up</h2>



<p>Got a tricky pattern, validation, parsing, or a lookaround edge case you want covered? Drop a comment in the forums with your use.</p>



<p>Happy matching!</p>



<p><em>Gabriel is a digital marketing enthusiast who loves coding with Xojo to create cool software tools for any platform. He is always eager to learn and share new ideas!</em></p>



<ul class="wp-block-social-links has-normal-icon-size is-content-justification-center is-layout-flex wp-container-core-social-links-is-layout-16018d1d wp-block-social-links-is-layout-flex"><li class="wp-social-link wp-social-link-facebook  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.facebook.com/goxojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M12 2C6.5 2 2 6.5 2 12c0 5 3.7 9.1 8.4 9.9v-7H7.9V12h2.5V9.8c0-2.5 1.5-3.9 3.8-3.9 1.1 0 2.2.2 2.2.2v2.5h-1.3c-1.2 0-1.6.8-1.6 1.6V12h2.8l-.4 2.9h-2.3v7C18.3 21.1 22 17 22 12c0-5.5-4.5-10-10-10z"></path></svg><span class="wp-block-social-link-label screen-reader-text">Facebook</span></a></li>

<li class="wp-social-link wp-social-link-x  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://x.com/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M13.982 10.622 20.54 3h-1.554l-5.693 6.618L8.745 3H3.5l6.876 10.007L3.5 21h1.554l6.012-6.989L15.868 21h5.245l-7.131-10.378Zm-2.128 2.474-.697-.997-5.543-7.93H8l4.474 6.4.697.996 5.815 8.318h-2.387l-4.745-6.787Z" /></svg><span class="wp-block-social-link-label screen-reader-text">X</span></a></li>

<li class="wp-social-link wp-social-link-linkedin  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.linkedin.com/company/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M19.7,3H4.3C3.582,3,3,3.582,3,4.3v15.4C3,20.418,3.582,21,4.3,21h15.4c0.718,0,1.3-0.582,1.3-1.3V4.3 C21,3.582,20.418,3,19.7,3z M8.339,18.338H5.667v-8.59h2.672V18.338z M7.004,8.574c-0.857,0-1.549-0.694-1.549-1.548 c0-0.855,0.691-1.548,1.549-1.548c0.854,0,1.547,0.694,1.547,1.548C8.551,7.881,7.858,8.574,7.004,8.574z M18.339,18.338h-2.669 v-4.177c0-0.996-0.017-2.278-1.387-2.278c-1.389,0-1.601,1.086-1.601,2.206v4.249h-2.667v-8.59h2.559v1.174h0.037 c0.356-0.675,1.227-1.387,2.526-1.387c2.703,0,3.203,1.779,3.203,4.092V18.338z"></path></svg><span class="wp-block-social-link-label screen-reader-text">LinkedIn</span></a></li>

<li class="wp-social-link wp-social-link-github  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://github.com/topics/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M12,2C6.477,2,2,6.477,2,12c0,4.419,2.865,8.166,6.839,9.489c0.5,0.09,0.682-0.218,0.682-0.484 c0-0.236-0.009-0.866-0.014-1.699c-2.782,0.602-3.369-1.34-3.369-1.34c-0.455-1.157-1.11-1.465-1.11-1.465 c-0.909-0.62,0.069-0.608,0.069-0.608c1.004,0.071,1.532,1.03,1.532,1.03c0.891,1.529,2.341,1.089,2.91,0.833 c0.091-0.647,0.349-1.086,0.635-1.337c-2.22-0.251-4.555-1.111-4.555-4.943c0-1.091,0.39-1.984,1.03-2.682 C6.546,8.54,6.202,7.524,6.746,6.148c0,0,0.84-0.269,2.75,1.025C10.295,6.95,11.15,6.84,12,6.836 c0.85,0.004,1.705,0.114,2.504,0.336c1.909-1.294,2.748-1.025,2.748-1.025c0.546,1.376,0.202,2.394,0.1,2.646 c0.64,0.699,1.026,1.591,1.026,2.682c0,3.841-2.337,4.687-4.565,4.935c0.359,0.307,0.679,0.917,0.679,1.852 c0,1.335-0.012,2.415-0.012,2.741c0,0.269,0.18,0.579,0.688,0.481C19.138,20.161,22,16.416,22,12C22,6.477,17.523,2,12,2z"></path></svg><span class="wp-block-social-link-label screen-reader-text">GitHub</span></a></li>

<li class="wp-social-link wp-social-link-youtube  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.youtube.com/c/XojoInc" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M21.8,8.001c0,0-0.195-1.378-0.795-1.985c-0.76-0.797-1.613-0.801-2.004-0.847c-2.799-0.202-6.997-0.202-6.997-0.202 h-0.009c0,0-4.198,0-6.997,0.202C4.608,5.216,3.756,5.22,2.995,6.016C2.395,6.623,2.2,8.001,2.2,8.001S2,9.62,2,11.238v1.517 c0,1.618,0.2,3.237,0.2,3.237s0.195,1.378,0.795,1.985c0.761,0.797,1.76,0.771,2.205,0.855c1.6,0.153,6.8,0.201,6.8,0.201 s4.203-0.006,7.001-0.209c0.391-0.047,1.243-0.051,2.004-0.847c0.6-0.607,0.795-1.985,0.795-1.985s0.2-1.618,0.2-3.237v-1.517 C22,9.62,21.8,8.001,21.8,8.001z M9.935,14.594l-0.001-5.62l5.404,2.82L9.935,14.594z"></path></svg><span class="wp-block-social-link-label screen-reader-text">YouTube</span></a></li></ul>



<p class="has-text-align-center has-text-color has-link-color wp-elements-a0a2ac26ad214a49dac577734d259176" style="color:#84bd00"><a href="https://xojo.com/download/" target="_blank" rel="noreferrer noopener">Download Xojo</a></p>
]]></content:encoded>
					
		
		
			</item>
	</channel>
</rss>
