Een Windows-programma in FASM

johanok / at / gmail adres

Als test de FASM broncode van een klein programma (met een knop en een commando). Gewoon om te tonen hoe een knop (en een commando uitvoeren) gebruikt wordt in FASM. In dit voorbeeld wordt na een knopklik de browser geopend in een nieuw venster, en gaan we naar de pagina http://users.telenet.be/sf15419/palmen.html





format PE GUI 4.0      ; compileer met de gratis fasm compiler - flat assembler
                       ; openen met FASMW.EXE, opslaan als [folder\] 'naam.asm' en 'runnen'
entry start            ; grootte van de exe: 3.584 bytes

section '.idata' import data readable writeable        ; bibliotheken - dlls (de functies hier in worden gebruikt)

include 'win32a.inc'

library kernel32,  'KERNEL32.DLL', \                   ; Windows is niet hoofdlettergevoelig
        user32  ,  'USER32.DLL', \                     ; in tegenstelling tot opdrachten in asm zelf
        shell32,   'SHELL32.DLL', \
        gdi32,     'GDI32.DLL', \
        comctl32,  'COMCTL32.DLL'

include '\api\KERNEL32.INC'                            ; o.a. GetModuleHandle gebruikt deze dll
include '\api\user32.inc'                              ; deze voor functies o.a. [LoadIcon] en [LoadCursor]
include '\api\shell32.inc'                             ; hier voor ShellExecute
include '\api\gdi32.inc'                               ; deze dll voor [CreateFont]
include '\api\comctl32.inc'                            ; voor InitCommonControls

section '.data' data readable writeable                     ; declaratie variabelen en constanten
  KlasseVenster          db 'OmHetEven', 0                  ; db = define byte (FF of 0 ~ 255) of stringconstante
  KlasseKnop             db 'BUTTON', 0
  Titel                  db 'Open Pagina', 0                ; strings - (moeten null terminated zijn)
  TextKnopShell          db 'Openen in een nieuw venster', 0
  FoutTekst              db 'Foutmelding', 0
  NietOpenTekst          db 'Kan de toepassing niet vinden', 0
  BestandsModus          db 'open', 0
  FontName               db 'MS Sans Serif', 0
  TeOpenenProg           db 'iexplore.exe', 0               ; kan ook 'notepad.exe'
  TeOpenenBestand        db 'http://users.telenet.be/sf15419/palmen.html', 0   ; optioneel, mag NULL zijn
  hwnd                   dd ?                               ; handle van Venster
  hKnop1                 dd ?                               ; handle van Knop1
  hFont                  dd ?                               ; handle van font - dd = define double

  wc WNDCLASS 0, WindowProc, 0, 0, 0, 0, 0, COLOR_BTNFACE+1, 0, KlasseVenster
  msg MSG

