IT rekvalifikácia. Seniorní programátori zarábajú až 6 000 €/mesiac a rekvalifikácia je prvým krokom. Zisti, ako na to!

1. diel - Dialógové okno Windows v assembleri

V dnešnom ASM tutoriálu pri tvorbe užívateľského rozhrania použijeme funkcie Windows na vytváranie dialógových okien.

Využívanie natívnych dialógových okien

Táto praktika má samozrejme svoje výhody a nevýhody.

Výhody

  • Používame priamo súčasť operačného systému. Nemusíme inštalovať žiadne knižnice.
  • Funguje to vo všetkých verziách Windows.
  • Vo Visual Studiu je editor, v ktorom si môžeme dialógové okná jednoducho naklikať.

Nevýhody

  • Vyzerá to trochu zastaralo. V dnešnej dobe sú ľudia zvyknutí, že všetko musí byť materiálne a ploché.
  • Rozloženie je statické. Ak by sme chceli dynamicky pridávať do formulára ďalšie položky, museli by sme si sami počítať ich súradnice.
  • Nie je možné robiť animácie ani iné špeciálne efekty.

Vytvorenie resources

Formulár si definujeme najprv ako tzv. Resource. V moderných aplikáciách sa resources používajú prevažne pre obrázky a ikony. Ak vytvárame používateľské rozhranie pomocou Win32 API, potom do resoures ukladáme tiež menu, panely nástrojov, klávesové skratky a dialógy. Čokoľvek si dáme do resources, bude vložené do EXE súboru.

Vo Visual Studiu klikneme v Solution Exploreri alebo v menu Project na Add New Item. Potom v ľavom paneli klikneme na Resource a vpravo vyberieme Resource File (.rc).

Programovanie v ASM pre Windows

Keď v Solution Exploreri dvakrát klikneme na novo pridaný .rc súbor, zobrazí sa Resource View. V Resource View klikneme pravým tlačidlom na .rc súbor a zvolíme Add Resource.

Programovanie v ASM pre Windows

Ďalej zvolíme Dialóg a klikneme na tlačidlo New.

Programovanie v ASM pre Windows

Objaví sa editor dialógu a vľavo je toolbox so všetkými možnými ovládacími prvkami.

Zdrojový kód

Keď sa chceme pozrieť na zdrojový kód .rc súboru, v Solution Exploreri naň klikneme pravým tlačidlom a zvolíme View Code. V tejto lekcii použijeme nasledujúci súbor Resource.rc. Môžete si ho odtiaľto celý skopírovať a alebo si ho môžete skúsiť sami naklikať vo Visual Studiu. Pretože súbor vygenerovaný Visual Studiom je pomerne dlhý, tu uvedieme len tie riadky, ktoré sú nevyhnutné na spustenie programu (zvyšok súboru je prípadne k stiahnutiu v archíve pod lekcií):

#include "resource.h"
#include "winres.h"
LANGUAGE LANG_CZECH, SUBLANG_DEFAULT
#pragma code_page(1250)

IDD_LOGIN DIALOGEX 0, 0, 155, 103
STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Vítejte"
FONT 8, "MS Shell Dlg", 0, 0, 0x1
BEGIN
    LTEXT           "Zadejte Vaše jméno:",374,6,9,142,8
    EDITTEXT        IDC_NAME, 7, 26, 142, 14, ES_AUTOHSCROLL
    CONTROL         "Pamatovat si mě",IDC_REMEMBER,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,55,142,10
    DEFPUSHBUTTON   "OK",IDOK,19,78,50,14
    PUSHBUTTON      "Zrušit",IDCANCEL,86,78,50,14
END

Kód korešponduje s nasledujúcim dialógovým oknom:

Programovanie v ASM pre Windows

Použitie resources v ASM

Visual Studio automaticky pre všetky položky generuje číselné identifikátory a vkladá ich do hlavičkového súboru resource.h:

#define IDD_LOGIN                       102
#define IDC_REMEMBER                    1001
#define IDC_NAME                        1002

V assembleri nemôžeme použiť priamo súbor resource.h, ale manuálne z neho musíme vytvoriť resource.inc, ktorý bude vyzerať takto:

IDD_LOGIN equ 102
IDC_REMEMBER equ 1001
IDC_NAME equ 1002

