<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: amir abedi</title>
    <description>The latest articles on DEV Community by amir abedi (@amir_abedi_222ad74caaa786).</description>
    <link>https://dev.to/amir_abedi_222ad74caaa786</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4121098%2Fe64ce90c-e3c5-41b5-ab7e-6da9f7a7a317.png</url>
      <title>DEV Community: amir abedi</title>
      <link>https://dev.to/amir_abedi_222ad74caaa786</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/amir_abedi_222ad74caaa786"/>
    <language>en</language>
    <item>
      <title>I Spent a Year Fighting GDI+ in WinForms So You Don't Have To</title>
      <dc:creator>amir abedi</dc:creator>
      <pubDate>Sat, 19 Sep 2026 07:54:27 +0000</pubDate>
      <link>https://dev.to/amir_abedi_222ad74caaa786/i-spent-a-year-fighting-gdi-in-winforms-so-yo-35g8</link>
      <guid>https://dev.to/amir_abedi_222ad74caaa786/i-spent-a-year-fighting-gdi-in-winforms-so-yo-35g8</guid>
      <description>&lt;p&gt;Let's be honest: &lt;strong&gt;Windows Forms is still a workhorse.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;For internal B2B applications, industrial automation software, administration tools, monitoring systems, and heavy desktop clients, WinForms can still get the job done remarkably fast.&lt;/p&gt;

&lt;p&gt;And with WinForms continuing on modern .NET versions, including .NET 6, .NET 8, and beyond, it isn't disappearing anytime soon.&lt;/p&gt;

&lt;p&gt;But there is one problem that developers keep running into:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The default UI hasn't aged as gracefully as the framework itself.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Show a client a modern web application and then show them a traditional WinForms form with gray buttons, old-school grids, and basic panels, and the visual difference can make an otherwise perfectly capable application feel dated.&lt;/p&gt;

&lt;p&gt;A year ago, I decided to see how far I could push WinForms in the other direction.&lt;/p&gt;

&lt;p&gt;I wanted modern-looking controls.&lt;/p&gt;

&lt;p&gt;Rounded corners.&lt;/p&gt;

&lt;p&gt;Better dashboards.&lt;/p&gt;

&lt;p&gt;Dark mode.&lt;/p&gt;

&lt;p&gt;Custom grids and navigation.&lt;/p&gt;

&lt;p&gt;And, most importantly, something that still behaved like a proper WinForms application inside Visual Studio.&lt;/p&gt;

&lt;p&gt;I thought it would be simple.&lt;/p&gt;

&lt;p&gt;I was wrong.&lt;/p&gt;




&lt;h1&gt;
  
  
  The GDI+ Reality Check
&lt;/h1&gt;

&lt;p&gt;My original plan was straightforward:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Override &lt;code&gt;OnPaint()&lt;/code&gt;, draw some rounded rectangles, add some shadows, and move on.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That plan lasted about five minutes.&lt;/p&gt;

&lt;p&gt;Once you start building a real collection of custom WinForms controls, rendering quickly becomes much more complicated than drawing a rectangle.&lt;/p&gt;

&lt;p&gt;The problems don't appear when you're drawing one button on a test form.&lt;/p&gt;

&lt;p&gt;They appear when you have dozens of controls, nested layouts, resizing, DPI scaling, design-time support, themes, images, animations, and frequent repaint operations happening throughout the application.&lt;/p&gt;

&lt;p&gt;I eventually ran into three major areas of pain.&lt;/p&gt;




&lt;h2&gt;
  
  
  1. The Flickering Problem
&lt;/h2&gt;

&lt;p&gt;WinForms applications can look perfectly fine until you start resizing a complex window.&lt;/p&gt;

&lt;p&gt;Then everything changes.&lt;/p&gt;

&lt;p&gt;Nested controls repaint.&lt;/p&gt;

&lt;p&gt;Layouts are recalculated.&lt;/p&gt;

&lt;p&gt;Invalidation propagates through the hierarchy.&lt;/p&gt;

&lt;p&gt;And suddenly your beautiful dashboard starts flashing while the window is being resized.&lt;/p&gt;

&lt;p&gt;Getting double buffering and repaint behavior right across a hierarchy of custom controls isn't simply a matter of adding:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="n"&gt;DoubleBuffered&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Sometimes it helps.&lt;/p&gt;

&lt;p&gt;Sometimes it doesn't.&lt;/p&gt;

&lt;p&gt;And sometimes the real problem is somewhere else in the rendering or layout pipeline.&lt;/p&gt;