section '.code' code readable executable                    ; uitvoerbare gedeelte van code
start:                                                      ; klassen registreren
  invoke  GetModuleHandle, 0                                ; invoke = functie van windows api aanroepen
  mov     [wc.hInstance], eax                               ; handle komt in eax-register, hier opslaan
  invoke  LoadIcon, 0, 32515                                ; uitroepteken-icoon van windows
  mov     [wc.hIcon], eax                                   ; registreren bij venster
  invoke  LoadCursor, 0, IDC_ARROW                          ; huis- tuin- en keuken gewoon windows pijltje
  mov     [wc.hCursor], eax                                 ; registreren bij venster
  invoke  RegisterClass, wc                                 ; indien registreren gelukt is, is eax 'true'
  or      eax, eax                                          ; nakijken of gelukt (als eax nul is, mislukt)
  jz      error                                             ; indien niet, 'jump if zero' jz naar label "error"
  invoke InitCommonControls                                 ; voor zichtbaarheid knop in XP en Vista
  invoke  CreateWindowEx, WS_EX_TOPMOST, KlasseVenster, Titel, WS_VISIBLE + WS_SYSMENU, \
          12, 24, 180, 60, 0, 0, [wc.hInstance], 0          ; venster aanmaken
  or      eax, eax                                          ; test of het gelukt is
  jz      error                                             ; indien niet: foutmelding
  mov     [hwnd], eax                                       ; indien wel handle van venster vastleggen
  invoke  CreateWindowEx, 0, KlasseKnop, TextKnopShell, WS_VISIBLE+WS_CHILD+ BS_PUSHBUTTON+WS_TABSTOP, \
          2, 2, 170, 22, [hwnd], 1004, [wc.hInstance], 0    ; knop 'openen' creeren
  mov     [hKnop1], eax                                     ; handle van knop vastleggen
  invoke  CreateFont,14,5,0,0,0,FALSE,FALSE,FALSE,ANSI_CHARSET,OUT_RASTER_PRECIS,\
                     CLIP_DEFAULT_PRECIS,DEFAULT_QUALITY,FIXED_PITCH+FF_DONTCARE,FontName
  or      eax, eax                                          ; font creeren en registreren en kijken of gelukt
  jz      error                                             ; indien niet enz...
  mov     [hFont],eax                                       ; handle font registreren
  invoke  SendMessage, [hKnop1],  WM_SETFONT, [hFont],0     ; font zetten voor de knop
msg_loop:                                              ; standaard windows oneindige lus; houdt venster open
  invoke  GetMessage, msg, 0, 0, 0                     ; while GetMessage(MainMsg, 0, 0, 0) do        <----
  or      eax, eax                                     ; is het een bericht "toepassing afsluiten"?        |
  jz      end_loop                                     ; indien ja: (eax=0) jz jump if zero naar end_loop  |
  invoke  IsDialogMessage, [hwnd], msg                 ; is het een dialoogbericht (een tab bvb)           |
  or      eax, eax                                     ; antwoord komt in accumulatorregister eax          |
  jnz     msg_loop                                     ; jump if not zero If not IsDialogMessage(msg) then |
  invoke  TranslateMessage, msg                        ; translate bericht                                 |
  invoke  DispatchMessage, msg                         ; dispatch bericht                                  |
  jmp     msg_loop                                     ; loop       >-------->-------->-------->-------->--
error:                                                 ; label bij fouten
  invoke  MessageBox, 0, FoutTekst, 0, MB_ICONERROR+MB_OK ; wordt enkel bij fout getoond
end_loop:                                              ; label einde programma
  invoke  ExitProcess, [msg.wParam]                    ; en Windows API call: einde programma
  
proc WindowProc hwnd, wmsg, wparam, lparam             ; procedure voor berichtendispatching
  push    ebx esi edi                                  ; base register, source index en destination index opslaan
  cmp     [wmsg], WM_COMMAND                           ; in Delphi is dit case wmsg of, in C switch msg
  je      .wmcommand                                   ; wat te doen bij welk commando
  cmp     [wmsg], WM_DESTROY                           ; vergelijk het bericht met sluiten toepassing
  je      .wmdestroy                                   ; 'je' jump if equal naar label wmdestroy
  .defwndproc:
    invoke  DefWindowProc, [hwnd], [wmsg], [wparam], [lparam] ; moet voor normaal windows-gedrag
    jmp     .finish
  .wmcommand:                                          ; nakijken of er een commando was
    cmp     [wparam], 1004                             ; kijk na of het van de knop afkomstig is
    je      .KnopSchrijf                               ; zo ja, ga naar label KnopSchrijf
    jmp     .finish                                    ; zo neen: niets doen
  .KnopSchrijf:                                        ; naar hier indien knopklik dus
    invoke ShellExecute, NULL, BestandsModus, TeOpenenProg, TeOpenenBestand, NULL, SW_SHOW ; voer extern commando uit
    cmp     eax, 32                                    ; indien gelukt is de returncode groter dan 32
    ja      .finish                                    ; indien gelukt einde opdrachten
    invoke  MessageBox, [hwnd], NietOpenTekst, 0, MB_ICONERROR+MB_OK ; indien mislukt: toon POPUP - bericht aan de gebruiker
    jmp     .finish                                    ; ga naar einde functie WindowProc
  .wmdestroy:                                          ; einde programma
    invoke  PostQuitMessage, 0                         ; Windows api call einde programma
    xor     eax, eax                                   ; eax op 0 zetten in 2 kloktikken (deze lijn moet niet echt)
  .finish:                                             ; einde functie proc WindowProc
    pop     edi esi ebx                                ; destination index, source index en base register terugzetten
    ret                                                ; terug naar aanroepende functie