Nie je vhodné používať názvy DIALOG1, CHECK1, EDIT1 atď., Ale je lepšie pomenovať si ovládacie prvky podľa toho, čo ktorý ovládací prvok robí.

Program v assembleri

Pripravíme si súbor s ASM kódom:

        option win64:2
        include windows.inc
        include resource.inc
        .data
remember dd FALSE
name     db "nějaké jméno", 100 dup(0)
        .code

Naša dialógové okno obsahuje jeden prepínač a jedno textové pole. V sekcii .data sú pre nich vytvorené globálne premenné. Všimnite si, že za textom sú vyhradené nulové bajty operátorom dup. To je kvôli tomu, že do premennej potom zapíšeme text, ktorý zadal používateľ. Ak používateľ zadá príliš dlhý text, tak sa oreže.

Kód

Pridajme ďalšie riadky reprezentujúci časť s kódom ASM programu.

dlgproc

Najprv pridáme funkciu pre obsluhu nášho okna:

dlgproc proc hWnd:HWND, msg:UINT, wParam:WPARAM, lParam:LPARAM
        mov hWnd,rcx
        .if edx == WM_INITDIALOG
                invoke CheckDlgButton, hWnd, IDC_REMEMBER, remember
                invoke SetDlgItemText, hWnd, IDC_NAME, addr name
                mov eax,TRUE
        .elseif edx == WM_COMMAND
                .if r8w == IDOK
                        invoke IsDlgButtonChecked, hWnd, IDC_REMEMBER
                        mov remember,eax
                        invoke GetDlgItemText, hWnd, IDC_NAME, addr name, sizeof name
                        invoke EndDialog, hWnd, IDOK
                .elseif r8w == IDCANCEL
                        invoke EndDialog, hWnd, IDCANCEL
                .else
                        mov eax,FALSE
                .endif
        .else
                mov eax,FALSE
        .endif
        ret
dlgproc endp

Názov funkcie si môžeme zvoliť aký chceme. V aplikácii často býva viac okien, takže je rozumné si ich správne pomenovávať, aby sme sa v nich vyznali. V prvom parametra hWnd dostaneme handle nášho okna. Vo Windows je všetka komunikácia medzi oknami a systémom riešená pomocou správ. V parametri msg je typ správy, ktorú máme obslúžiť. Parametre wParam a lParam závisia od toho, o ktorú správu sa jedná. V 64-bitové aplikácii sa parametre odovzdávajú v registroch. Hneď na začiatku si register ECX uložíme do premennej hWnd, pretože ho neskôr budeme potrebovať. Ďalej sme použili príkazy .if, .elseif, .else a .endif, ktoré fungujú podobne ako vo vyšších programovacích jazykoch a zvyšujú čitateľnosť programu.

Vo WM_INITDIALOG vyplníme počiatočnej hodnoty položiek podľa hodnôt z premenných. Funkcia CheckDlgButton zaškrtne prepínač, zatiaľ čo funkcia SetDlgItemText vyplní text. V registri EAX vraciame TRUE, čo znamená, že systém automaticky aktivuje čiže nastaví focus na prvú položku dialógu.

Vo WM_COMMAND sa obsluhujú tlačidlá alebo iné ovládacie prvky. Keď užívateľ stlačí tlačidlo "OK", uložíme si zadané hodnoty do premenných a potom zavrieme okno funkcií EndDialog. Pokiaľ užívateľ stlačí tlačidlo "Zrušiť" alebo zatvorí okno, potom tiež ukončíme dialóg.

Ak správu nespracujeme, musíme v registri EAX vrátiť FALSE a systém správu spracuje za nás a vykoná nejakú predvolenú akciu.

main

A konečne dodáme aj hlavnú funkciu main:

main proc
        invoke GetModuleHandle, NULL
        invoke DialogBoxParam, rax, IDD_LOGIN, 0, addr dlgproc, 0
        invoke ExitProcess, 0
main endp
end main

