10 puan yazan GN⁺ 2025-05-12 | 3 yorum | WhatsApp'ta paylaş
  • Simple Todo, C ve Win32 API ile yapılmış yerel bir Windows Todo uygulamasıdır; Windows GUI programlama ve sistem entegrasyonu özelliklerini gösteren bir projedir
  • Başlıca özellikler: Todo oluşturma·düzenleme·silme, tamamlandı olarak işaretleme, sistem tepsisine küçültme, Windows ile otomatik başlatma seçeneği ve büyük/küçük harf duyarsız gerçek zamanlı arama
  • Veriler %APPDATA%\TodoApp\todos.dat içinde ikili dosya olarak saklanır; tüm Todo listesini içerir ve en fazla 100 Todo destekler
  • Derleme için Windows üzerinde MinGW-w64 ve Windows SDK gerekir; depoyu klonladıktan sonra .\build.bat ile derlenir
  • Yapı main.c, todo.c, gui.c, utils/search.c olarak ayrılmıştır ve GUI, Win32 API·Common Controls·UXTheme kullanır

Projenin niteliği

  • Simple Todo, C ve Win32 API ile yazılmış yerel bir Windows Todo uygulamasıdır
  • Hafif bir yerel çalıştırılabilir dosyayı hedefler ve Windows'un varsayılan görünümünü ve hissini, ayrıca modern Windows görsel stillerini kullanır
  • GUI, Win32 API tabanlıdır; sistem tepsisi entegrasyonu ve dosya G/Ç üzerinden veri kalıcılığı içerir

Todo özellikleri

  • Todo öğeleri oluşturulabilir, düzenlenebilir ve silinebilir
  • Görevler tamamlandı olarak işaretlenebilir
  • Her Todo için öncelik ayarlanabilir
  • Arama özelliği gerçek zamanlı çalışır ve büyük/küçük harf duyarsız eşleşme destekler
  • Uygulama sistem tepsisine küçültülebilir
  • Windows başlangıcında otomatik çalıştırma seçeneği sunar

Veri saklama yöntemi

  • Todo verileri %APPDATA%\TodoApp\todos.dat içinde saklanır
  • Kayıt biçimi, tüm Todo listesini içeren bir ikili dosyadır
  • Depolama kapasitesi en fazla 100 Todo ile sınırlıdır

Derleme ve çalıştırma

  • Gereksinimler
    • Windows OS
    • MinGW-w64 GCC derleyicisi
    • MinGW ile gelen Windows SDK
  • Derleme adımları
    • MinGW-w64'ü kurun ve bin dizinini sistem PATH değişkenine ekleyin
    • Depoyu klonladıktan sonra simple-todo-c dizinine geçin
    • Derlemek için .\build.bat komutunu çalıştırın
  • Uygulama bin/todo.exe ile başlatılır

Uygulama yapısı

  • Proje yapısı işlevlere göre C dosyalarına ayrılmıştır
    • src/main.c: uygulama giriş noktası
    • src/todo.c, src/todo.h: Todo yönetim mantığı ve veri yapıları
    • src/gui.c: GUI uygulaması
    • src/utils/search.c, src/utils/search.h: arama işlevinin uygulanması ve bildirimi
    • src/app.manifest: Windows görsel stilleri için manifest
  • Temel bileşenler Win32 API, Common Controls, UXTheme ve File I/O'dur
  • Hata ayıklama için Visual Studio, VS Code vb. ile kullanılabilen DEBUGGING.md kılavuzu sağlanır

Lisans ve katkı

  • Lisans MIT License'dır
  • Pull Request yoluyla katkı kabul edilir

3 yorum

 
aer0700 2025-05-13