endp                                                   ; einde procedure

section '.rsrc' resource data readable                 ; sectie bronnen: hier resources voor runtime themes 'window styles'
  directory RT_MANIFEST,manifest                       ; afgeronde knoppen e.d. ipv hoekige verouderde knoppen
  resource manifest,1,LANG_NEUTRAL,man                 ; moderne progressbar, aanvinkvak enz...
  resdata man
    db '<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">'
    db '<dependency><dependentAssembly><assemblyIdentity '
      db 'type="win32" name="Microsoft.Windows.Common-Controls" '
      db 'version="6.0.0.0" processorArchitecture="X86" '
      db 'publicKeyToken="6595b64144ccf1df" language="*" />'
    db '</dependentAssembly></dependency></assembly>'
endres                                                 ; einde resdata


Dit compileert tot een exe van 3.584 bytes. Uiteraard is dit een eenvoudig voorbeeld, het is perfect mogelijk om een veel uitgebreider programma te maken. Alles wat in een andere programmertaal mogelijk is, is dat hier ook. Het lijkt in het begin wat omslachtig, maar het went snel. En het resultaat is een zeer klein en razendsnel programma.




Een uitgebreider programma in FASM: een kladblokje. Dit is al wat moeilijker, omdat we bestanden moeten kunnen openen en opslaan (met bestand / openen / opslaan dialoogbox), en ook omdat we bij een "resize" van het venster, het edit-veld mee resizen, en een aanvinkvak mee moeten verplaaten. Om iets toe te voegen dat het windows kladblok niet heeft, dit voorbeeld kan "on top" blijven of niet, volgens de keuze van de gebruiker. Hoe ziet het er uit?


Hier worden ook de runtime themes gebruikt. Bij FASM worden voorbeelden bijgeleverd, o.a. een "minipad". Mooi om even de bron te bestuderen, maar het kon alleen tekstjes bewerken (en niet uit bestand openen of opslaan). Vandaar dat ik dit verder bewerkt heb. Overigens vindt men zo goed als geen voorbeelden voor het gebruik van die runtime themes - Window styles - afgezien van deze pagina. Nu de broncode hiervan:



format PE GUI 4.0 
entry start 

include 'win32a.inc'

section '.data' data readable writeable        ; declaratie van variabelen, constanten  en handles
  GrootteGeheugen        equ 131071
  MaxLengtePad           equ 260
  GrootteBestandOpen     equ 76
  Klasse                 db 'Om_HetEven', 0
  Titel                  db 'OnTopPad - Bewerkt Max. 128 KBytes', 0
  KlasseKnop             db 'BUTTON', 0
  KlasseEdit             db 'EDIT', 0
  TekstCheckbox1         db 'On Top', 0
  TextKnopLees           db 'Openen', 0
  TextKnopSchrijf        db 'Opslaan', 0
  FoutTekst              db 'Fout', 0
  buffer:       times    MaxLengtePad db 0
  FontNaam1              db 'MS Sans Serif', 0
  FontNaam2              db 'Arial', 0
  FilterString           db 'Text Files',0,'*.TXT;',0
                         db 'All Files',0,'*.*',0,0

  hMem                   rd 1
  pMem                   rd 1
  GrootteBlok            rd 1
  hwnd                   dd ?   ; handle van Venster
  hEdit1                 dd ?   ; handle van editbox 1
  hKnop1                 dd ?   ; handle van knop 1
  hKnop2                 dd ?
  hCheck1                dd ?   ; checkbox
  hFile                  dd ?   ; handle van bestand
  hFont1                 dd ?
  hFont2                 dd ?

  wc     WNDCLASS 0, WindowProc, 0, 0, 0, 0, 0, COLOR_BTNFACE+1, 0, Klasse
  msg    MSG
  ofn    OPENFILENAME
  client RECT