Vo funkcii zistíme handle našej aplikácie a zobrazíme dialógové okno. Ak by bol dialóg skompilovaný do DLL, potom by bol vo funkcii GetModuleHandle miesto NULL názov DLL súboru. Funkcia DialogBoxParam vracia v registri RAX hodnotu, ktorú sme predtým zadali v EndDialog. Môžeme si teda z dialógu vracať nejakú hodnotu. Pokiaľ naopak potrebujeme odovzdať nejakú hodnotu smerom do dialógu, zadáme ju ako posledný parameter funkcie DialogBoxParam a potom ju budeme mať vo WM_INITDIALOG v parametri lParam.

Common controls - Manifest

Keď program spustíme, bude okno vyzerať ako v dávnych dobách vo Windows 95:

Programovanie v ASM pre Windows

Aby vyzeralo trochu modernejšie, musíme nový vzhľad povoliť v manifeste. Vo vlastnostiach projektu Linker -> Manifest File -> Additional Manifest Dependencies zadáme "type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'".

Ak použijeme pokročilejšie ovládacie prvky, musíme ich inicializovať. Za riadok include windows.h pridáme tieto dva riadky:

include commctrl.inc
includelib comctl32.lib

Na začiatok funkcie main pridáme riadky:

local ic:INITCOMMONCONTROLSEX
        mov ic.dwSize, sizeof INITCOMMONCONTROLSEX
        mov ic.dwICC, ICC_LISTVIEW_CLASSES or ICC_TREEVIEW_CLASSES or ICC_BAR_CLASSES
        invoke InitCommonControlsEx, addr ic

Inicializuje len to, čo budeme skutočne potrebovať. Celkový zoznam, čo všetko ide iniciovať, je nižšie:

  • ICC_LISTVIEW_CLASSES - zoznam položiek s viacerými stĺpci
  • ICC_TREEVIEW_CLASSES - stromové zobrazenie
  • ICC_BAR_CLASSES - panel s nástrojmi
  • ICC_TAB_CLASSES - záložky
  • ICC_UPDOWN_CLASS - šípky hore a dole u zadávanie čísel
  • ICC_PROGRESS_CLASS - ukazovateľ priebehu
  • ICC_HOTKEY_CLASS - klávesová skratka
  • ICC_ANIMATE_CLASS - animácie, AVI klip
  • ICC_DATE_CLASSES - dátum a čas
  • ICC_USEREX_CLASSES - výber z viac položiek s obrázkami
  • ICC_COOL_CLASSES - moderné panel s nástrojmi ako v MS Office

dlgproc bez .if

Na záver si ukážeme, ako by vyzerala dialógová procedúra bez použitia .if, čo je samozrejme len nadstavba prekladača nad inštrukciami:

dlgproc proc hWnd:HWND, msg:UINT, wParam:WPARAM, lParam:LPARAM
        mov hWnd,rcx
        cmp edx,WM_INITDIALOG
        jne @@1
        invoke CheckDlgButton, hWnd, IDC_REMEMBER, remember
        invoke SetDlgItemText, hWnd, IDC_NAME, addr name
        mov eax,TRUE
        jmp @@ret
@@1:    cmp edx,WM_COMMAND
        jne @@0
        cmp r8w,IDCANCEL
        je @@e
        cmp r8w,IDOK
        jne @@0
        invoke IsDlgButtonChecked, hWnd, IDC_REMEMBER
        mov remember,eax
        invoke GetDlgItemText, hWnd, IDC_NAME, addr name, sizeof name
        mov r8w,IDOK
@@e:    invoke EndDialog, hWnd, r8w
@@0:    mov eax,FALSE
@@ret:  ret
dlgproc endp

V prílohe máte aplikácii k stiahnutiu so zdrojovým kódom pre prípad, že by vám čokoľvek nešlo.


 

Mal si s čímkoľvek problém? Stiahni si vzorovú aplikáciu nižšie a porovnaj ju so svojím projektom, chybu tak ľahko nájdeš.

Stiahnuť

Stiahnutím nasledujúceho súboru súhlasíš s licenčnými podmienkami

Stiahnuté 10x (5.28 kB)
Aplikácia je vrátane zdrojových kódov v jazyku ASM

 

Všetky články v sekcii
Programovanie v ASM pre Windows
Článok pre vás napísal Petr Laštovička
Avatar
Užívateľské hodnotenie:
Ešte nikto nehodnotil, buď prvý!
Autor se věnuje vývoji webových aplikací v ASP.NET a aplikací pro Windows v C++ nebo C#.
Aktivity