<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>WinUI 3 on kenji.blog</title><link>http://kenji.blog/id/tags/winui-3/</link><description>Recent content in WinUI 3 on kenji.blog</description><generator>Hugo -- gohugo.io</generator><language>id</language><copyright>kenjinote</copyright><lastBuildDate>Sun, 13 Sep 2026 04:00:00 +0900</lastBuildDate><atom:link href="http://kenji.blog/id/tags/winui-3/index.xml" rel="self" type="application/rss+xml"/><item><title>Belajar dari Jurnal Pengembangan 'LogicPad': Perjalanan Merilis Aplikasi Windows Buatan Sendiri</title><link>http://kenji.blog/id/p/logicpad-windows-app-development-journey/</link><pubDate>Sun, 13 Sep 2026 04:00:00 +0900</pubDate><guid>http://kenji.blog/id/p/logicpad-windows-app-development-journey/</guid><description>&lt;img src="http://kenji.blog/p/logicpad-windows-app-development-journey/img/eyecatch.jpg" alt="Featured image of post Belajar dari Jurnal Pengembangan 'LogicPad': Perjalanan Merilis Aplikasi Windows Buatan Sendiri" />&lt;h2 id="1-pendahuluan-mengapa-memilih-membangun-aplikasi-native-windows-saat-ini">1. Pendahuluan: Mengapa Memilih Membangun Aplikasi Native Windows Saat Ini
&lt;/h2>&lt;p>Dalam pengembangan aplikasi modern, tidak diragukan lagi bahwa teknologi lintas platform (cross-platform) seperti Electron, Tauri, dan React Native telah menjadi arus utama. Pendekatan &amp;ldquo;tulis sekali, jalankan di mana saja&amp;rdquo; (Write Once, Run Anywhere) yang menggunakan teknologi web sangatlah rasional dari sudut pandang kecepatan pengembangan dan pemeliharaan. Namun, saya dengan sengaja memilih jalur untuk mengembangkan aplikasi yang disebut &amp;ldquo;LogicPad&amp;rdquo; sebagai aplikasi native yang sepenuhnya dioptimalkan untuk Windows.&lt;/p>
&lt;p>LogicPad adalah simulator sirkuit logika digital sekaligus editor teks yang ditargetkan untuk insinyur perangkat keras (hardware) dan pelajar sirkuit logika. Aplikasi ini perlu menyimulasikan puluhan ribu gerbang logika secara real-time, dan pada saat yang sama, merender data gelombang yang kompleks tanpa penundaan (delay). Dalam ranah yang menuntut performa ekstrem seperti ini, jeda sementara beberapa milidetik (micro-stutter) akibat pengumpulan sampah (garbage collection) atau overhead perenderan dari web view akan menyebabkan penurunan pengalaman pengguna yang fatal.&lt;/p>
&lt;p>Dalam artikel ini, saya akan menelusuri kembali perjalanan pengembangan LogicPad, mulai dari konsep pengembangan, implementasi spesifik menggunakan C++ dan WinUI 3 (Windows App SDK), menerobos hambatan teknis, pemaketan MSIX, hingga pendistribusiannya ke seluruh dunia melalui Microsoft Store, disertai dengan penjelasan teknis yang mendetail. Dengan membagikan proses tentang bagaimana seorang pengembang individu dapat membangun aplikasi Windows native berkualitas perusahaan (enterprise), saya berharap artikel ini dapat menjadi panduan bagi mereka yang juga ingin mengambil tantangan dalam pengembangan native.&lt;/p>
&lt;h2 id="2-linimasa-proyek">2. Linimasa Proyek
&lt;/h2>&lt;p>Pengembangan LogicPad dilakukan sebagai proyek pribadi yang memanfaatkan waktu di akhir pekan dan malam hari. Keseluruhan linimasanya memakan waktu sekitar setengah tahun (6 bulan). Berikut adalah bagan Gantt yang menunjukkan kemajuan proyek tersebut.&lt;/p>
&lt;pre class="mermaid">
gantt
title Linimasa Pengembangan LogicPad
dateFormat YYYY-MM-DD
section &amp;#34;Perencanaan &amp;amp; Desain&amp;#34;
&amp;#34;Analisis Kebutuhan &amp;amp; Pembuatan Prototipe&amp;#34; :a1, 2025-10-01, 30d
&amp;#34;Desain Arsitektur (Core C++)&amp;#34; :a2, after a1, 20d
section &amp;#34;Pengembangan Inti&amp;#34;
&amp;#34;Mesin Simulasi (C++)&amp;#34; :a3, after a2, 45d
&amp;#34;Integrasi WinUI 3 XAML&amp;#34; :a4, after a3, 40d
section &amp;#34;Penyempurnaan UI/UX&amp;#34;
&amp;#34;Bilah Judul Kustom &amp;amp; Windowing&amp;#34; :a5, after a4, 15d
&amp;#34;Dispatcher Asinkron &amp;amp; Multithreading&amp;#34; :a6, after a5, 15d
section &amp;#34;Rilis &amp;amp; Store&amp;#34;
&amp;#34;Pemaketan MSIX &amp;amp; Kapabilitas&amp;#34; :a7, after a6, 10d
&amp;#34;Sertifikasi Microsoft Store&amp;#34; :a8, after a7, 14d
&lt;/pre>
&lt;p>Seperti yang bisa dilihat, sebagian besar waktu pengembangan dihabiskan untuk mengoptimalkan mesin inti (core engine) dan mengintegrasikan pemrosesan asinkron antara WinUI 3 dan C++. Meskipun pengembangan native memiliki biaya persiapan awal dan kurva pembelajaran yang lebih tinggi dibandingkan dengan pengembangan lintas platform, investasi tersebut pasti akan terbayar lunas dalam bentuk performa pada hasil akhirnya.&lt;/p>
&lt;h2 id="3-pemilihan-teknologi-kedalaman-c--winui-3--windows-app-sdk">3. Pemilihan Teknologi: Kedalaman C++ / WinUI 3 / Windows App SDK
&lt;/h2>&lt;p>Dalam pengembangan LogicPad, pemilihan tumpukan teknologi (technology stack) merupakan salah satu keputusan terpenting. Untuk kerangka kerja antarmuka pengguna native di platform Windows, secara historis terdapat berbagai pilihan seperti Win32 API (User32/GDI), MFC, Windows Forms, WPF, dan UWP. Saat ini, Microsoft merekomendasikan &lt;strong>WinUI 3&lt;/strong>, yang dibundel dengan &lt;strong>Windows App SDK&lt;/strong>, untuk pengembangan aplikasi desktop Windows modern.&lt;/p>
&lt;h3 id="31-arsitektur-windows-app-sdk-dan-winui-3">3.1. Arsitektur Windows App SDK dan WinUI 3
&lt;/h3>&lt;p>Windows App SDK adalah sekumpulan pustaka (library) yang menyediakan API Windows terbaru tanpa bergantung pada versi OS. Berbeda dengan UWP (Universal Windows Platform) tradisional yang terikat sangat erat dengan pembaruan sistem operasi (OS), Windows App SDK didistribusikan bersama aplikasinya, sehingga menjamin pengoperasian yang konsisten dari Windows 10 (versi 1809 dan yang lebih baru) hingga Windows 11.&lt;/p>
&lt;p>WinUI 3 adalah kerangka kerja UI native yang berjalan di atas Windows App SDK dan sepenuhnya mendukung Fluent Design System. Bagian internal WinUI 3 dibangun dengan C++ dan DirectX, sehingga berjalan dengan performa yang sangat cepat.&lt;/p>
&lt;h3 id="32-alasan-mengapa-memilih-c-cwinrt-dibandingkan-c">3.2. Alasan Mengapa Memilih C++ (C++/WinRT) Dibandingkan C#
&lt;/h3>&lt;p>WinUI 3 mendukung bahasa C# dan C++ sebagai bahasa pengembangannya. Memang, penggunaan C# dan .NET dapat meningkatkan efisiensi proses pengembangan secara dramatis, akan tetapi LogicPad mengadopsi &lt;strong>C++/WinRT&lt;/strong> karena mempertimbangkan beberapa alasan berikut:&lt;/p>
&lt;ol>
&lt;li>&lt;strong>Manajemen Memori yang Deterministik&lt;/strong>: Dikarenakan tidak ada pengumpul sampah (Garbage Collector), waktu alokasi dan pelepasan memori dapat dikontrol sepenuhnya. Hal ini mencegah terjadinya jeda sementara GC di tengah loop simulasi.&lt;/li>
&lt;li>&lt;strong>SIMD dan Optimasi Cache&lt;/strong>: Di C++, tata letak fisik memori (seperti Struct of Arrays) dapat didefinisikan secara sangat ketat untuk memaksimalkan rasio cache CPU.&lt;/li>
&lt;li>&lt;strong>Batas ABI Native&lt;/strong>: C++/WinRT adalah proyeksi modern bahasa C++ untuk COM (Component Object Model). API native dari OS dapat dipanggil secara langsung tanpa overhead P/Invoke layaknya di C#.&lt;/li>
&lt;/ol>
&lt;p>Fondasi dasar C++/WinRT adalah COM. Semua objek WinRT pada dasarnya adalah objek COM yang mengimplementasikan antarmuka &lt;code>IUnknown&lt;/code>, dan smart pointer dari C++/WinRT seperti &lt;code>winrt::com_ptr&lt;/code> secara otomatis akan mengelola perhitungan jumlah rujukannya atau reference count (&lt;code>AddRef&lt;/code> / &lt;code>Release&lt;/code>).&lt;/p>
&lt;h2 id="4-hambatan-terbesar-dan-terobosan-dalam-pengembangan-winui-3">4. Hambatan Terbesar dan Terobosan dalam Pengembangan WinUI 3
&lt;/h2>&lt;p>Meskipun tangguh, melakukan pengembangan antarmuka WinUI 3 menggunakan C++/WinRT turut dibayangi dengan kerumitan tersendiri. Pada bagian ini, saya akan menerangkan secara detail perihal dua tantangan teknis utama dan paling merepotkan selama pengembangan LogicPad, beserta dengan kunci solusinya.&lt;/p>
&lt;h3 id="41-kengerian-pembaruan-ui-asinkron-di-c-dan-coroutines">4.1. Kengerian Pembaruan UI Asinkron di C++ dan Coroutines
&lt;/h3>&lt;p>Satu aturan mutlak dalam aplikasi UI modern adalah &amp;ldquo;Jangan pernah memblokir thread UI&amp;rdquo;. Di aplikasi LogicPad, operasi simulasi sirkuit raksasa harus dieksekusi melalui thread latar belakang (background thread), dan hasilnya wajib direfleksikan kembali ke thread UI untuk ditampilkan.&lt;/p>
&lt;p>Jika Anda memakai C#, persoalan ini bisa relatif mudah ditanggulangi dengan &lt;code>async/await&lt;/code> dan &lt;code>DispatcherQueue&lt;/code>. Namun, di C++, masalah semacam ini diwujudkan dengan merangkai perpaduan antara Coroutines bawaan C++20 beserta perintah &lt;code>winrt::apartment_context&lt;/code>. Pemahaman wawasan terkait permodelan apartemen COM (STA: Single-Threaded Apartment dan MTA: Multi-Threaded Apartment) sangatlah penting.&lt;/p>
&lt;p>Cuplikan kode di bawah merupakan ekstrak dari basis kode LogicPad yang menunjukkan pola eksekusi sinkronisasi dari operasi background kembali ke thread UI tanpa hambatan:&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;span class="lnt">26
&lt;/span>&lt;span class="lnt">27
&lt;/span>&lt;span class="lnt">28
&lt;/span>&lt;span class="lnt">29
&lt;/span>&lt;span class="lnt">30
&lt;/span>&lt;span class="lnt">31
&lt;/span>&lt;span class="lnt">32
&lt;/span>&lt;span class="lnt">33
&lt;/span>&lt;span class="lnt">34
&lt;/span>&lt;span class="lnt">35
&lt;/span>&lt;span class="lnt">36
&lt;/span>&lt;span class="lnt">37
&lt;/span>&lt;span class="lnt">38
&lt;/span>&lt;span class="lnt">39
&lt;/span>&lt;span class="lnt">40
&lt;/span>&lt;span class="lnt">41
&lt;/span>&lt;span class="lnt">42
&lt;/span>&lt;span class="lnt">43
&lt;/span>&lt;span class="lnt">44
&lt;/span>&lt;span class="lnt">45
&lt;/span>&lt;span class="lnt">46
&lt;/span>&lt;span class="lnt">47
&lt;/span>&lt;span class="lnt">48
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-cpp" data-lang="cpp">&lt;span class="line">&lt;span class="cl">&lt;span class="cp">#include&lt;/span> &lt;span class="cpf">&amp;lt;winrt/Windows.Foundation.h&amp;gt;&lt;/span>&lt;span class="cp">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cp">#include&lt;/span> &lt;span class="cpf">&amp;lt;winrt/Microsoft.UI.Dispatching.h&amp;gt;&lt;/span>&lt;span class="cp">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cp">#include&lt;/span> &lt;span class="cpf">&amp;lt;winrt/Microsoft.UI.Xaml.h&amp;gt;&lt;/span>&lt;span class="cp">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cp">&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">using&lt;/span> &lt;span class="k">namespace&lt;/span> &lt;span class="n">winrt&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">using&lt;/span> &lt;span class="k">namespace&lt;/span> &lt;span class="n">Microsoft&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">UI&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">Xaml&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">using&lt;/span> &lt;span class="k">namespace&lt;/span> &lt;span class="n">Microsoft&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">UI&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">Dispatching&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">// Event handler untuk klik tombol
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span>&lt;span class="n">winrt&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">fire_and_forget&lt;/span> &lt;span class="n">MainWindow&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">OnRunSimulationClicked&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">IInspectable&lt;/span> &lt;span class="k">const&lt;/span>&lt;span class="o">&amp;amp;&lt;/span> &lt;span class="cm">/* sender */&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">RoutedEventArgs&lt;/span> &lt;span class="k">const&lt;/span>&lt;span class="o">&amp;amp;&lt;/span> &lt;span class="cm">/* args */&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// Menangkap konteks apartemen thread UI saat ini (STA)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">winrt&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">apartment_context&lt;/span> &lt;span class="n">ui_thread&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">try&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// Memperbarui status UI (dieksekusi di thread UI)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">StatusTextBlock&lt;/span>&lt;span class="p">().&lt;/span>&lt;span class="n">Text&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">L&lt;/span>&lt;span class="s">&amp;#34;Sedang menjalankan simulasi...&amp;#34;&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">ProgressBar&lt;/span>&lt;span class="p">().&lt;/span>&lt;span class="n">IsIndeterminate&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="nb">true&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// Memindahkan konteks ke pool thread (MTA)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="k">co_await&lt;/span> &lt;span class="n">winrt&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">resume_background&lt;/span>&lt;span class="p">();&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// Proses simulasi yang sangat berat (dieksekusi di thread latar belakang)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="c1">// Selama waktu ini, thread UI dibebaskan sehingga mencegah aplikasi membeku (freeze)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">vector&lt;/span>&lt;span class="o">&amp;lt;&lt;/span>&lt;span class="n">LogicResult&lt;/span>&lt;span class="o">&amp;gt;&lt;/span> &lt;span class="n">results&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">CoreEngine&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">RunMassiveSimulation&lt;/span>&lt;span class="p">();&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// Memformat hasil simulasi menjadi string (terus dieksekusi di latar belakang)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">winrt&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">hstring&lt;/span> &lt;span class="n">outputText&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">FormatResults&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">results&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// Mengembalikan konteks ke thread UI
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="k">co_await&lt;/span> &lt;span class="n">ui_thread&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// Proses setelah ini dieksekusi di thread UI, sehingga aman untuk mengakses kontrol XAML
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">ResultTextBlock&lt;/span>&lt;span class="p">().&lt;/span>&lt;span class="n">Text&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">outputText&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">ProgressBar&lt;/span>&lt;span class="p">().&lt;/span>&lt;span class="n">IsIndeterminate&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="nb">false&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">StatusTextBlock&lt;/span>&lt;span class="p">().&lt;/span>&lt;span class="n">Text&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">L&lt;/span>&lt;span class="s">&amp;#34;Selesai&amp;#34;&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">catch&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">winrt&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">hresult_error&lt;/span> &lt;span class="k">const&lt;/span>&lt;span class="o">&amp;amp;&lt;/span> &lt;span class="n">ex&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// Bahkan saat terjadi exception (pengecualian), kembali ke thread UI untuk menampilkan pesan kesalahan
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="k">co_await&lt;/span> &lt;span class="n">ui_thread&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">StatusTextBlock&lt;/span>&lt;span class="p">().&lt;/span>&lt;span class="n">Text&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">L&lt;/span>&lt;span class="s">&amp;#34;Kesalahan: &amp;#34;&lt;/span> &lt;span class="o">+&lt;/span> &lt;span class="n">ex&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">message&lt;/span>&lt;span class="p">());&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">ProgressBar&lt;/span>&lt;span class="p">().&lt;/span>&lt;span class="n">IsIndeterminate&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="nb">false&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Meskipun perilaku dari &lt;code>winrt::apartment_context&lt;/code> terkesan seperti tipuan sulap, secara internal ia bekerja berdasarkan sistem C++ tingkat lanjut yang mendispatch eksekusi ke antarmuka &lt;code>IContextCallback&lt;/code> yang bertugas untuk mengingat konteks thread asalnya, lalu menjalankan proses ke konteks tersebut manakala perintah &lt;code>co_await&lt;/code> tereksekusi. Inilah alasan mengapa kita dapat menulis pemrosesan asinkron memakai gaya prosedural lazim tanpa khawatir harus jatuh ke dalam &amp;ldquo;callback hell&amp;rdquo;.&lt;/p>
&lt;h3 id="42-implementasi-lengkap-bilah-judul-kustom">4.2. Implementasi Lengkap Bilah Judul Kustom
&lt;/h3>&lt;p>Untuk aplikasi era Windows 11, &amp;ldquo;bilah judul kustom&amp;rdquo; yang dapat menempatkan tab maupun kotak pencarian langsung pada bilah judul (caption bar) merupakan salah satu persyaratan UX yang modern. Meskipun sangat gampang jika kita berniat mengganti tampilan warnanya di WinUI 3, tantangannya bakal berubah sangat dramatis jika kita bermaksud &amp;ldquo;memperluas area klien ke bilah judul dengan tetap mempertahankan penarikan jendela (drag) dan snap layout otomatis saat diseret ke tepi layar&amp;rdquo;.&lt;/p>
&lt;p>Di LogicPad, area bilah judul tersebut kami bangun dengan elemen UI XAML menggunakan API &lt;code>ExtendsContentIntoTitleBar&lt;/code>. Kode di bawah menjabarkan langkah teknis untuk mengkustomisasi bilah judul menggunakan utilitas &lt;code>AppWindow&lt;/code> dari Windows App SDK.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;span class="lnt">26
&lt;/span>&lt;span class="lnt">27
&lt;/span>&lt;span class="lnt">28
&lt;/span>&lt;span class="lnt">29
&lt;/span>&lt;span class="lnt">30
&lt;/span>&lt;span class="lnt">31
&lt;/span>&lt;span class="lnt">32
&lt;/span>&lt;span class="lnt">33
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-cpp" data-lang="cpp">&lt;span class="line">&lt;span class="cl">&lt;span class="cp">#include&lt;/span> &lt;span class="cpf">&amp;lt;winrt/Microsoft.UI.Windowing.h&amp;gt;&lt;/span>&lt;span class="cp">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cp">#include&lt;/span> &lt;span class="cpf">&amp;lt;winrt/Microsoft.UI.Interop.h&amp;gt;&lt;/span>&lt;span class="cp">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cp">#include&lt;/span> &lt;span class="cpf">&amp;lt;microsoft.ui.interop.h&amp;gt;&lt;/span>&lt;span class="cp"> &lt;/span>&lt;span class="c1">// untuk GetWindowIdFromWindow
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kt">void&lt;/span> &lt;span class="n">MainWindow&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">InitializeCustomTitleBar&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// Mengambil HWND (handle jendela) dari jendela saat ini
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="k">auto&lt;/span> &lt;span class="n">windowNative&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="k">this&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">try_as&lt;/span>&lt;span class="o">&amp;lt;::&lt;/span>&lt;span class="n">IWindowNative&lt;/span>&lt;span class="o">&amp;gt;&lt;/span>&lt;span class="p">();&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">HWND&lt;/span> &lt;span class="n">hwnd&lt;/span>&lt;span class="p">{&lt;/span> &lt;span class="k">nullptr&lt;/span> &lt;span class="p">};&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">windowNative&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">get_WindowHandle&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="o">&amp;amp;&lt;/span>&lt;span class="n">hwnd&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// Mengonversi HWND ke WindowId dan memperoleh instans AppWindow
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">winrt&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">Microsoft&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">UI&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">WindowId&lt;/span> &lt;span class="n">windowId&lt;/span> &lt;span class="o">=&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">winrt&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">Microsoft&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">UI&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">GetWindowIdFromWindow&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">hwnd&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">auto&lt;/span> &lt;span class="n">appWindow&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">winrt&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">Microsoft&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">UI&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">Windowing&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">AppWindow&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">GetFromWindowId&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">windowId&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// Memeriksa apakah versi OS mendukung kustomisasi
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">winrt&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">Microsoft&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">UI&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">Windowing&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">AppWindowTitleBar&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">IsCustomizationSupported&lt;/span>&lt;span class="p">())&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">auto&lt;/span> &lt;span class="n">titleBar&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">appWindow&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">TitleBar&lt;/span>&lt;span class="p">();&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// Memperluas area klien (konten) ke dalam bilah judul
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">titleBar&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">ExtendsContentIntoTitleBar&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="nb">true&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// Mengatur latar belakang tombol keterangan bawaan (minimize, maximize, close) menjadi transparan
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">titleBar&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">ButtonBackgroundColor&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">winrt&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">Microsoft&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">UI&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">Colors&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">Transparent&lt;/span>&lt;span class="p">());&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">titleBar&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">ButtonInactiveBackgroundColor&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">winrt&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">Microsoft&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">UI&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">Colors&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">Transparent&lt;/span>&lt;span class="p">());&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// Mengonfigurasi elemen UI (AppTitleBar) yang ditentukan dalam XAML sebagai area seret (drag)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="c1">// ※ Untuk detail pada bagian ini, Anda perlu memantau UIElement di sisi XAML dengan Dispatcher thread UI,
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="c1">// lalu memanggil SetDragRectangles() untuk memberitahukan kepada OS ihwal area yang bisa ditarik.
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Jebakan ranjau paling fatal pada implementasi ini adalah setiap kali ukuran elemen UI di sisi XAML berubah (seperti ketika ukuran jendela diubah pengguna), kita diwajibkan untuk melaporkan pengujian kalkulasi titik koordinat (Hit Test Area), dengan memanggil fungsi &lt;code>InputNonClientPointerSource&lt;/code> atau &lt;code>SetDragRectangles&lt;/code> untuk mencatatkan ke OS bahwa &amp;ldquo;koordinat ini masih merupakan wilayah operasional untuk menarik aplikasi&amp;rdquo;. Jika hal ini diabaikan, niscaya akan memancing berbagai bug, seperti macetnya fungsi jendela yang enggan digeser meskipun ditarik dari bilah judul, atau sebaliknya, klik pada suatu tombol kontrol justru salah ditafsirkan sebagai gestur penarikan bingkai jendela.&lt;/p>
&lt;h2 id="5-kedalaman-pemaketan-msix-dan-appxmanifest">5. Kedalaman Pemaketan MSIX dan AppXManifest
&lt;/h2>&lt;p>Untuk mendistribusikan LogicPad setelah proyeknya selesai, saya harus membuat installer. Ketimbang mengandalkan model installer format lama seperti MSI atau EXE, saya mengadopsi format instalasi modern &lt;strong>MSIX&lt;/strong>. MSIX memberikan rasa aman bagi pengguna karena proses instalasi dan penghapusan aplikasi (uninstall) terlaksana secara sangat bersih (tanpa mengotori registry), dan dilengkapi dengan sistem pembaruan otomatis.&lt;/p>
&lt;p>Akan tetapi, poin utama di antara hal krusial saat memaketkan aplikasi native C++ menjadi paket MSIX terletak di dalam file manifest yaitu &lt;code>Package.appxmanifest&lt;/code>.&lt;/p>
&lt;p>LogicPad perlu membaca dan menulis file proyek sirkuit berskala raksasa pada sistem file lokal pengguna (misalnya dokumen lokal). Dalam standar isolasi (sandbox) platform UWP, aplikasi hanya diberi akses membaca data pada bilik terisolasinya sendiri (AppContainer). Maka sebab itu, demi mendapatkan hak akses penuh selayaknya aplikasi desktop native, pengembang harus mendaftarkan perizinan &lt;code>runFullTrust&lt;/code> di dalam file manifest.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;span class="lnt">26
&lt;/span>&lt;span class="lnt">27
&lt;/span>&lt;span class="lnt">28
&lt;/span>&lt;span class="lnt">29
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-xml" data-lang="xml">&lt;span class="line">&lt;span class="cl">&lt;span class="cp">&amp;lt;?xml version=&amp;#34;1.0&amp;#34; encoding=&amp;#34;utf-8&amp;#34;?&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nt">&amp;lt;Package&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="na">xmlns=&lt;/span>&lt;span class="s">&amp;#34;http://schemas.microsoft.com/appx/manifest/foundation/windows10&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="na">xmlns:uap=&lt;/span>&lt;span class="s">&amp;#34;http://schemas.microsoft.com/appx/manifest/uap/windows10&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="na">xmlns:rescap=&lt;/span>&lt;span class="s">&amp;#34;http://schemas.microsoft.com/appx/manifest/foundation/windows10/restrictedcapabilities&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="na">IgnorableNamespaces=&lt;/span>&lt;span class="s">&amp;#34;uap rescap&amp;#34;&lt;/span>&lt;span class="nt">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;lt;Identity&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="na">Name=&lt;/span>&lt;span class="s">&amp;#34;LogicPad.Studio&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="na">Publisher=&lt;/span>&lt;span class="s">&amp;#34;CN=Kenji&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="na">Version=&lt;/span>&lt;span class="s">&amp;#34;1.0.0.0&amp;#34;&lt;/span> &lt;span class="nt">/&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;lt;Properties&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;lt;DisplayName&amp;gt;&lt;/span>LogicPad&lt;span class="nt">&amp;lt;/DisplayName&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;lt;PublisherDisplayName&amp;gt;&lt;/span>Kenji&lt;span class="nt">&amp;lt;/PublisherDisplayName&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;lt;Logo&amp;gt;&lt;/span>Assets\StoreLogo.png&lt;span class="nt">&amp;lt;/Logo&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;lt;/Properties&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;lt;Dependencies&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;lt;TargetDeviceFamily&lt;/span> &lt;span class="na">Name=&lt;/span>&lt;span class="s">&amp;#34;Windows.Desktop&amp;#34;&lt;/span> &lt;span class="na">MinVersion=&lt;/span>&lt;span class="s">&amp;#34;10.0.17763.0&amp;#34;&lt;/span> &lt;span class="na">MaxVersionTested=&lt;/span>&lt;span class="s">&amp;#34;10.0.22621.0&amp;#34;&lt;/span> &lt;span class="nt">/&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;lt;/Dependencies&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;lt;Capabilities&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c">&amp;lt;!-- Kapabilitas umum --&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;lt;Capability&lt;/span> &lt;span class="na">Name=&lt;/span>&lt;span class="s">&amp;#34;internetClient&amp;#34;&lt;/span> &lt;span class="nt">/&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c">&amp;lt;!-- Kapabilitas terbatas agar dapat berjalan sebagai aplikasi desktop native --&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;lt;rescap:Capability&lt;/span> &lt;span class="na">Name=&lt;/span>&lt;span class="s">&amp;#34;runFullTrust&amp;#34;&lt;/span> &lt;span class="nt">/&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;lt;/Capabilities&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nt">&amp;lt;/Package&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Baris kode &lt;code>&amp;lt;rescap:Capability Name=&amp;quot;runFullTrust&amp;quot; /&amp;gt;&lt;/code> ini disebut fitur &amp;ldquo;Kapabilitas Terbatas (Restricted Capability)&amp;rdquo;, dan ketika mengirimkannya ke Microsoft Store, pembuat harus menyertakan dokumen alasan untuk membenarkan tuntutan hak khusus tersebut kepada peninjau. Saya menjelaskan, &amp;ldquo;Aplikasi ini adalah alat untuk profesional guna membaca, menulis, dan mengekspor proyek sirkuit logika sembarang di dalam penyimpanan lokal pengguna,&amp;rdquo; dan dari situ persetujuan pun didapat tanpa kendala.&lt;/p>
&lt;h2 id="6-jalan-menuju-microsoft-store-dan-proses-peninjauan">6. Jalan Menuju Microsoft Store dan Proses Peninjauan
&lt;/h2>&lt;p>Usai sesi kompilasi dan pemaketan bundle MSIX selesai dikerjakan, tiba saatnya menyerahkan aplikasi ke Microsoft Store. Dari kacamata pengembang individu, distribusi melalui wadah resmi Store memberikan keuntungan tidak ternilai, meliputi pembaruan otomatis yang andal, jaminan kualitas pada kredibilitas aplikasi, dan sokongan sistem pembayaran yang praktis.&lt;/p>
&lt;p>Proses penyerahan ke Microsoft Store diselenggarakan lewat rute portal &amp;ldquo;Partner Center&amp;rdquo;. Diagram di bawah menunjukkan gambaran kasar dari awal kompilasi hingga rilis publik.&lt;/p>
&lt;pre class="mermaid">
flowchart TD
A[&amp;#34;Pengembang (Visual Studio)&amp;#34;] --&amp;gt;|Build &amp;amp; Sign| B[&amp;#34;Pembuatan Bundle MSIX&amp;#34;]
B --&amp;gt; C[&amp;#34;Windows App Certification Kit (WACK)&amp;#34;]
C --&amp;gt;|Lulus| D[&amp;#34;Dasbor Partner Center&amp;#34;]
C --&amp;gt;|Gagal| E[&amp;#34;Perbaiki Masalah Kode / Manifest&amp;#34;]
E --&amp;gt; A
D --&amp;gt;|Unggah Paket| F[&amp;#34;Proses Sertifikasi Store&amp;#34;]
F --&amp;gt; G[&amp;#34;Pemindaian Malware Otomatis&amp;#34;]
G --&amp;gt; H[&amp;#34;Peninjauan Konten Manual&amp;#34;]
H --&amp;gt;|Disetujui| I[&amp;#34;Penerbitan ke Microsoft Store&amp;#34;]
H --&amp;gt;|Ditolak| J[&amp;#34;Atasi Umpan Balik &amp;amp; Kirim Ulang&amp;#34;]
J --&amp;gt; D
I --&amp;gt; K[&amp;#34;Aplikasi Dirilis!&amp;#34;]
&lt;/pre>
&lt;h3 id="61-dinding-wack-windows-app-certification-kit">6.1. Dinding WACK (Windows App Certification Kit)
&lt;/h3>&lt;p>Sebelum mengunggah berkas ke Partner Center, kita diwajibkan melaksanakan serangkaian pengujian lokal yakni &lt;strong>WACK (Windows App Certification Kit)&lt;/strong>. Peranti utilitas ini mengemban tugas otonom demi memindai secara otomatis apakah program yang dirilis bebas dari crash, terhindar dari panggilan yang tak didukung melalui sistem API, serta memenuhi persyaratan kinerja minimal.&lt;/p>
&lt;p>Kala berhadapan dengan aplikasi berarsitektur C++ native, hal yang sangat perlu mendapat perhatian khusus adalah notifikasi error &amp;ldquo;Penggunaan API yang tidak didukung&amp;rdquo;. Saat kita memaksakan integrasi (statically link) pustaka lawas usang produksi pihak ketiga C++, pustaka ini sering ketahuan menggunakan panggilan Win32 API kuno di dalam sistemnya yang akan ditolak oleh sistem WACK. Untuk menghindari masalah ini, saya sigap memperbarui pustaka dependensi dengan rilis terbarunya dan memodifikasi sebagian fungsi ke alternatif API pada Windows App SDK.&lt;/p>
&lt;h3 id="62-peninjauan-dan-penerbitan">6.2. Peninjauan dan Penerbitan
&lt;/h3>&lt;p>Dalam pengaturan Partner Center, ini mencakup penetapan nominal biaya aplikasi, rating klasifikasi penggolongan rentang usia (rating IARC), menyertakan tangkapan gambar layar (screenshot) dan penulisan catatan deskripsi ke dalam etalase Store. Mengingat LogicPad murni dibuat sebagai alat teknis, secara serta-merta ia memperoleh izin rating untuk semua umur (All Ages).&lt;/p>
&lt;p>Selang beberapa hari kalender semenjak pengajuan, proses rilis ini rampung direview dalam durasi tiga hari kerja. Sesudah melewati pemindaian malware dan pengetesan fungsionalitas otomatis, perwakilan Microsoft memeriksa aplikasi secara manual. Permintaan kapabilitas &lt;code>runFullTrust&lt;/code> berhasil disetujui tanpa ada kendala. Rasa sukacita meluap tak tertahankan sesaat melihat rentetan tulisan status rilis telah mencapai status &amp;ldquo;Dipublikasikan (In the Store)&amp;rdquo;, kepuasan dari pencapaian yang tidak dapat digantikan oleh nilai apa pun.&lt;/p>
&lt;h2 id="7-pengembangan-individu-sebagai-bisnis-model-matematis-kinerja-dan-pendapatan">7. Pengembangan Individu Sebagai Bisnis: Model Matematis Kinerja dan Pendapatan
&lt;/h2>&lt;p>Alih-alih sekadar merasa puas setelah membuat sebuah aplikasi, untuk terus menghadirkan pembaruan LogicPad dan menjadikannya bisnis mandiri, diperlukan langkah pengukuran mengevaluasi spesifikasi secara teknis dan juga model komersialisasi secara kuantitatif.&lt;/p>
&lt;h3 id="71-model-optimalisasi-penggunaan-memori-berkat-bahasa-c">7.1. Model Optimalisasi Penggunaan Memori Berkat Bahasa C++
&lt;/h3>&lt;p>Keunggulan utama LogicPad terletak pada aspeknya yang sangat luar biasa ringan bila dibandingkan dengan aplikasi editor bersenjatakan mesin Electron (contohnya: VSCode). Skema rumus matematika rasio jejak pemakaian memori aplikasi (Memory Footprint), $M_{total}$, dapat dijabarkan seperti model formula berikut:&lt;/p>
$$
M_{total} = M_{UI} + M_{engine} + M_{cache}
$$&lt;p>Di sini, alokasi memori pada antarmuka $M_{UI}$, berkat bantuan sistem native rendering bawaan dari WinUI 3, sukses menghasilkan penghematan ukuran dimensi memori yang luar biasa drastis menyusut, jauh lebih efisien dibandingkan mesin Electron yang memakan beban untuk memuat engine peramban (kira-kira di batas 50MB saja).
Tambahan lagi, kapasitas memori untuk engine C++, $M_{engine}$, bertumbuh dengan skala ekuivalen linear sejajar terhadap akumulasi kuantitas komponen gerbang logikanya $N$, ini semua diraih dari optimasi struct dan meminimalisasi sistem alokasi pointer di dalamnya.&lt;/p>
$$
M_{engine} = N \times \text{sizeof(LogicNode)}
$$&lt;p>Dengan mendayagunakan kemampuan sintaks &lt;code>#pragma pack&lt;/code> C++ guna memadatkan penjajaran struktur ruang memori (struct alignment), sayapun mengukir kemampuan mumpuni dalam memangkas pemakaian sisa batas ketersediaan kuota memori per simpul (node) ke batas yang sekecil-kecilnya.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;span class="lnt">6
&lt;/span>&lt;span class="lnt">7
&lt;/span>&lt;span class="lnt">8
&lt;/span>&lt;span class="lnt">9
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-cpp" data-lang="cpp">&lt;span class="line">&lt;span class="cl">&lt;span class="cp">#pragma pack(push, 1)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cp">&lt;/span>&lt;span class="c1">// Meminimalkan memori dengan memaketkan tanpa tabel fungsi virtual (vtable)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span>&lt;span class="k">struct&lt;/span> &lt;span class="nc">LogicNode&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kt">uint32_t&lt;/span> &lt;span class="n">id&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="c1">// 4 bytes
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="kt">uint16_t&lt;/span> &lt;span class="n">type&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="c1">// 2 bytes
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="kt">bool&lt;/span> &lt;span class="n">isActive&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="c1">// 1 byte
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="c1">// Ukuran struktur adalah 7 byte (tanpa padding alignment)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span>&lt;span class="p">};&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cp">#pragma pack(pop)
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Sedangkan memori pada lapisan cache $M_{cache}$ bertugas menampung riwayat simulasi, yang jejak pembengkakannya wajib naik eksponensial sebanding $\mathcal{O}(N \log N)$, namun terlepas dari itu, karena jejak dasar awal memory footprint asalnya memang sangat ringan, konsumsi puncak batas memori pada RAM dari aplikasi ini dapat dikunci dalam nilai aman di bawah batas 200MB, sungguhpun meski dalam keadaan diuji menampung simulasi masif dari puluhan ribu struktur nodus logika sirkuit.&lt;/p>
&lt;h3 id="72-ltv-dan-cac-rencana-pemasaran">7.2. LTV dan CAC: Rencana Pemasaran
&lt;/h3>&lt;p>Dalam strategi monetisasi untuk pengembangan individu, keseimbangan antara Nilai Seumur Hidup Pelanggan (LTV: Lifetime Value) dan Biaya Akuisisi Pelanggan (CAC: Customer Acquisition Cost) adalah segalanya. LogicPad mengadopsi model lisensi pembelian sekali bayar (freemium), alih-alih langganan (subscription).&lt;/p>
&lt;p>LTV dihitung sebagai jumlah nilai sekarang dari probabilitas pembelian versi pemutakhiran (upgrade) di masa depan yang didiskon dengan rasio diskon $d$. Jika periode adalah $T$, itu dapat dinyatakan dengan rumus berikut:&lt;/p>
$$
LTV = \sum_{t=1}^{T} \frac{ARPU_t \times Margin}{(1+d)^t}
$$&lt;p>Di sisi lain, CAC adalah total biaya pemasaran, seperti iklan di Twitter (sekarang X) dan kunjungan dari artikel blog, dibagi dengan jumlah pengguna baru.&lt;/p>
$$
CAC = \frac{Total\ Marketing\ Spend}{Number\ of\ New\ Users}
$$&lt;p>Kekuatan dari pengembangan individu adalah biaya tenaga kerja pengembangan dapat dianggap sebagai biaya hangus (sunk cost) untuk &amp;ldquo;waktu hobi&amp;rdquo;, sehingga CAC murni hanya bergantung pada perhitungan biaya pemasaran saja. Saat ini, berkat aliran organik yang terutama bersumber dari rekomendasi mulut ke mulut pada komunitas ceruk teknologi (niche), ekonomi unit LTV &amp;gt; CAC yang sehat dapat diwujudkan di mana nilai CAC mendekati $CAC \approx 0$.&lt;/p>
&lt;h2 id="8-penutup-dunia-pengembangan-aplikasi-native-yang-kasar-namun-indah">8. Penutup: Dunia Pengembangan Aplikasi Native yang Kasar Namun Indah
&lt;/h2>&lt;p>Saat mengenang kembali perjalanan mulai dari perancangan LogicPad hingga peluncurannya di Microsoft Store, ini bukanlah jalan yang mulus. Terus-menerus bergelut dengan pesan galat (error) kompilasi C++/WinRT yang rumit, melacak kebocoran memori (memory leak) yang diakibatkan oleh bug penghitungan referensi pada COM, serta meneliti spesifikasi XML pada manifest MSIX.&lt;/p>
&lt;p>Justru di era ketika teknologi web kian canggih di mana &amp;ldquo;apa pun bisa dibangun di dalam browser&amp;rdquo;, pengalaman pengembangan native dengan secara langsung menyentuh perintah OS API serta mencermati alokasi ruang memori per 1 byte dan merawat efisiensi clock CPU 1 siklus, mampu meroketkan kekuatan pemahaman dasar seseorang sebagai engineer secara amat drastis.&lt;/p>
&lt;p>WinUI 3 dan Windows App SDK saat ini sedang dikembangkan secara aktif dan masih merupakan alat terhebat guna membangun sebuah aplikasi native desktop Windows yang mempesona, secara maksimal memanfaatkan paradigma antarmuka Windows 11. Besar sekali harapan dan impian saya bahwa artikel blog teknis ini nantinya mampu menjadi panduan bagi para pengembang yang ingin menantang diri dalam pengembangan aplikasi Windows native, supaya ke depannya akan kian lahir melimpah ruah ragam variasi perangkat hebat di Store.&lt;/p>
&lt;p>Pengembangan belumlah selesai. Di versi LogicPad selanjutnya, saya merencanakan untuk menggabungkan fungsi mesin perenderan bentuk gelombang kustom yang memanfaatkan fitur Direct2D. Pada artikel sekuel selanjutnya, saya akan membahas sisi interoperabilitas integrasi perpaduan antara DirectX dan utilitas WinUI 3 (penggunaan SwapChainPanel). Harap nantikan.&lt;/p></description></item></channel></rss>