section '.code' code readable executable                    ; begin uitvoerbare code

start:                                                      ; klassen registreren
  invoke  GetModuleHandle, 0                                ; hoofdinstantie opvragen - antwoord komt in eax-register
  mov     [wc.hInstance], eax                               ; vastleggen in variabele
  invoke  LoadIcon, 0, 32515                                ; 32515 = vraagteken-icoon van windows
  mov     [wc.hIcon], eax                                   ; ook weer vastleggen
  invoke  LoadCursor, 0, IDC_ARROW                          ; huis- tuin- en keuken gewoon windowspijltje
  mov     [wc.hCursor], eax                                 ; weer eens vastleggen want eax = vluchtig
  invoke  RegisterClass, wc                                 ; kijken of registreren van de klasse gelukt is
  or      eax, eax                                          ; indien eax niet 0 is, is het gelukt
  jz      error                                             ; jump iz zero (jz) = indien niet gelukt
  invoke InitCommonControls                                 ; voor zichtbaarheid knoppen in XP en Vista
  invoke  CreateWindowEx, WS_EX_TOPMOST, Klasse, Titel, WS_VISIBLE + WS_OVERLAPPEDWINDOW,\
          12, 24, 400, 258, 0, 0, [wc.hInstance], 0         ; venster aanmaken
  or      eax, eax                                          ; test of het gelukt is
  jz      error                                             ; indien niet: stoppen
  mov     [hwnd], eax                                       ; indien wel: handle toekennen
  invoke  CreateWindowEx, 0, KlasseKnop, TextKnopLees, WS_VISIBLE + WS_CHILD + BS_PUSHBUTTON + WS_TABSTOP, \
          4, 2, 70, 22, [hwnd], 1000, [wc.hInstance], 0     ; Knop Openen
  mov     [hKnop1], eax
  invoke  CreateWindowEx, 0, KlasseKnop, TextKnopSchrijf, WS_VISIBLE + WS_CHILD+ BS_PUSHBUTTON + WS_TABSTOP,\
          78, 2, 70, 22, [hwnd], 1001, [wc.hInstance], 0    ; Knop Opslaan
  mov     [hKnop2], eax
  invoke  CreateWindowEx, 0, KlasseKnop, TekstCheckbox1, WS_VISIBLE + WS_CHILD + BS_AUTOCHECKBOX + WS_TABSTOP, \
          326, 2, 70, 22, [hwnd], 1002, [wc.hInstance], 0   ; Een checkbox (Win32) = een soort knop (KlasseKnop)
  mov     [hCheck1], eax
  invoke  CreateFont, 14, 5, 0, 0, 0, FALSE, FALSE, FALSE, ANSI_CHARSET,\
            OUT_RASTER_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY,\
            FIXED_PITCH + FF_DONTCARE, FontNaam1            ; font 1
  or      eax,eax                                           ; de edit wordt pas bij het wm_create event aangemaakt
  jz      error                                             ; om die aan te passen aan het reeds gemaakte venster.
  mov     [hFont1],eax                                      ; resizen is daarna eenvoudig
  invoke  SendMessage, [hKnop1],   WM_SETFONT, [hFont1], 0  ; font toekennen aan knoppen
  invoke  SendMessage, [hKnop2],   WM_SETFONT, [hFont1], 0
  invoke  SendMessage, [hCheck1],  WM_SETFONT, [hFont1], 0
  invoke  SendMessage, [hCheck1],  BM_CLICK                 ; checkbox moet aangevinkt zijn bij opstart

