TE
TechEcho
StartseiteTop 24hNeuesteBesteFragenZeigenJobs
GitHubTwitter
Startseite

TechEcho

Eine mit Next.js erstellte Technologie-Nachrichtenplattform, die globale Technologienachrichten und Diskussionen bietet.

GitHubTwitter

Startseite

StartseiteNeuesteBesteFragenZeigenJobs

Ressourcen

HackerNews APIOriginal HackerNewsNext.js

© 2025 TechEcho. Alle Rechte vorbehalten.

I built a native Windows Todo app in pure C (278 KB, no frameworks)

364 Punktevon toxi360vor 1 Tag

44 comments

masternightvor 1 Tag
There is something I like about win32 gui programming. It&#x27;s a little idiosyncratic, but if you read Raymond Chen&#x27;s blog you&#x27;ll see why.<p>The win32 API has its origins on the 8088 processor and doing things a certain way results in saving 40 bytes of code or uses one less register or something.<p>I wrote a lot of toy gui apps using mingw and Petzold&#x27;s book back in the day. Writing custom controls, drawing graphics and text, handling scrolling, hit testing etc was all a lot of fun.<p>I see in your app you&#x27;re using strcpy, sprintf. Any kind of serious programming you should be using the length-checked variants. I&#x27;m surprised the compiler didn&#x27;t spew.<p>You&#x27;ll also find that the Win32 API has a lot of replacements for what&#x27;s in the C standard library. If you really want to try and get the executable size down, see if you can write your app using only &lt;Windows.h&gt; and no cstdlib. Instead of memset() you&#x27;ve got ZeroMemory(), instead of memcpy() you&#x27;ve got CopyMemory().<p>At some point writing raw C code becomes painful. Still, I think doing your first few attempts in raw C is the best way to learn. Managing all the minutiae gives you a great sense of what&#x27;s going on while you&#x27;re learning.<p>If you want to play more with win32 gui programming, I&#x27;d have a look at the WTL (Windows Template Library). It&#x27;s a C++ wrapper around the win32 API and makes it much easier to reason about what&#x27;s going on.
评论 #43960664 未加载
评论 #43957789 未加载
评论 #43957759 未加载
评论 #43957771 未加载
评论 #43960215 未加载
评论 #43958301 未加载
评论 #43960111 未加载
评论 #43961245 未加载
electrolyvor 1 Tag
Instead of laboriously calling CreateWindow() for every control, traditionally we would lay out a dialog resource in a .rc file (Visual Studio still has the dialog editor to do it visually) and then use CreateDialog() instead of CreateWindow(). This will create all the controls for you. Add an application manifest and you can get modern UI styling and high-DPI support.
评论 #43960265 未加载
评论 #43957582 未加载
评论 #43957395 未加载
评论 #43958824 未加载
评论 #43957511 未加载
评论 #43960370 未加载
broken_broken_vor 1 Tag
I have done something similar for Linux under 2 KiB in assembly some time ago: <a href="https:&#x2F;&#x2F;gaultier.github.io&#x2F;blog&#x2F;x11_x64.html" rel="nofollow">https:&#x2F;&#x2F;gaultier.github.io&#x2F;blog&#x2F;x11_x64.html</a><p>As others have said, doing so in pure C and linking dynamically, you can easily remain under 20 KiB, at least on Linux, but Windows should be even simpler since it ships with much more out of the box as part of the OS.<p>In any event, I salute the effort! You can try the linking options I mentioned at the end of my article, it should help getting the size down.
评论 #43960763 未加载
eviksvor 1 Tag
&gt; no frameworks<p>Checks out: blurry fonts in scaled dpi, no Tab support, can&#x27;t Ctrl-A select text in text fields and do all the other stuff that pre-modern frameworks offered you, errors on adding a row, ...<p>&gt; modern<p>In what way?
评论 #43956763 未加载
评论 #43956726 未加载
评论 #43967981 未加载
AaronAPUvor 1 Tag
The 6502 programmer in me is dying inside that 278kb now passes as lightweight.
评论 #43957149 未加载
评论 #43956257 未加载
评论 #43955813 未加载
评论 #43969805 未加载
评论 #43956598 未加载
评论 #43956420 未加载
评论 #43956301 未加载
评论 #43956129 未加载
评论 #43956579 未加载
评论 #43956571 未加载
评论 #43958987 未加载
评论 #43956473 未加载
评论 #43956803 未加载
评论 #43956566 未加载
评论 #43956423 未加载
评论 #43960537 未加载
toxi360vor 1 Tag
Hello friends, I made this app just to try it out and have some fun, haha, but the comments are right, something like this could have been done more sensibly with C++ or other languages, ahaha.
评论 #43956656 未加载
评论 #43956398 未加载
评论 #43957557 未加载
评论 #43956339 未加载
评论 #43957476 未加载
transcriptasevor 1 Tag
Seeing a lot of chirps in here from people who work on software or websites that load megabytes of JS or C# or in order to send 278kb of telemetry every time the user moves their mouse.
评论 #43958166 未加载
phendrenad2vor 1 Tag
The fact that you can do everything in C when developing a Windows app always makes me feel all warm and fuzzy. Building up from the lowest-level primitives just makes sense.<p>Meanwhile, on MacOS, everything is an ObjectiveC Object, so if you want to write an app in pure C you <i>can</i> but it&#x27;s about 1000x more verbose because you&#x27;ve gone an abstraction level deeper than Apple intended, and you essentially have to puppeteer the Objective C class hierarchy to make anything happen. It&#x27;s incredibly icky.<p>I don&#x27;t know why they can&#x27;t rebase the ObjectiveC class-based API onto a basic win32-style procedural API (technically win32 is also &quot;class-based&quot; but it&#x27;s minimal). It&#x27;s part of why I don&#x27;t see myself porting any of my C code to MacOS any time soon.
评论 #43965412 未加载
评论 #43960257 未加载
vparikhvor 1 Tag
Looks like you are linking to static libraries. You should link to DLL not to static libraries - this is will cut down on the application size dramatically.
评论 #43956044 未加载
评论 #43957041 未加载
dvdkonvor 1 Tag
If you&#x27;re going for a small EXE, I&#x27;d recommend telling GCC to optimise for size with &quot;-Os&quot;.<p>Link-Time Optimisation with &quot;-flto&quot; might also help, depending on how the libraries were built.
评论 #43956000 未加载
userbinatorvor 1 Tag
That&#x27;s more than 10x bigger than I expected, given that all it seems to do is manipulate a list view. Something like this should be doable in under 10KB.
smusamashahvor 1 Tag
The title reminds of recently released really fast file explorer called File Pilot. Made in C and weighs 1.8MB only <a href="https:&#x2F;&#x2F;filepilot.tech&#x2F;" rel="nofollow">https:&#x2F;&#x2F;filepilot.tech&#x2F;</a>
webprofusionvor 1 Tag
Nostalgia: My first job in 1997 was a windows apps in C++, it was weather software used on ships and oil rigs, we used to ship updates on floppy disk via helicopter.
p0w3n3dvor 1 Tag
Great respect! I&#x27;ve tried many times, without final result. I&#x27;ll try to use this for learning purposes!<p>Btw. I like how Inno Setup used some very old Delphi 2 compiler to create exe so small it would fit without breaking the zip compliancy. I read it somewhere 10+ years ago, so not sure if this is still the case, but still. And the initial dialog was done in pure winapi.h (of course it was winapi.pas which made everything more difficult for me to learn from)
rfl890vor 1 Tag
There&#x27;s no application manifest for the common controls so it will look outdated
leecommamichaelvor etwa 23 Stunden
Odd that there’s so much conversation about this. Why is that? Genuine question.
评论 #43961224 未加载
burnt-resistorvor 1 Tag
Contains numerous memory leaks, doesn&#x27;t permit arbitrarily long lists, and saves and restores uninitialized data. Really sloppy.
lucasoshirovor 1 Tag
Every time I see something in C for Windows I see people using MinGW, gcc and friends just like they would do in a Unix-like system. But I wouldn&#x27;t expect that they are tools that Microsoft recommends for developing on Windows.<p>So, a honest question from a Linux&#x2F;Mac guy: what is the Windows-y way to do that?
评论 #43958940 未加载
评论 #43960377 未加载
评论 #43965697 未加载
评论 #43960621 未加载
formerly_provenvor 1 Tag
If you add a manifest you’ll get post-Windows-2000 GUI styling.
评论 #43957062 未加载
评论 #43956316 未加载
评论 #43955855 未加载
评论 #43955800 未加载
scripturialvor 1 Tag
The allure of the perfect notes and todo app. Having gone through phases of various modern todo and note apps over the years, I’ve finally let it go and decided to embrace just using text files. (Neovim for me, not that it matters which text editor one uses)<p>It’s not that there aren’t cool apps for this stuff, it’s more that I have a trail of data across various todo and notes apps from years of different tools.<p>One solution to the problem of making things “feel native” is to go all in on letting go of native. Target a different style, be it minimalism, Commodore 64, pixel art, etc… it can be fun that way, especially if it’s mostly just a tool for you.
评论 #43957991 未加载
vardumpvor 1 Tag
I think this Win32 app could be done in C under 20 kB.
评论 #43955670 未加载
评论 #43957984 未加载
评论 #43957879 未加载
mtlynchvor 1 Tag
Thanks for sharing, OP!<p>It&#x27;s probably too late, but this qualifies for &quot;Show HN&quot; if you update the title to have the prefix &quot;Show HN: &quot;.[0]<p>I think the size of the source is actually more impressive than the size of the binary. I&#x27;m impressed that you can implement the whole thing in what looks like about 1 KLOC in just four .c files.<p>[0] <a href="https:&#x2F;&#x2F;news.ycombinator.com&#x2F;showhn.html">https:&#x2F;&#x2F;news.ycombinator.com&#x2F;showhn.html</a>
jftugavor 1 Tag
Here is one of few Windows apps that I have written, albeit in C#. compinfo is a single, 431 KB windows executable.<p>It displays basic computer info including user name, computer name, OS, model, serial number (service tag), CPU model, memory, IPv4 address and uptime.<p><a href="https:&#x2F;&#x2F;github.com&#x2F;jftuga&#x2F;compinfo">https:&#x2F;&#x2F;github.com&#x2F;jftuga&#x2F;compinfo</a>
nu11ptrvor 1 Tag
This is a blast from the past and it is neat to see some bare bones coding projects, but as others have said this is hardly &quot;modern&quot;.
Disposal8433vor 1 Tag
&gt; A modern, native Windows Todo application<p>What&#x27;s modern about it? Also you could have used C++ instead to remove some potential issues, and those global variables...<p>Use std::string and std::array or std::list, some anonymous namespaces, remove all the malloc, etc. Your code would be half the size and still compile to the same assembly language without the bugs.
评论 #43956740 未加载
评论 #43957053 未加载
评论 #43956299 未加载
评论 #43956173 未加载
dataflowvor 1 Tag
You&#x27;ll definitely want to allow theming on your controls, if for no other reason than to let them feel native like the rest of the OS.<p>I&#x27;d also suggest at ATL, to make your life a bit easier without making it much heavier.
dochtmanvor 1 Tag
Curious what this would look like written in Rust, using the windows-rs bindings.
_bin_vor 1 Tag
Fun project! I think the smallest I ever shrunk a win32 application was on the order of 2-4kb by writing in ASM. It was a great illustration of why 10x binary size is actually a great trade-off in terms of productivity.
thecaiovor 1 Tag
Never easy to pull these off, so congrats! App might be modern in the sense that you coded it in 2025, but looks straight out of Windows 98
nsxwolfvor 1 Tag
The Readme emojis tell me this was vibe coded.
ghewgillvor 1 Tag
I think the hard limit of 100 todos is the best feature of this. Why don&#x27;t other todo apps have this feature?
评论 #43957708 未加载
评论 #43956796 未加载
re-lre-lvor 1 Tag
It should be written UPPER CASE, in Pascal, maybe...
pshirshovvor 1 Tag
If only I can do the same across 3 desktop and two phone platforms...
slicktuxvor 1 Tag
Simple and elegant!
pcunitevor 1 Tag
Back in the day I used to use UPX to compress my executables to achieve impressively small sizes.
评论 #43970584 未加载
评论 #43956693 未加载
hudovor 1 Tag
Less LOC than React&#x2F;Redux app... Makes you think, what were we doing last 30 years :&#x2F;
评论 #43957574 未加载
yapyapvor 1 Tag
Title says 278 KB, github says 27 KB.<p>I assume this is a typo in the title, OP if you ask dang nicely I’m sure he would be willing to remove the typo.
toxi360vor 1 Tag
Right now it&#x27;s only 27 kb and I&#x27;ve added the manifest file :)
dorianmariecomvor 1 Tag
ready for enterprise todo
bitwizevor 1 Tag
Hell to the yes!<p><pre><code> int PASCAL WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdLine, int nCmdShow); </code></pre> If you know, you know.<p>I&#x27;m to understand that entire divisions of Microsoft itself no longer know how to code anywhere near this level, which is why many of their flagship applications (looking at you, Microsoft Teams (work or school)) are Electron monstrosities you can watch draw themselves like Windows 1.0 apps -- on modern multicore hardware.<p>EDIT: more correct function sig
评论 #43957156 未加载
tippytippytangovor 1 Tag
The pedantry in the comments of a todo app is exquisite. HN never disappoints.<p>Very nostalgic OP, warms my heart 10&#x2F;10
keepamovinvor 1 Tag
Interesting! I was just looking at raylib for this kind of thing: super light weight, cross platform, reliable, ideally C-based method to get GUI.<p>Raylib and raygui is truly incredible from my point of view. I succeeded in getting the macOS and Windows builds going on a bunch of cute little novel (not stock standard in the repo) examples in a matter of hours with AI help. I&#x27;m inspired by all I can do with this.<p>For ages I felt &quot;cut off&quot; from the world of Desktop GUI because it was so verbose, and had high friction - need a bunch of tooling, set up, and so on. And then everything was fragile. I like to work quickly, with feedback, and PoCs and results. I think in raylib I have found a method that really achieves this. For instance, check out this tiny little &quot;text_input.c&quot;<p><pre><code> #define RAYGUI_IMPLEMENTATION #include &lt;raylib.h&gt; #include &quot;deps&#x2F;raygui.h&quot; #define WINDOW_WIDTH 800 #define WINDOW_HEIGHT 600 #define MAX_INPUT_CHARS 32 int main(void) { InitWindow(WINDOW_WIDTH, WINDOW_HEIGHT, &quot;Text Input Demo&quot;); SetTargetFPS(60); &#x2F;&#x2F; Load a larger font for better text appearance Font font = LoadFontEx(&quot;resources&#x2F;fonts&#x2F;arial.ttf&quot;, 32, 0, 0); if (font.texture.id == 0) { font = GetFontDefault(); &#x2F;&#x2F; Fallback to default font if loading fails } &#x2F;&#x2F; Set the font for raygui controls GuiSetFont(font); &#x2F;&#x2F; Customize raygui styles (using BGR order for hex values) GuiSetStyle(BUTTON, TEXT_ALIGNMENT, TEXT_ALIGN_CENTER); GuiSetStyle(BUTTON, BASE_COLOR_NORMAL, 0x50AF4CFF); &#x2F;&#x2F; Green (B=80, G=175, R=76, A=255) ‚Üí R=76, G=175, B=80 GuiSetStyle(BUTTON, TEXT_COLOR_NORMAL, 0xFFFFFFFF); &#x2F;&#x2F; White text GuiSetStyle(BUTTON, BASE_COLOR_PRESSED, 0x6ABB66FF); &#x2F;&#x2F; Lighter green GuiSetStyle(BUTTON, TEXT_COLOR_PRESSED, 0xFFFFFFFF); GuiSetStyle(BUTTON, BASE_COLOR_FOCUSED, 0x84C781FF); &#x2F;&#x2F; Hover color GuiSetStyle(BUTTON, TEXT_COLOR_FOCUSED, 0xFFFFFFFF); GuiSetStyle(BUTTON, BORDER_WIDTH, 2); GuiSetStyle(BUTTON, BORDER_COLOR_NORMAL, 0x327D2EFF); &#x2F;&#x2F; Dark green border &#x2F;&#x2F; Adjust font size for raygui controls (optional, since font is already 32pt) GuiSetStyle(DEFAULT, TEXT_SIZE, 20); &#x2F;&#x2F; Slightly smaller for button and text box to fit better GuiSetStyle(DEFAULT, TEXT_SPACING, 1); char inputText[MAX_INPUT_CHARS + 1] = &quot;\0&quot;; &#x2F;&#x2F; Buffer for text input bool textBoxEditMode = false; &#x2F;&#x2F; Tracks if the text box is being edited bool messageSubmitted = false; &#x2F;&#x2F; Tracks if a message has been submitted float effectTimer = 0.0f; &#x2F;&#x2F; Timer for the flash effect const float effectDuration = 0.5f; &#x2F;&#x2F; Flash duration in seconds while (!WindowShouldClose()) { &#x2F;&#x2F; Update effect timer if (effectTimer &gt; 0) { effectTimer -= GetFrameTime(); } BeginDrawing(); &#x2F;&#x2F; Set background color based on effect if (effectTimer &gt; 0) { ClearBackground((Color){ 255, 255, 150, 255 }); &#x2F;&#x2F; Yellow flash (RGB order) } else { ClearBackground(RAYWHITE); } &#x2F;&#x2F; Center the text box and button int textBoxWidth = 200; int textBoxHeight = 40; int buttonWidth = 120; int buttonHeight = 40; int textBoxX = (WINDOW_WIDTH - textBoxWidth) &#x2F; 2; int textBoxY = (WINDOW_HEIGHT - textBoxHeight) &#x2F; 2 - 40; int buttonX = (WINDOW_WIDTH - buttonWidth) &#x2F; 2; int buttonY = textBoxY + textBoxHeight + 10; &#x2F;&#x2F; Draw the text box if (GuiTextBox((Rectangle){ (float)textBoxX, (float)textBoxY, textBoxWidth, textBoxHeight }, inputText, MAX_INPUT_CHARS, textBoxEditMode)) { textBoxEditMode = !textBoxEditMode; &#x2F;&#x2F; Toggle edit mode on click } &#x2F;&#x2F; Draw the button if (GuiButton((Rectangle){ (float)buttonX, (float)buttonY, buttonWidth, buttonHeight }, &quot;Submit&quot;)) { messageSubmitted = true; effectTimer = effectDuration; &#x2F;&#x2F; Start the flash effect TraceLog(LOG_INFO, &quot;Message submitted: %s&quot;, inputText); } &#x2F;&#x2F; Display the submitted message if (messageSubmitted &amp;&amp; inputText[0] != &#x27;\0&#x27;) { const char *label = &quot;Message: &quot;; char displayText[256]; snprintf(displayText, sizeof(displayText), &quot;%s%s&quot;, label, inputText); int textWidth = MeasureTextEx(font, displayText, 32, 1).x; int textX = (WINDOW_WIDTH - textWidth) &#x2F; 2; int textY = buttonY + buttonHeight + 20; DrawTextEx(font, displayText, (Vector2){ (float)textX, (float)textY }, 32, 1, (Color){ 33, 150, 243, 255 }); &#x2F;&#x2F; Bright blue (RGB order) } EndDrawing(); } UnloadFont(font); CloseWindow(); return 0; } </code></pre> I love it! I feel unleashed again to program in graphics and games and real GUI! The first real paid programming job I had was using a lot of ps5 in Java and JavaScript (Open Processing) and I dug it! :)<p>And the file sizes are sweet (to me):<p>- macOS: text_input - 123736<p>- Windows: text_input.exe - 538909<p>Two dependencies to distribute with on Windows: glfw3.dll and libraylib.dll (322K and 2.1MB respectively)<p>Raylib was built to make game programming fun. And maybe I will use it for that! :) But right now I want to use it for GUI. The issue with Qt and others, is while I like the idea of standard-Andy controls, I don&#x27;t want to pay a commercial license - when I figure &quot;it can&#x27;t be <i>that</i> hard to get what I want&quot; - as I plan to use this stuff for commercial&#x2F;proprietary control-panes and layers on my existing products: BrowserBox, DiskerNet, and more.<p>At the same time I really respect what Qt have done growing their business and might be inspired or even emulate some of their model myself in my business.
thehiasvor 1 Tag
278kb? you are doing something very wrong, this should be possible in 10kb!
评论 #43956697 未加载
fizlebitvor 1 Tag
Me no like inconsistent use of spaces.<p><pre><code> x += labelW+20; hDescEdit = createModernEdit(hwnd, x, y, editW, btnH, ID_DESC_EDIT); x += editW + gap; </code></pre> What no clang-format or equiv in 1990?