&lt;p&gt;I spent a lot of time testing resize scenarios and trying to understand exactly when controls were being invalidated and repainted.&lt;/p&gt;




&lt;h2&gt;
  
  
  2. GDI+ Resources, Rendering and High DPI
&lt;/h2&gt;

&lt;p&gt;Once you start doing custom drawing, you also become responsible for much more than pixels.&lt;/p&gt;

&lt;p&gt;Pens.&lt;/p&gt;

&lt;p&gt;Brushes.&lt;/p&gt;

&lt;p&gt;Fonts.&lt;/p&gt;

&lt;p&gt;Bitmaps.&lt;/p&gt;

&lt;p&gt;Graphics objects.&lt;/p&gt;

&lt;p&gt;Paths.&lt;/p&gt;

&lt;p&gt;Images.&lt;/p&gt;

&lt;p&gt;All of these have to be handled carefully, especially inside controls that may repaint many times during their lifetime.&lt;/p&gt;

&lt;p&gt;Then there is DPI scaling.&lt;/p&gt;

&lt;p&gt;A control that looks perfect on one monitor can suddenly look slightly wrong on another.&lt;/p&gt;

&lt;p&gt;Rounded corners can become uneven.&lt;/p&gt;

&lt;p&gt;Icons can look blurry.&lt;/p&gt;

&lt;p&gt;Spacing can feel inconsistent.&lt;/p&gt;

&lt;p&gt;Shadows can look different at different scales.&lt;/p&gt;

&lt;p&gt;None of this is particularly difficult in isolation.&lt;/p&gt;

&lt;p&gt;The problem is that these small issues accumulate across an entire control library.&lt;/p&gt;




&lt;h2&gt;
  
  
  3. The Visual Studio Designer
&lt;/h2&gt;

&lt;p&gt;Then there was the part I underestimated the most:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;design-time behavior.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A custom control isn't only executed when your application runs.&lt;/p&gt;

&lt;p&gt;Visual Studio can instantiate it inside the Form Designer.&lt;/p&gt;

&lt;p&gt;Properties are inspected.&lt;/p&gt;

&lt;p&gt;Design-time services are used.&lt;/p&gt;

&lt;p&gt;Resources may be loaded.&lt;/p&gt;

&lt;p&gt;And if your control makes an assumption that is valid at runtime but invalid at design-time, you can end up with a broken designer experience.&lt;/p&gt;

&lt;p&gt;You build the application.&lt;/p&gt;

&lt;p&gt;Everything works.&lt;/p&gt;

&lt;p&gt;You open the Form Designer.&lt;/p&gt;

&lt;p&gt;That's when you realize that a control library needs to be designed for two different worlds:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;runtime and design-time.&lt;/strong&gt;&lt;/p&gt;




&lt;h1&gt;
  
  
  What I Learned Building Custom WinForms Controls
&lt;/h1&gt;

&lt;p&gt;After enough debugging sessions, I started noticing a pattern.&lt;/p&gt;

&lt;p&gt;The hard part wasn't drawing a rounded button.&lt;/p&gt;

&lt;p&gt;The hard part was building a &lt;strong&gt;reusable rendering architecture&lt;/strong&gt; around it.&lt;/p&gt;

&lt;p&gt;Here are some lessons that mattered most.&lt;/p&gt;




&lt;h2&gt;
  
  
  Don't treat every control as an &lt;code&gt;OnPaint()&lt;/code&gt; problem
&lt;/h2&gt;

&lt;p&gt;A control needs more than rendering logic.&lt;/p&gt;

&lt;p&gt;State management, invalidation, sizing, DPI behavior, resource ownership, interaction states, and design-time behavior all matter.&lt;/p&gt;




&lt;h2&gt;
  
  
  Rendering and appearance should be separated
&lt;/h2&gt;

&lt;p&gt;If every control handles colors independently, adding a global theme becomes painful.&lt;/p&gt;

&lt;p&gt;A shared theme system makes the controls much easier to manage.&lt;/p&gt;




&lt;h2&gt;
  
  
  Design-time behavior needs to be considered from day one
&lt;/h2&gt;

&lt;p&gt;Trying to "fix the designer later" is much harder than designing controls with Visual Studio's designer in mind from the beginning.&lt;/p&gt;




&lt;h2&gt;
  
  
  Resize testing should happen early
&lt;/h2&gt;

&lt;p&gt;Don't wait until the end of development to test a complex dashboard while continuously resizing the window.&lt;/p&gt;

&lt;p&gt;If your rendering architecture has problems, resizing will find them.&lt;/p&gt;

&lt;p&gt;Fast.&lt;/p&gt;