msg_loop:                                              ; standaard windows oneindige lus houdt venster open
  invoke  GetMessage, msg, 0, 0, 0                     ; while GetMessage(msg, 0, 0, 0) do           <-----
  or      eax, eax                                     ; is het een bericht '0' - "toepassing afsluiten?"  |
  jz      end_loop                                     ; indien ja: jump if zero(jz) naar label end_loop   |
  invoke  TranslateMessage, msg                        ; translate bericht                                 |
  invoke  DispatchMessage, msg                         ; dispatch bericht                                  |
  jmp     msg_loop                                     ; loop       >--------------------------------------

error: 
  invoke  MessageBox, 0, FoutTekst, 0, MB_ICONERROR + MB_OK ; wordt alleen bij fout weergegeven

end_loop: 
  invoke  ExitProcess, [msg.wParam]                    ; bij einde programma

proc WindowProc hwnd, wmsg, wparam, lparam             ; procedure voor berichtendispatching
  push    ebx esi edi                                  ; eerst de vereiste registers bewaren 
  cmp     [wmsg], WM_CREATE                            ; case wmsg of
  je      .wmcreate                                    ; procedure bij creatie venster
  cmp     [wmsg], WM_COMMAND
  je      .wmcommand                                   ; procedure verwerken van commando's
  cmp     [wmsg], WM_DESTROY
  je      .wmdestroy                                   ; procedure einde programma
  cmp     [wmsg], WM_SIZE                              ; wordt het venster geresized?
  je      .wmsize                                      ; jump if equal (je) naar procedure "resizen venster"
  
  .defwndproc:                                         ; dit moet "default" altijd verwerkt worden voor normaal
    invoke  DefWindowProc, [hwnd], [wmsg], [wparam], [lparam]  ; windowsgedrag
    jmp     .finish                                    ; hier komen we enkel indien er geen bericht of commando was

  .wmsize:                                             ; hier start de procedure resizen venster
    invoke  GetClientRect,[hwnd],client                ; vraag grootte van het hele venster op
    mov    eax, [client.bottom]                        ; hoogte in eax opslaan
    sub    eax, 30                                     ; 30 pixels van de onderrand aftellen
    mov    edx, [client.right]                         ; breedte opvragen
    sub    edx, 8                                      ; 8 pixels van breedte afhalen
    invoke MoveWindow, [hEdit1], 4, 28, edx, eax, TRUE ; en nu sizen (edx verliest nu zijn waarde)
    mov    edx, [client.right]                         ; edx dus opnieuw instellen
    sub    edx, 58                                     ; 58 pixels van breedte afhalen (checkbox zelf + tekst 'On Top')
    invoke MoveWindow, [hCheck1], edx, 2, 70, 22, TRUE ; checkbox mee verplaatsen bij het resizen
    jmp     .finish                                    ; ga naar einde procedure "berichtendispatching"

  .wmcreate:                                           ; hier wordt de edit gemaakt en gesized + font toegekend
    invoke  GetClientRect,[hwnd],client                ; grootte van het ganse venster opvragen
    invoke  CreateWindowEx, WS_EX_CLIENTEDGE, KlasseEdit, NULL, WS_VISIBLE + WS_CHILD + WS_TABSTOP + ES_LEFT +\  ; edit
            ES_AUTOVSCROLL + ES_MULTILINE + WS_VSCROLL, \
            4,28,[client.right], [client.bottom],\     ; grootte edit wordt hier aan aangepast
            [hwnd],0,[wc.hInstance],NULL
    mov     [hEdit1], eax                              ; handle van edit opslaan
    invoke  SendMessage, [hEdit1], EM_LIMITTEXT, 131069, 0 ; hoeveel karakters moet de edit verwerken (standaard = 30000)
    invoke  CreateFont, 16, 9, 0, 0, 0, FALSE, FALSE, FALSE, ANSI_CHARSET,\
              OUT_RASTER_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY,\
              FIXED_PITCH + FF_DONTCARE, FontNaam2     ; font 2 toekennen aan edit
    or      eax,eax                                    ; kijk of aanmaken font gelukt is (eax niet nul)
    jz      error                                      ; indien mislukt (indien eax toch nul is) jump if zero naar error
    mov     [hFont2],eax                               ; indien gelukt handle van font opslaan
    invoke  SendMessage, [hEdit1],  WM_SETFONT, [hFont2], 0
    invoke  SetFocus,    [hEdit1]
    stdcall ValOpenFilename, [hwnd]                    ; voorafgaande declaratie - zie laatste procedure van deze code
    jmp     .finish                                    ; ga naar einde procedure "berichtendispatching"

  .wmcommand:                                          ; kijken welk commando verstuurd werd
    cmp     [wparam], 1000                             ; was het knop "Openen"?
    je      .KnopOpen                                  ; en naar de overeenkomstige procedure jumpen hier knop 'openen'
    cmp     [wparam], 1001                             ; cmp compare of wparam 1001 (knop schrijven) is
    je      .KnopSchrijf                               ; zo ja (je = jump if equal) naar juiste label
    cmp     [wparam], 1002                             ; of was het de checkbox...
    je      .Checkbox1                                 ; enz.
    jmp     .finish                                    ; ga naar einde procedure "berichtendispatching"

  .KnopOpen:
    mov     [ofn.Flags], OFN_FILEMUSTEXIST or OFN_PATHMUSTEXIST or OFN_LONGNAMES or\
                         OFN_EXPLORER or OFN_HIDEREADONLY                  ; flags bestand openen zetten
    invoke  GetOpenFileName, ofn                                           ; nakijken
    or     eax, eax
    jz     .finish
    invoke  CreateFile, buffer,\                                           ; bestand openen dialoogbox
                        GENERIC_READ or GENERIC_WRITE ,\
                        FILE_SHARE_READ or FILE_SHARE_WRITE,\
                        NULL, OPEN_EXISTING, FILE_ATTRIBUTE_ARCHIVE,\
                        NULL
    mov     [hFile],eax                                ; handle van gekozen bestand komt in eax --> opslaan dus
    invoke  GlobalAlloc, GMEM_MOVEABLE or GMEM_ZEROINIT, GrootteGeheugen   ; geheugen toekennen
    mov     [hMem], eax
    invoke  GlobalLock, [hMem]                                             ; en reserveren
    mov     [pMem], eax
    invoke  ReadFile, [hFile], [pMem], GrootteGeheugen-1, GrootteBlok, NULL; bestand lezen
    invoke  SendMessage,[hEdit1], WM_SETTEXT,NULL, [pMem]                  ; en naar edit-veld overzetten
    invoke  CloseHandle,[hFile]                                            ; bestand sluiten
    invoke  GlobalUnlock,[pMem]                                            ; geheugenreservatie vrijgeven
    invoke  GlobalFree,[hMem]                                              ; geheugenplaats zelf vrijgeven
    jmp     .finish                                    ; ga naar einde procedure "berichtendispatching"

  .KnopSchrijf:
    mov     [ofn.Flags], OFN_LONGNAMES or OFN_EXPLORER or OFN_HIDEREADONLY
    invoke  GetSaveFileName, ofn
    or     eax, eax
    jz     .finish
    invoke  CreateFile, buffer,\
                        GENERIC_READ or GENERIC_WRITE ,\
                        FILE_SHARE_READ or FILE_SHARE_WRITE,\
                        NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_ARCHIVE,\
                        NULL
    mov     [hFile], eax
    invoke  GlobalAlloc, GMEM_MOVEABLE or GMEM_ZEROINIT, GrootteGeheugen
    mov     [hMem], eax
    invoke  GlobalLock, [hMem]
    mov     [pMem], eax
    invoke  SendMessage, [hEdit1], WM_GETTEXT, GrootteGeheugen-1, [pMem]
    invoke  WriteFile, [hFile], [pMem], eax, GrootteBlok,NULL
    invoke  CloseHandle, [hFile]
    invoke  GlobalUnlock, [pMem]
    invoke  GlobalFree, [hMem]
    jmp     .finish

  .Checkbox1:                                                              ; bij aanklikken van checkbox
    invoke  SendMessage, [hCheck1], BM_GETCHECK                            ; is hCheck1 gechecked? (antwoord in eax)
    or      eax, eax                                                       ; indien eax = 0 dan BST_UNCHECKED
    jz      .NoTop                                                         ; in dat geval niet on top zetten
    invoke  SetWindowPos, [hwnd], HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE + SWP_NOSIZE  ; anders wel on top zetten
    jmp     .finish                                                        ; en einde
    .NoTop:                                                                ; niet on top zetten
    invoke  SetWindowPos, [hwnd], HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE + SWP_NOSIZE
    jmp     .finish                                    ; ga naar einde procedure "berichtendispatching"

  .wmdestroy:                                          ; bij afsluiten toepassing
    invoke  PostQuitMessage, 0

  .finish:                                             ; bij einde procedure
    pop     edi esi ebx
    ret