Tam bir nostalji havası var.

 
GN⁺ 2025-05-12
Hacker News yorumları
  • Win32 GUI programlamada garip biçimde hoşuma giden bir şey var
    Biraz tuhaf, ama Raymond Chen’in blogunu okursanız nedenini görürsünüz
    Win32 API’nin kökleri 8088 işlemci dönemine dayanıyor; belirli bir şekilde yapınca 40 bayt kod tasarrufu etmek ya da bir register’ı daha az kullanmak gibi arka planları var
    Eskiden mingw ve Petzold kitabıyla çok sayıda oyuncak GUI uygulaması yapmıştım; özel kontrol yazmak, grafik ve metin çizmek, kaydırmayı işlemek, hit test yapmak gibi şeylerin hepsi epey eğlenceliydi
    Uygulamada strcpy, sprintf kullanıldığı görülüyor; ciddi programlama için uzunluk kontrolü yapan varyantları kullanmak gerekir. Derleyicinin uyarı yağdırmamış olması şaşırtıcı
    Win32 API’de C standart kütüphanesindekilerin yerine geçen çok sayıda işlev var. Çalıştırılabilir dosya boyutunu gerçekten küçültmek istiyorsanız uygulamayı C standart kütüphanesi olmadan yazmayı deneyebilirsiniz. memset() yerine ZeroMemory(), memcpy() yerine CopyMemory() var
    Bir noktadan sonra saf C kodunu elle yazmak acı verici hale geliyor, ama ilk birkaç denemeyi saf C ile yapmanın öğrenmek için en iyisi olduğunu düşünüyorum. Ayrıntıları kendiniz yönettiğinizde öğrenme sürecinde içeride neler döndüğünü daha iyi kavrıyorsunuz
    Win32 GUI programlamayı daha fazla denemek istiyorsanız WTL(Windows Template Library)’ye bakmanızı öneririm. Win32 API’yi saran bir C++ sarmalayıcısı olduğu için davranışını anlamak çok daha kolaylaşıyor

    • AlomWare Toolbox adlı harika bir PC uygulaması kullanıyorum; Win32 tasarımının tipik örneğine oldukça yakın(https://www.alomware.com/images/tab-automation.png)
      Çok fazla özelliği olmasına rağmen bu sayede boyutu yalnızca yaklaşık 3MB. Framework yok, tek bir çalıştırılabilir dosyadan ibaret; keşke tüm yazılımlar hâlâ böyle olsa
    • Bugünlerde en azından strcpy yerine strncpy kullanmazsanız, yalnızca insanlardan değil yapay zeka araçlarından bile bunu yapmamanız gerektiğini tekrar tekrar duymayı göze almanız gerekir
      Kişisel olarak Zig kullanmamın başlıca nedenlerinden biri, bu tür yaygın tuzakların çoğunu azaltması. Elbette C de gayet iyi
    • memset() yerine ZeroMemory(), memcpy() yerine CopyMemory() olduğunu söylediniz ama MSVC intrinsic muhtemelen rep stos/movs komutlarını kullanır
      Bir fonksiyon çağrısından daha küçük olabilir. Çünkü fonksiyon çağrısına import table girdisinin boyutu da dahildir
    • Bu tür işleri çok yaptım ve dürüst olmak gerekirse native kodla native UI geliştirebilme becerisini özlüyorum
    • fopen/fread/fclose da kullanıyor; CreateFile/ReadFile/WriteFile gibi Win32 API’lerini kullanmıyor gibi görünüyor
  • Her kontrol için zahmetle CreateWindow() çağırmak yerine, geleneksel olarak .rc dosyasına dialog resource yerleştirilir (Visual Studio’da bunu görsel olarak yapabilen dialog editor hâlâ var) ve CreateWindow() yerine CreateDialog() kullanılırdı
    Böylece tüm kontroller otomatik olarak oluşturulur. Uygulama manifest’i eklerseniz modern UI stili ve yüksek DPI desteği de elde edebilirsiniz

    • Bu yöntemle kontroller arasında Tab ile geçiş ve birkaç klavye kısayolu da otomatik gelir
      Ancak yeniden boyutlandırma istiyorsanız bunu yine elle işlemeniz gerekir; ama genellikle kolaydır ve kod da birkaç yüz baytı geçmez
    • C standart kütüphanesi ile işletim sistemi kütüphanesinin çakışması pratikte yalnızca UNIX için geçerli; Windows 1.0’ın çıktığı 1985’te henüz standart denebilecek bir şey de yoktu
      K&R C vardı, ama UNIX dışındaki her işletim sistemi hangi işlevleri sunacağını kendi seçiyordu
      Üstelik UNIX ailesinden olmayan yerlerde standart kütüphaneden platformun değil C derleyicisinin sorumlu olduğu bir gelenek vardı
      Bu yüzden C kütüphanesini Borland, Watcom, Symantec, Microsoft, Green Hills, Zortech gibi firmalar sağlıyordu
      Mac OS de MPW çıkana kadar böyleydi; IBM ve Unisys, mikro bilgisayarlar ve ana bilgisayarlar, OpenVMS öncesi VMS de öyleydi
      Windows 10’dan beri Universal C Runtime da var
    • Bu yaklaşım, düzgün bir yabancı fonksiyon arayüzü (FFI) olan dillere kolayca taşınabilir ve bunun dışında hiçbir şeye ihtiyaç duymaz
      Resource compiler’a da, resource DLL’i oluşturacak linker’a da gerek yok
      Resource dosyaları ve bunların ikili formatı iyi bir API değil
      Makul ölçüde yüksek seviyeli bir dilde CreateWindow çağrıları varsa, dile iyi oturan resource benzeri bir DSL’i metaprogramlama ile oluşturmak mümkün olabilir
  • Eskiden Linux’ta assembly ile buna benzer bir şeyi 2KiB’nin altında yapmıştım: https://gaultier.github.io/blog/x11_x64.html
    Başkalarının da söylediği gibi saf C ile yapıp dinamik linking kullanırsanız, en azından Linux’ta 20KiB’nin altında tutmak kolaydır. Windows’ta işletim sistemine varsayılan olarak dahil olan çok daha fazla şey olduğundan daha da kolay olabilir
    Her hâlükârda denemeyi destekliyorum. Yazımın sonunda belirttiğim linker seçeneklerini denerseniz boyutu küçültmeye yardımcı olacaktır

    • Biraz genişletilmiş ncurses tabanlı TUI TODO programı 15K. Linux ve statik linkli değil
      Henüz musl ile ncurses derlemeyi deneyemedim
  • “Native Windows look and feel” denince, gerçekten çalıştırmadan önce liste görünümünde bir context menu olmasını ve belirli alanlara çift tıklayınca satır içinde sayılabilecek bir açılır menü ya da metin kutusu çıkmasını beklemiştim
    Artık Win32 UI/UX’e uygun program tasarlamayı bilmiyorlar mı, yoksa ben mi çok yaşlandım, bilmiyorum

  • “Framework yok” denmiş ama DPI ölçeklemede yazı tipleri bulanık, Tab desteği yok, metin alanında Ctrl-A ile tümünü seçme çalışmıyor; modern öncesi framework’lerin bile sunduğu birçok özellik eksik ve satır eklerken hata da oluşuyor
    “Modern” derken ne kastediliyor bilmiyorum

    • DPI farkındalığı ayarı için örnek burada: https://github.com/Dwedit/GameStretcher/blob/master/Stretche...
      Bu kod user32:SetProcessDpiAwarenessContext, shcore:SetProcessDpiAwareness, user32:SetProcessDPIAware seçeneklerinden hangisinin mevcut olduğunu dinamik olarak kontrol edip çağırıyor
      Windows sürümü çok eski olup bunların hiçbirini uygulamamışsa (Windows XP öncesi), hiçbirini çağırmıyor
    • “Modern” demek, gerekenden çok daha büyük olup birçok özelliğin eksik olması anlamına geliyor gibi
      Eksik diye sayılan özelliklerin çoğunu eklemek çok kolay; özellikle kontroller arasında Tab ile geçiş gibi şeyleri
  • İçimdeki 6502 programcısı, 278KB’nin artık hafif sayıldığını gördükçe içten içe ölüyor

    • Bu ikiliyi yeniden üretip 278KB’nin nereye gittiğini görmek istedim
      Karşılaştığım ilk engel, git core.autocrlf=false olarak ayarlıysa build.bat dosyasının çalışmamasıydı. core.autocrlf=true yapıp tekrar klonlayınca derleyebildim
      Toolchain olarak https://github.com/niXman/mingw-builds-binaries/releases/tag... adresindeki x86_64-15.1.0-release-win32-seh-msvcrt-rt_v12-rev0.7z paketini kullandım
      Bu durumda 102KB’lik bir .exe dosyası çıkıyor. Öne sürülen 278KB’den en baştan çok daha iyi. Yazar farklı bir toolchain veya ayar kullanıyor olabilir; bu yüzden tam yeniden üretim adımları olsa iyi olurdu
      GCC’ye birkaç seçenek vererek daha da küçültmek mümkün
      gcc -Os => 100KB
      gcc -Oz => 99KB
      gcc -flto => 101KB
      gcc -s => 51KB
      gcc -s -Oz -flto => 47KB
      Tek derdiniz küçük .exe boyutuysa hâlâ ciddi iyileştirme alanı var
    • Bunun önemli bir kısmı platform ve çalıştırılabilir dosya biçimi yüzünden
      Stack trace bilgisi, dinamik linkleme altyapısı, exception handling tabloları gibi şeyler olmasa çok daha hafif olabilir. Exception handling tabloları, exception’ların C fonksiyonlarının içinden geçebilmesi nedeniyle C’de de gerekli
    • Demoscene yarışmalarında 64KB TODO uygulaması kategorisi açılması için dilekçe verebiliriz belki
    • Açıkçası bu kadar büyük olması şaşırtıcı. Daha küçük olmasını ya da neredeyse yarısının uygulama ikonundan gelmesini beklerdim
      Eskiden böyle bir şey yazdığımda daha küçük olduğunu hatırlıyorum. Acaba MinGW yüzünden mi?
    • Birden Win32’yi assembly ile programlamanın epey havalı olduğu dönemler aklıma geldi
      Muhtemelen shareware indirme boyutlarının büyümesine verilen bir tepkiydi. MFC’nin karanlık çağıydı
      Erken dönem Palm Pilot 68k programlamayla birlikte, retrocomputing olmayan assembly’nin son alkışları olarak hatırlıyorum
  • Arkadaşlar, bu sadece denenip eğlence için yapılmış bir uygulama. Yorumlar haklı; böyle bir şey muhtemelen C++ veya başka bir dille daha makul şekilde yapılabilirdi

    • Yaklaşık 30 yıl önce ilk Windows programımı yazarken ben de tam böyle öğrenmiştim. Sadece muhtemelen C++ derleyicisi kullanmışımdır
      Nedenini tam bilmiyorum ama Windows API belgeleri C tarzı kodu C++ derleyicisiyle yazma yönünde yönlendiriyor gibiydi. Microsoft, C++’ı C’nin geliştirilmiş bir üst kümesi olarak görüp C tarzı kod için de kullanılmasının doğru olduğunu düşünmüş olmalı
    • Şaka değil, bu uygulamayı varsayılan Windows 11 TODO uygulamasına tercih ederim
    • Olması gereken yol tam da bu
      Win32 API kullanacaksanız başka bir dil temelde hiçbir şeyi değiştirmez; hatta işleri daha da kafa karıştırıcı hâle getirebilir
      İnsanlar sık sık C++ tarzı düşünmeye saplanıyor ve Win32 API’ye aşina olmayan biri için bütünü daha da karmaşık bir yığın hâline getirirdi
      Çok sevimli bir deneme ve başkaları ne düşünürse düşünsün Win32 API’ye aşinalık iyi bir temel yetkinliktir
    • https://github.com/Efeckc17/YoutubeGO Referans olarak, bu uygulamayı da inceleyip değerlendirirseniz gerçekten çok mutlu olurum
    • Böyle temiz native UI projeleri, programlama öğrenme motivasyonumu oluşturan şeydi. Harika
  • Burada, kullanıcı fareyi her oynattığında 278KB telemetri göndermek için birkaç MB JS veya C# yükleyen yazılım ya da web siteleri yapan insanların epey alay ettiğini görüyorum

    • C# + WinForms ile yapılmış benzer bir uygulama diskte 10KB’den küçük ve 6MB RAM kullanıyor
      Bu uygulama 1,5MB RAM kullanıyor; ikisi de anında açılıyor
  • Windows uygulaması geliştirirken her şeyi C ile yapabilmek insanı her zaman iyi hissettiriyor
    En düşük seviyedeki temel yapı taşlarından başlayıp üstüne koyarak ilerlemek gayet doğal geliyor
    Buna karşılık macOS’te her şey Objective-C nesnesi olduğu için, saf C ile uygulama yazmak mümkün olsa da Apple’ın amaçladığı soyutlamanın bir seviye altına inmiş oluyorsunuz; bu da neredeyse 1000 kat daha laf kalabalığına dönüşüyor. Bir şey yapmak için fiilen Objective-C sınıf hiyerarşisini kukla gibi oynatmak gerekiyor; bu gerçekten rahatsız edici
    Objective-C’nin sınıf tabanlı API’sinin neden temel Win32 tarzı prosedürel API’nin üstüne tekrar oturtulamadığını bilmiyorum. Teknik olarak Win32 de “sınıf tabanlı” sayılır ama bu asgari düzeyde
    Bu yüzden şimdilik C kodumu macOS’e port etmeye pek içim elvermiyor

    • İlginç şekilde Windows’ta COM ve COM’un üzerine kurulu WinRT adlı kendi nesne yönelimli API/ABI’si var
      Ancak COM arayüzleri için MIDL derleyicisi, arayüzleri C’de kullanıp uygulayabileceğiniz header’lar üretiyor: https://www.codeproject.com/KB/com/com_in_c1.aspx
      Bildiğim kadarıyla bugün WinRT’de de hâlâ çalışıyor. Yalnız üretilen C struct’larının ve fonksiyon adlarının tüm namespace’i içermesi gerektiğinden çok çirkinleşiyor: https://stackoverflow.com/a/7437006/111335
    • Prosedürel bir API vardı; adı Carbon’dı
      user32.dll’in bariz biçimde kopyaladığı Macintosh Toolbox API’si için neredeyse drop-in bir ikameydi
      Ancak programcının hissettiği sıcaklık dışında, UI gerçekten nesne yönelimli olmak ister. Bazı ortak davranışları paylaşan farklı nesnelerden oluşan bir ağaç, UI kodunun %99’unu neredeyse birebir açıklar
      Toolbox ve Carbon’da bu nesne yönelimlilik eksikti, bu yüzden epey zorlandılar. Windows’un gerçekten eklediği daha özgün fikirlerden biri de pencere sınıfıydı
      Kişisel olarak C’den Objective-C sınıflarıyla doğrudan uğraşırken hissettiğim tuhaflığın aynısını, user32.dll kodunda pencere sınıfları veya pencere prosedürleri tanımlamak zorunda kaldığım her seferinde hissediyorum[0]
      UI nasıl nesne yönelimliliği istiyorsa, nesne yönelimlilik de kendine özel dil özellikleri ister. Onlar olmadan da yapılabilir ama kullanılabilirlik 2000 kat kötüleşir
      [0] Ya da GTK/GObject ile ilgili herhangi bir şey
  • Statik bir kütüphaneye link ediyormuş gibi görünüyor
    Statik kütüphane yerine DLL’e link etmeli; böylece uygulama boyutu ciddi ölçüde küçülür

    • Bu bana tam tersi gibi görünüyor
      DLL’i zaten programla birlikte dağıtmanız gerekiyorsa (işletim sisteminin parçası olmadığı için), DLL tüm işlevleri içerir ve her DLL kendi C runtime’ına bile sahip olabilir
      Her şeyi tek bir EXE’ye statik olarak derlerseniz yalnızca bir C runtime olur ve kullanılmayan fonksiyonlar kolayca çıkarılabilir
      DLL ancak o kod birden fazla program arasında paylaşıldığında boyutu küçültür
    • Hayır, CRT’nin statik sürümüne link etmek iyi bir seçim. Kullanılmayan kodu budayabilirsiniz
      MSVCRxx/VCRUNTIME’a dinamik link verirseniz kullanıcının Microsoft’tan tam olarak o DLL’i indirmesi gerekir
      MSVCRT’ye dinamik link verirseniz bu sorun olmaz ama Visual Studio’da bunu yapmak çok zordur
      CRT’ye statik link vermenin gerçekten sorun olacağı durum muhtemelen yalnızca LGPL uyumluluğudur
 
roxie 2025-05-16

Ağabeylerin nefesi buraya kadar ulaşıyor gibi bir his...