&lt;h2&gt;
  
  
  A UI library is more than a collection of controls
&lt;/h2&gt;

&lt;p&gt;The controls are only part of the problem.&lt;/p&gt;

&lt;p&gt;You also need consistent behavior, shared styling, theming, resources, designers, documentation, and a predictable developer experience.&lt;/p&gt;

&lt;p&gt;That realization eventually changed the direction of the project.&lt;/p&gt;




&lt;h1&gt;
  
  
  Turning That Experience Into FTR Controls
&lt;/h1&gt;

&lt;p&gt;Instead of keeping everything inside a private project, I decided to turn the architecture into a reusable WinForms UI suite.&lt;/p&gt;

&lt;p&gt;That's how &lt;strong&gt;FTR Controls&lt;/strong&gt; started.&lt;/p&gt;

&lt;p&gt;The idea wasn't to create another huge UI framework with hundreds of obscure properties.&lt;/p&gt;

&lt;p&gt;I wanted something focused on a simpler goal:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Make modern WinForms UI development feel like normal WinForms development again.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Drop a control onto a form.&lt;/p&gt;

&lt;p&gt;Open the Visual Studio Property Grid.&lt;/p&gt;

&lt;p&gt;Configure it.&lt;/p&gt;

&lt;p&gt;Write your application logic.&lt;/p&gt;

&lt;p&gt;Don't spend your afternoon writing another custom &lt;code&gt;OnPaint()&lt;/code&gt; implementation because a button needs rounded corners.&lt;/p&gt;

&lt;p&gt;FTR.UI.WinForms includes &lt;strong&gt;26 custom WinForms controls&lt;/strong&gt; covering dashboards, grids, navigation, calendars, ribbons, cards, sliders, charts, notifications, and more.&lt;/p&gt;

&lt;p&gt;The important part isn't just how the controls look.&lt;/p&gt;

&lt;p&gt;It's how they behave inside a real WinForms development workflow.&lt;/p&gt;




&lt;h1&gt;
  
  
  Let's Build a Modern Dashboard
&lt;/h1&gt;

&lt;p&gt;Here's a simple example of how the pieces fit together.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Build the Layout
&lt;/h2&gt;

&lt;p&gt;Instead of implementing your own custom navigation and dashboard containers, you can compose the application using the provided controls.&lt;/p&gt;

&lt;p&gt;For example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Add an &lt;code&gt;FTRRibbon&lt;/code&gt; to the top.&lt;/li&gt;
&lt;li&gt;Add an &lt;code&gt;FTRTreeList&lt;/code&gt; for navigation.&lt;/li&gt;
&lt;li&gt;Add an &lt;code&gt;FTRDashboard&lt;/code&gt; to the main content area.&lt;/li&gt;
&lt;li&gt;Configure docking and sizing through the normal WinForms designer.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The goal is that this should still feel familiar to a WinForms developer.&lt;/p&gt;

&lt;p&gt;You aren't learning an entirely different application framework.&lt;/p&gt;

&lt;p&gt;You're still building a WinForms application.&lt;/p&gt;




&lt;h2&gt;
  
  
  2. Create Data Cards
&lt;/h2&gt;

&lt;p&gt;Suppose you want a card on your dashboard.&lt;/p&gt;

&lt;p&gt;You can create it directly in code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;card&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;FTRCard&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;HeaderText&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Monthly Revenue"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;ShowHeader&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;CardBackColor&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Color&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;White&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can also configure the control through the Visual Studio Property Grid.&lt;/p&gt;

&lt;p&gt;That's an important part of the design philosophy behind FTR Controls:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The developer should work with properties and application logic, not rendering code.&lt;/strong&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  One-Click Dark Mode
&lt;/h1&gt;

&lt;p&gt;Another problem that becomes surprisingly difficult when building a UI library from scratch is theming.&lt;/p&gt;

&lt;p&gt;If every control owns its own colors, switching an application from Light to Dark can quickly become a maintenance nightmare.&lt;/p&gt;

&lt;p&gt;FTR Controls uses a centralized theme system.&lt;/p&gt;

&lt;p&gt;Switching the application's theme can be done through a single setting:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="n"&gt;ThemeManager&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CurrentTheme&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ThemeManager&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ThemeMode&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Dark&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Instead of manually finding every control and changing its colors, the shared theme system manages the common visual appearance across the application.&lt;/p&gt;

&lt;p&gt;The available theme modes include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Light&lt;/li&gt;
&lt;li&gt;Dark&lt;/li&gt;
&lt;li&gt;Color&lt;/li&gt;
&lt;li&gt;Duotone&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A consistent theme system is important because a modern application is not just a collection of controls.&lt;/p&gt;

