<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Personal Project on kenji.blog</title><link>http://kenji.blog/pt/tags/personal-project/</link><description>Recent content in Personal Project on kenji.blog</description><generator>Hugo -- gohugo.io</generator><language>pt</language><copyright>kenjinote</copyright><lastBuildDate>Sun, 13 Sep 2026 04:00:00 +0900</lastBuildDate><atom:link href="http://kenji.blog/pt/tags/personal-project/index.xml" rel="self" type="application/rss+xml"/><item><title>Aprendendo com o desenvolvimento do LogicPad: A trajetória até o lançamento de um aplicativo Windows de desenvolvimento pessoal</title><link>http://kenji.blog/pt/p/logicpad-windows-app-development-journey/</link><pubDate>Sun, 13 Sep 2026 04:00:00 +0900</pubDate><guid>http://kenji.blog/pt/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 Aprendendo com o desenvolvimento do LogicPad: A trajetória até o lançamento de um aplicativo Windows de desenvolvimento pessoal" />&lt;h2 id="1-introdução-por-que-ousar-criar-um-aplicativo-nativo-para-windows-hoje-em-dia">1. Introdução: Por que ousar criar um aplicativo nativo para Windows hoje em dia?
&lt;/h2>&lt;p>No desenvolvimento moderno de aplicativos, não há dúvida de que as tecnologias multiplataforma, como Electron, Tauri e React Native, se tornaram a norma. A abordagem &amp;ldquo;escreva uma vez, rode em qualquer lugar&amp;rdquo; (Write Once, Run Anywhere) usando tecnologias web é muito racional do ponto de vista da velocidade de desenvolvimento e facilidade de manutenção. No entanto, decidi ousar e escolher o caminho do desenvolvimento de um aplicativo chamado &amp;ldquo;LogicPad&amp;rdquo; como um aplicativo nativo totalmente otimizado para o Windows.&lt;/p>
&lt;p>O LogicPad é um simulador de circuitos lógicos digitais e editor de texto voltado para engenheiros de hardware e estudantes de circuitos lógicos. Ele precisa simular dezenas de milhares de portas lógicas em tempo real e, simultaneamente, renderizar dados complexos de forma de onda sem nenhum atraso. Em um domínio que exige essa performance extrema, uma pausa de alguns milissegundos causada pela coleta de lixo (micro-stutter) ou a sobrecarga de renderização de um web view levam a uma degradação fatal da experiência do usuário.&lt;/p>
&lt;p>Neste artigo, vou relembrar a trajetória, junto com uma explicação técnica bastante detalhada, desde a concepção do desenvolvimento do LogicPad, a implementação usando C++ e WinUI 3 (Windows App SDK), a superação de barreiras técnicas específicas, o empacotamento MSIX, até a distribuição mundial por meio da Microsoft Store. Ao compartilhar o processo de como um desenvolvedor individual pode criar um aplicativo nativo do Windows com qualidade corporativa, espero que isso sirva de guia para aqueles que também desejam enfrentar o desafio do desenvolvimento nativo.&lt;/p>
&lt;h2 id="2-cronograma-do-projeto">2. Cronograma do Projeto
&lt;/h2>&lt;p>O desenvolvimento do LogicPad prosseguiu como um projeto pessoal, aproveitando os fins de semana e as noites. O cronograma geral durou cerca de meio ano (6 meses). Abaixo está um gráfico de Gantt que mostra o progresso do projeto.&lt;/p>
&lt;pre class="mermaid">
gantt
title Cronograma de Desenvolvimento do LogicPad
dateFormat YYYY-MM-DD
section &amp;#34;Planejamento e Design&amp;#34;
&amp;#34;Análise de Requisitos e Prototipagem&amp;#34; :a1, 2025-10-01, 30d
&amp;#34;Design de Arquitetura (Núcleo C++)&amp;#34; :a2, after a1, 20d
section &amp;#34;Desenvolvimento do Núcleo&amp;#34;
&amp;#34;Motor de Simulação (C++)&amp;#34; :a3, after a2, 45d
&amp;#34;Integração WinUI 3 XAML&amp;#34; :a4, after a3, 40d
section &amp;#34;Refinamento de UI/UX&amp;#34;
&amp;#34;Barra de Título Personalizada e Janelas&amp;#34; :a5, after a4, 15d
&amp;#34;Dispatcher Assíncrono e Multithreading&amp;#34; :a6, after a5, 15d
section &amp;#34;Lançamento e Loja&amp;#34;
&amp;#34;Empacotamento MSIX e Capacidades&amp;#34; :a7, after a6, 10d
&amp;#34;Certificação da Microsoft Store&amp;#34; :a8, after a7, 14d
&lt;/pre>
&lt;p>Como pode ser visto, a maior parte do tempo de desenvolvimento foi gasta na otimização do motor principal e na integração do processamento assíncrono entre o WinUI 3 e o C++. Embora o desenvolvimento nativo tenha uma configuração inicial e curva de aprendizado maiores em comparação com o desenvolvimento multiplataforma, esse investimento certamente tem retorno garantido na forma do desempenho final.&lt;/p>
&lt;h2 id="3-seleção-de-tecnologia-as-profundezas-do-c--winui-3--windows-app-sdk">3. Seleção de Tecnologia: As Profundezas do C++ / WinUI 3 / Windows App SDK
&lt;/h2>&lt;p>Ao desenvolver o LogicPad, a seleção da pilha de tecnologia foi uma das decisões mais importantes. Historicamente, existem várias opções para frameworks de UI nativos na plataforma Windows, como Win32 API (User32/GDI), MFC, Windows Forms, WPF e UWP. Atualmente, a Microsoft recomenda o &lt;strong>WinUI 3&lt;/strong>, que está incluído no &lt;strong>Windows App SDK&lt;/strong>, para o desenvolvimento moderno de aplicativos de desktop do Windows.&lt;/p>
&lt;h3 id="31-arquitetura-do-windows-app-sdk-e-winui-3">3.1. Arquitetura do Windows App SDK e WinUI 3
&lt;/h3>&lt;p>O Windows App SDK é um conjunto de bibliotecas para fornecer as APIs mais recentes do Windows, independentemente da versão do sistema operacional. Ao contrário da antiga UWP (Universal Windows Platform), que estava fortemente vinculada às atualizações do sistema operacional, o Windows App SDK é distribuído junto com o aplicativo, garantindo uma operação consistente desde o Windows 10 (versão 1809 e posterior) até o Windows 11.&lt;/p>
&lt;p>O WinUI 3 é um framework de interface de usuário nativo que funciona sobre este Windows App SDK e suporta totalmente o Fluent Design System. Os componentes internos do WinUI 3 são construídos em C++ e DirectX, operando com extrema rapidez.&lt;/p>
&lt;h3 id="32-por-que-ousar-escolher-c-cwinrt-em-vez-de-c">3.2. Por que ousar escolher C++ (C++/WinRT) em vez de C#
&lt;/h3>&lt;p>O WinUI 3 suporta C# e C++ como linguagens de desenvolvimento. Se você usar C# e .NET, a eficiência de desenvolvimento melhorará drasticamente, mas eu adotei &lt;strong>C++/WinRT&lt;/strong> no LogicPad pelas seguintes razões:&lt;/p>
&lt;ol>
&lt;li>&lt;strong>Gerenciamento de memória determinístico&lt;/strong>: Como não há coletor de lixo (GC), você pode controlar totalmente o tempo de alocação e liberação de memória. Isso evita pausas do GC durante o loop de simulação.&lt;/li>
&lt;li>&lt;strong>Otimização de SIMD e cache&lt;/strong>: Em C++, o layout físico da memória (como Struct of Arrays) pode ser estritamente definido, permitindo maximizar a taxa de acertos de cache da CPU.&lt;/li>
&lt;li>&lt;strong>Fronteira ABI nativa&lt;/strong>: O C++/WinRT é uma projeção C++ moderna do COM (Component Object Model). Ele permite chamar APIs nativas do sistema operacional diretamente sem a sobrecarga do P/Invoke encontrado em C#.&lt;/li>
&lt;/ol>
&lt;p>A base do C++/WinRT é o COM. Todos os objetos WinRT são essencialmente objetos COM que implementam a interface &lt;code>IUnknown&lt;/code>, e os ponteiros inteligentes do C++/WinRT, como &lt;code>winrt::com_ptr&lt;/code>, gerenciam automaticamente a contagem de referências (&lt;code>AddRef&lt;/code> / &lt;code>Release&lt;/code>).&lt;/p>
&lt;h2 id="4-a-maior-barreira-no-desenvolvimento-do-winui-3-e-sua-solução">4. A Maior Barreira no Desenvolvimento do WinUI 3 e sua Solução
&lt;/h2>&lt;p>O desenvolvimento do WinUI 3 usando C++/WinRT é poderoso, mas traz suas próprias complexidades. Aqui, explicarei detalhadamente os dois maiores desafios técnicos enfrentados durante o desenvolvimento do LogicPad e suas respectivas soluções.&lt;/p>
&lt;h3 id="41-o-terror-das-atualizações-de-ui-assíncronas-e-as-corrotinas-no-c">4.1. O Terror das Atualizações de UI Assíncronas e as Corrotinas no C++
&lt;/h3>&lt;p>A regra de ouro dos aplicativos de UI modernos é: &amp;ldquo;Você não deve bloquear a thread da UI&amp;rdquo;. No LogicPad, é necessário realizar cálculos massivos de simulação de circuitos em uma thread em segundo plano e refletir esses resultados na thread da UI.&lt;/p>
&lt;p>No C#, isso poderia ser descrito com relativa facilidade usando &lt;code>async/await&lt;/code> e &lt;code>DispatcherQueue&lt;/code>, mas no C++ isso é alcançado combinando corrotinas (Coroutines) do C++20 com o &lt;code>winrt::apartment_context&lt;/code>. Compreender os modelos de apartment do COM (STA: Single-Threaded Apartment e MTA: Multi-Threaded Apartment) é essencial.&lt;/p>
&lt;p>O código abaixo é extraído da base de código real do LogicPad e demonstra o padrão de execução suave para executar processos em segundo plano e retornar para a thread da UI.&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">// Manipulador de evento de clique de botão
&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">// Captura o contexto do apartment (STA) da thread da UI atual
&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">// Atualiza o status da UI (isso é executado na thread da 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;Simulação em execução...&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">// Migra o contexto para o pool de threads (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">// Processo de simulação muito pesado (executado na thread em segundo plano)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="c1">// Durante esse tempo, a thread da UI é liberada, o que evita o congelamento do aplicativo
&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">// Formata os resultados da simulação para uma string (continua em segundo plano)
&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">// Retorna o contexto para a thread da 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">// Como o restante será executado na thread da UI, os controles XAML podem ser acessados com segurança
&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;Concluído&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">// Se ocorrer uma exceção, retorne para a thread da UI e mostre uma mensagem de erro
&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;Erro: &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>O comportamento deste &lt;code>winrt::apartment_context&lt;/code> parece mágico, mas internamente, um mecanismo avançado de C++ está em ação onde a interface &lt;code>IContextCallback&lt;/code> é usada para lembrar o contexto da thread original e enfileirar (despachar) o processamento nesse contexto no momento do &lt;code>co_await&lt;/code>. Dessa forma, os processos assíncronos podem ser descritos de maneira procedimental, sem cair no &amp;ldquo;inferno do callback&amp;rdquo; (callback hell).&lt;/p>
&lt;h3 id="42-implementação-perfeita-da-barra-de-título-personalizada">4.2. Implementação Perfeita da Barra de Título Personalizada
&lt;/h3>&lt;p>Na era dos aplicativos do Windows 11, uma &amp;ldquo;barra de título personalizada&amp;rdquo; que pode hospedar guias ou uma caixa de pesquisa dentro da área da barra de título da janela (área de legenda) é um requisito crítico para uma experiência de usuário (UX) moderna. No entanto, no WinUI 3, a customização da barra de título não se trata apenas de mudar a cor; o nível de dificuldade aumenta imensamente se o requisito for &amp;ldquo;estender a área do cliente até a barra de título e manter a movimentação de arraste da janela e o suporte ao snap layout (redimensionamento automático quando a janela é levada para as bordas da tela)&amp;rdquo;.&lt;/p>
&lt;p>No LogicPad, a API &lt;code>ExtendsContentIntoTitleBar&lt;/code> foi usada para construir a barra de título utilizando meus próprios elementos XAML. O código a seguir demonstra como usar a classe &lt;code>AppWindow&lt;/code> do Windows App SDK para personalizar a barra de título.&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">// for 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">// Obtém o HWND (identificador de janela) da janela atual
&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">// Converte HWND em WindowId e obtém a instância do 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">// Verifica se a versão do SO oferece suporte à personalização
&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">// Estende a área do cliente (conteúdo) para a barra de título
&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">// Torna o fundo dos botões de legenda padrão (minimizar, maximizar, fechar) transparente
&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">// Define o elemento da UI definido no XAML (AppTitleBar) como a área que pode ser arrastada
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="c1">// * Para os detalhes desta parte, é necessário monitorar o UIElement do lado do XAML com o
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="c1">// Dispatcher da thread da UI, e chamar SetDragRectangles() para comunicar a área de arrasto ao sistema operacional.
&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>A maior armadilha dessa implementação é que toda vez que o tamanho do elemento da interface do usuário do lado XAML muda (como ao redimensionar a janela), o sistema operacional deve ser notificado e a área de verificação de clique (hit test) deve ser recalculada usando &lt;code>InputNonClientPointerSource&lt;/code> ou &lt;code>SetDragRectangles&lt;/code>, declarando: &amp;ldquo;esta é uma área que pode ser arrastada&amp;rdquo;. Caso contrário, bugs surgirão, como a janela não se mover ao arrastar a barra de título, ou o sistema entender como um arraste de janela quando o que você pretendia fazer era clicar num botão.&lt;/p>
&lt;h2 id="5-o-abismo-do-empacotamento-msix-e-o-appxmanifest">5. O Abismo do Empacotamento MSIX e o AppXManifest
&lt;/h2>&lt;p>Para distribuir a versão final do LogicPad, é necessário criar um instalador. Em vez dos instaladores convencionais MSI ou EXE, adotei o moderno formato &lt;strong>MSIX&lt;/strong>. O MSIX garante que a instalação e a desinstalação sejam feitas de forma completamente limpa (sem sujar o registro) e conta com um recurso de atualização automática, tornando-o incrivelmente seguro e conveniente para os usuários.&lt;/p>
&lt;p>No entanto, ao empacotar um aplicativo nativo escrito em C++ no formato MSIX, a coisa mais crítica a observar é a configuração do arquivo &lt;code>Package.appxmanifest&lt;/code> (arquivo de manifesto).&lt;/p>
&lt;p>O LogicPad precisa ler e gravar enormes arquivos de projetos de circuitos lógicos salvos no sistema de arquivos local (como na pasta Documentos do usuário). O ambiente sandbox normal de UWP pode acessar somente a pasta de dados do próprio aplicativo (AppContainer). Para obter direitos totais de acesso como um aplicativo de desktop nativo, a capacidade &lt;code>runFullTrust&lt;/code> deve ser declarada no manifesto.&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;!-- Restrições gerais de funcionalidade --&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;!-- Funcionalidade restrita para execução como um aplicativo de desktop nativo --&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>Este &lt;code>&amp;lt;rescap:Capability Name=&amp;quot;runFullTrust&amp;quot; /&amp;gt;&lt;/code> é denominado &amp;ldquo;Capacidade Restrita&amp;rdquo; (Restricted Capability). Ao enviar para a Microsoft Store, é necessário enviar uma declaração de justificação explicando aos avaliadores o motivo pelo qual essas permissões são necessárias. Eu expliquei: &amp;ldquo;Como este aplicativo é uma ferramenta profissional para exportar, ler e gravar arquivos arbitrários de projeto de circuito lógico contidos no disco local do usuário&amp;rdquo; e recebi a aprovação sem incidentes.&lt;/p>
&lt;h2 id="6-o-caminho-até-a-microsoft-store-e-o-processo-de-certificação">6. O Caminho até a Microsoft Store e o Processo de Certificação
&lt;/h2>&lt;p>Assim que o aplicativo for concluído e o pacote MSIX tiver sido compilado, finalmente é a hora do envio para a Microsoft Store. Para os desenvolvedores individuais, a distribuição por meio da loja tem benefícios incontáveis: entrega automatizada de atualizações, garantia de confiabilidade e a utilidade do sistema de pagamentos.&lt;/p>
&lt;p>O processo de envio para a Microsoft Store se dá através do Partner Center (Centro de Parceiros). O fluxograma a seguir ilustra todo o processo desde a compilação até a publicação.&lt;/p>
&lt;pre class="mermaid">
flowchart TD
A[&amp;#34;Desenvolvedor (Visual Studio)&amp;#34;] --&amp;gt;|Construir e Assinar| B[&amp;#34;Geração do Pacote MSIX&amp;#34;]
B --&amp;gt; C[&amp;#34;Kit de Certificação de Aplicativos do Windows (WACK)&amp;#34;]
C --&amp;gt;|Aprovado| D[&amp;#34;Painel do Partner Center&amp;#34;]
C --&amp;gt;|Falha| E[&amp;#34;Corrigir Problemas de Código / Manifesto&amp;#34;]
E --&amp;gt; A
D --&amp;gt;|Enviar Pacote| F[&amp;#34;Processo de Certificação da Loja&amp;#34;]
F --&amp;gt; G[&amp;#34;Verificação Automática de Malware&amp;#34;]
G --&amp;gt; H[&amp;#34;Revisão Manual de Conteúdo&amp;#34;]
H --&amp;gt;|Aprovado| I[&amp;#34;Publicação na Microsoft Store&amp;#34;]
H --&amp;gt;|Rejeitado| J[&amp;#34;Resolver Feedback e Reenviar&amp;#34;]
J --&amp;gt; D
I --&amp;gt; K[&amp;#34;Aplicativo Está no Ar!&amp;#34;]
&lt;/pre>
&lt;h3 id="61-a-barreira-do-wack-windows-app-certification-kit">6.1. A Barreira do WACK (Windows App Certification Kit)
&lt;/h3>&lt;p>Antes de enviar o aplicativo ao Partner Center, você deve sempre executar o &lt;strong>WACK (Windows App Certification Kit)&lt;/strong> localmente e ser aprovado no teste prévio. O WACK é uma ferramenta que testa automaticamente se o aplicativo não vai travar, se não chama APIs não autorizadas e se atende aos requisitos de desempenho.&lt;/p>
&lt;p>Para aplicativos nativos C++, o erro a se prestar mais atenção é o &amp;ldquo;Uso de APIs não suportadas&amp;rdquo;. Quando você vincula estaticamente uma biblioteca C++ antiga de terceiros, ela pode usar internamente as obsoletas Win32 APIs, o que faz com que seja rejeitada na análise do WACK. Para evitar esse problema, atualizei as bibliotecas dependentes para as versões mais recentes e reescrevi algumas funções usando APIs alternativas fornecidas pelo Windows App SDK.&lt;/p>
&lt;h3 id="62-avaliação-e-publicação">6.2. Avaliação e Publicação
&lt;/h3>&lt;p>A configuração no Partner Center inclui a definição do preço do aplicativo, restrição de idade (classificação IARC) e o preenchimento de capturas de tela e descrições para a loja. Como o LogicPad é uma ferramenta técnica, obteve rapidamente a classificação livre para todas as idades.&lt;/p>
&lt;p>Levou cerca de 3 dias úteis desde a submissão do pacote até a conclusão da revisão. Após a varredura automática de malware e a verificação de funcionalidade, há uma verificação manual de funcionamento pela equipe de aprovação da Microsoft. O pedido de permissão para &lt;code>runFullTrust&lt;/code> passou sem problemas, e a sensação de realização no momento em que o status finalmente mudou para &amp;ldquo;Publicado (In the Store)&amp;rdquo; foi insubstituível.&lt;/p>
&lt;h2 id="7-desenvolvimento-pessoal-como-negócio-modelos-matemáticos-de-desempenho-e-lucro">7. Desenvolvimento Pessoal como Negócio: Modelos Matemáticos de Desempenho e Lucro
&lt;/h2>&lt;p>Para que não seja apenas a satisfação de criar um aplicativo, mas sim transformar o LogicPad em um projeto atualizado continuamente e viável como um negócio, é necessário avaliar quantitativamente tanto os indicadores técnicos quanto os comerciais.&lt;/p>
&lt;h3 id="71-o-modelo-de-otimização-do-uso-de-memória-proporcionado-pelo-c">7.1. O Modelo de Otimização do Uso de Memória Proporcionado pelo C++
&lt;/h3>&lt;p>O maior ponto forte do LogicPad é ser extremamente leve em comparação aos editores baseados em Electron (por exemplo, VSCode). O uso total de memória (footprint) do aplicativo, $M_{total}$, pode ser modelado da seguinte forma:&lt;/p>
$$
M_{total} = M_{UI} + M_{engine} + M_{cache}
$$&lt;p>Aqui, o $M_{UI}$ devido à renderização nativa do WinUI 3, é drasticamente menor (cerca de 50MB) se comparado com o Electron, que carrega um motor de navegador completo.
Além disso, a memória do motor C++, $M_{engine}$, escala linearmente em relação ao número de portas lógicas $N$, graças à estruturas otimizadas e eliminação de ponteiros.&lt;/p>
$$
M_{engine} = N \times \text{sizeof(LogicNode)}
$$&lt;p>Otimizando o alinhamento das estruturas usando &lt;code>#pragma pack&lt;/code> no C++, cortei a memória por nó até o limite absoluto.&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">// Não possui tabela de função virtual (vtable) e empacota para minimizar a memória
&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">// O tamanho da estrutura é de 7 bytes (sem preenchimento/padding de alinhamento)
&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>A memória da camada de cache $M_{cache}$ retém o histórico da simulação, portanto, aumenta proporcionalmente a $\mathcal{O}(N \log N)$, mas devido ao uso base ser pequeno, o uso total de RAM do sistema para um circuito com dezenas de milhares de nós permanece abaixo de 200 MB.&lt;/p>
&lt;h3 id="72-ltv-e-cac-matemática-de-marketing">7.2. LTV e CAC: Matemática de Marketing
&lt;/h3>&lt;p>Na estratégia de monetização para o desenvolvimento pessoal, o equilíbrio entre o Valor do Tempo de Vida do Cliente (LTV: Lifetime Value) e o Custo de Aquisição de Clientes (CAC: Customer Acquisition Cost) é tudo. O LogicPad não adota o modelo de assinatura, mas um modelo de licença de compra única (freemium).&lt;/p>
&lt;p>O LTV é calculado como a soma do valor presente descontado (usando a taxa de desconto $d$) da probabilidade de futuras compras de atualização. Para um período $T$, ele é expresso pela seguinte fórmula:&lt;/p>
$$
LTV = \sum_{t=1}^{T} \frac{ARPU_t \times Margin}{(1+d)^t}
$$&lt;p>Por outro lado, o CAC é o custo total de marketing, como anúncios no Twitter (atual X) e tráfego gerado por artigos de blog, dividido pelo número de novos usuários.&lt;/p>
$$
CAC = \frac{Total\ Marketing\ Spend}{Number\ of\ New\ Users}
$$&lt;p>A vantagem do desenvolvimento individual é que o custo de mão de obra para o desenvolvimento pode ser considerado como &amp;ldquo;tempo de hobby&amp;rdquo; (custo irrecuperável/sunk cost), permitindo que o CAC seja calculado apenas com base no custo puro de marketing. Atualmente, devido a um tráfego orgânico impulsionado principalmente pelo boca a boca em comunidades de tecnologia de nicho, um estado próximo a $CAC \approx 0$ foi atingido, realizando uma economia unitária saudável de $LTV > CAC$.&lt;/p>
&lt;h2 id="8-conclusão-o-mundo-árduo-porém-belo-do-desenvolvimento-de-aplicativos-nativos">8. Conclusão: O Mundo Árduo, Porém Belo, do Desenvolvimento de Aplicativos Nativos
&lt;/h2>&lt;p>Ao olhar para trás na jornada desde o desenvolvimento do LogicPad até seu lançamento na Microsoft Store, fica claro que não foi um caminho plano. Lutar contra erros de compilação obscuros em C++/WinRT, rastrear vazamentos de memória devido a bugs de contagem de referência COM e investigar as especificações de XML dos manifestos MSIX não foi tarefa fácil.&lt;/p>
&lt;p>É precisamente porque a evolução da tecnologia web nos trouxe para a era em que &amp;ldquo;você pode construir qualquer coisa em um navegador&amp;rdquo;, que a experiência de desenvolvimento nativo - atingindo diretamente as APIs do sistema operacional e prestando atenção a cada byte de memória e cada ciclo de clock do processador - aprimora esmagadoramente os músculos fundamentais de engenharia.&lt;/p>
&lt;p>O WinUI 3 e o Windows App SDK continuam sendo desenvolvidos ativamente e são as melhores ferramentas para a construção de aplicativos lindos que aproveitam ao máximo o paradigma da interface do usuário do Windows 11. Eu sinceramente espero que este artigo de blog sirva como um guia para desenvolvedores que estejam prestes a embarcar na criação de aplicativos nativos do Windows e que veremos cada vez mais aplicativos excepcionais ocupando as prateleiras da loja digital.&lt;/p>
&lt;p>O desenvolvimento ainda não acabou. Para a próxima versão do LogicPad, planejo integrar um mecanismo de renderização de forma de onda proprietário usando Direct2D. No próximo artigo, exploraremos profundamente a interoperabilidade do DirectX e WinUI 3 (utilizando o SwapChainPanel). Fique ligado!&lt;/p></description></item></channel></rss>