endp 

proc ValOpenFilename hWin                              ; structuur opzetten voor FileOpenSaveDialog
  mov      [ofn.lStructSize], GrootteBestandOpen
  push     [hWin]
  pop      [ofn.hwndOwner]
  push     [wc.hInstance]
  pop      [ofn.hInstance]
  mov      [ofn.lpstrFilter], FilterString
  mov      [ofn.lpstrFile], buffer
  mov      [ofn.nMaxFile], MaxLengtePad
  ret
endp

section '.idata' import data readable writeable        ; = section 'imports'

library kernel32,  'KERNEL32.DLL', \                   ; aangeroepen dll's (eigenlijk functies in deze dll's)
        user32,    'USER32.DLL', \
        shell32,   'SHELL32.DLL', \
        gdi32,     'GDI32.DLL', \
        comdlg32,  'COMDLG32.DLL',\
        comctl32,  'COMCTL32.DLL'

include '\api\kernel32.inc'
include '\api\user32.inc'
include '\api\shell32.inc'
include '\api\gdi32.inc'
include '\api\comdlg32.inc'
include '\api\comctl32.inc'

section '.rsrc' resource data readable                 ; runtime themes 'window styles' enabled
  directory RT_MANIFEST,manifest                       ; afgeronde knoppen e.d.
  resource manifest, 1, LANG_NEUTRAL, man
  resdata man
    db '<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">'
    db '<dependency><dependentAssembly><assemblyIdentity '
      db 'type="win32" name="Microsoft.Windows.Common-Controls" '
      db 'version="6.0.0.0" processorArchitecture="X86" '
      db 'publicKeyToken="6595b64144ccf1df" language="*" />'
    db '</dependentAssembly></dependency></assembly>'
endres

Deze broncode genereert een exe van 4.608 bytes groot. Het kladblok (notepad.exe) van Microsoft was ooit
 32736 bytes   (Windows 3.11 - [1992]) 
 34304 bytes   (Windows 95   - [1995])
 53248 bytes   (Windows 98   - [1998] - vanaf deze versie was font wijzigen mogelijk)
 69120 bytes   (Windows XP   - [2001] - vanaf deze versie was er geen limiet meer van 64 KBytes)
151040 bytes   (Windows Vista- [2007])
193536 bytes   (Windows 7    - [2009])
243712 bytes   (Windows 8    - [2012])
Dit speeltje is 52 keer kleiner, en kan bovenop andere toepassingen blijven staan. Ok, deze kan niet zoeken en vervangen, en heeft geen fontkeuze-dialogen. Overigens kan die "Max. 128 KBytes" gewoon naar believen gewijzigd worden, kan op heel wat meer gezet worden indien gewenst.

johanok / at / gmail adres

Snellere functies in Delphi
De programmastructuur in Windows
Numlock problemen Windows 8 en 10
Kleinere exe in Delphi zonder de VCL