&lt;p&gt;It is a complete visual experience.&lt;/p&gt;




&lt;h1&gt;
  
  
  The Flicker-Free Challenge
&lt;/h1&gt;

&lt;p&gt;This is the part where I don't want you to simply take my word for it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Try to break it.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I've created a demo application so developers can test the controls in a real WinForms environment.&lt;/p&gt;

&lt;p&gt;Try this:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Download and run the demo application.&lt;/li&gt;
&lt;li&gt;Open it in Visual Studio if you want to explore the controls.&lt;/li&gt;
&lt;li&gt;Resize the window aggressively.&lt;/li&gt;
&lt;li&gt;Switch between Light and Dark themes.&lt;/li&gt;
&lt;li&gt;Navigate through different sections.&lt;/li&gt;
&lt;li&gt;Try the controls under your own workload.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Pay attention to how the UI behaves during continuous resizing and repainting.&lt;/p&gt;

&lt;p&gt;A screenshot cannot demonstrate rendering behavior.&lt;/p&gt;

&lt;p&gt;A real application can.&lt;/p&gt;

&lt;p&gt;If you find a rendering issue, unexpected flickering, a DPI problem, or a designer-related problem, I would genuinely like to hear about it.&lt;/p&gt;




&lt;h1&gt;
  
  
  Why I Built It
&lt;/h1&gt;

&lt;p&gt;There are already several mature commercial UI libraries for WinForms.&lt;/p&gt;

&lt;p&gt;This project isn't about pretending they don't exist.&lt;/p&gt;

&lt;p&gt;I built FTR Controls because I wanted to solve the problems I personally kept running into while building modern desktop applications.&lt;/p&gt;

&lt;p&gt;The goal is a developer-friendly collection of controls that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Fits naturally into the WinForms designer.&lt;/li&gt;
&lt;li&gt;Works with the Visual Studio Property Grid.&lt;/li&gt;
&lt;li&gt;Provides a consistent visual system.&lt;/li&gt;
&lt;li&gt;Supports Light, Dark, Color, and Duotone themes.&lt;/li&gt;
&lt;li&gt;Reduces the need to write custom rendering code for common UI patterns.&lt;/li&gt;
&lt;li&gt;Works with modern .NET and supported .NET Framework applications.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;FTR.UI.WinForms supports:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;.NET Framework 4.7.2&lt;/li&gt;
&lt;li&gt;.NET 6+ Windows applications&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The most important goal is simple:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Developers should spend their time building their application, not rebuilding the same UI infrastructure over and over again.&lt;/strong&gt;&lt;/p&gt;




&lt;h1&gt;
  
  
  If You're Still Building WinForms in 2026...
&lt;/h1&gt;

&lt;p&gt;WinForms may not be the newest UI technology.&lt;/p&gt;

&lt;p&gt;But for a huge number of business applications, internal tools, industrial systems, administration software, and desktop clients, it remains a very practical choice.&lt;/p&gt;

&lt;p&gt;The framework isn't necessarily the problem.&lt;/p&gt;

&lt;p&gt;Sometimes the problem is simply that we're still building the UI the way we did twenty years ago.&lt;/p&gt;

&lt;p&gt;That's what I wanted to experiment with.&lt;/p&gt;

&lt;p&gt;After a year of fighting with custom rendering, I ended up with something I can actually reuse.&lt;/p&gt;

&lt;p&gt;That's &lt;strong&gt;FTR Controls&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;If you're working on a WinForms application and modernizing its UI is becoming a bigger task than you expected, give the demo a try.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;And if you manage to make it flicker, let me know. 👇&lt;/strong&gt;&lt;/p&gt;




&lt;h1&gt;
  
  
  Try It Yourself
&lt;/h1&gt;

&lt;p&gt;&lt;strong&gt;FTR UI Suite&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://ftr-ui-suite.vercel.app/" rel="noopener noreferrer"&gt;https://ftr-ui-suite.vercel.app/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Documentation&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://ftr-ui-suite.vercel.app/docs" rel="noopener noreferrer"&gt;https://ftr-ui-suite.vercel.app/docs&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;NuGet Package&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://www.nuget.org/packages/FTR.UI.WinForms" rel="noopener noreferrer"&gt;https://www.nuget.org/packages/FTR.UI.WinForms&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;The core idea is simple:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Stop fighting with pixels. Build the application.&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>dotnet</category>
      <category>csharp</category>
      <category>software</category>
      <category>programming</category>
    </item>
  </channel>
</rss>
