Lekce 1 - Dialogové okno Windows v assembleru
V dnešním ASM tutoriálu při tvorbě uživatelského rozhraní použijeme funkce Windows na vytváření dialogových oken.
Využívání nativních dialogových oken
Tato praktika má samozřejmě své výhody a nevýhody.
Výhody
- Používáme přímo součást operačního systému. Nemusíme instalovat žádné knihovny.
- Funguje to ve všech verzích Windows.
- Ve Visual Studiu je editor, ve kterém si můžeme dialogová okna jednoduše naklikat.
Nevýhody
- Vypadá to poněkud zastarale. V dnešní době jsou lidé zvyklí, že vše musí být materiální a ploché.
- Rozložení je statické. Pokud bychom chtěli dynamicky přidávat do formuláře další položky, museli bychom si sami počítat jejich souřadnice.
- Není možné dělat animace ani jiné speciální efekty.
Vytvoření resources
Formulář si definujeme nejprve jako tzv. resource. V moderních aplikacích se resources používají převážně pro obrázky a ikony. Pokud vytváříme uživatelské rozhraní pomocí Win32 API, pak do resoures ukládáme také menu, panely nástrojů, klávesové zkratky a dialogy. Cokoli si dáme do resources, bude vloženo do EXE souboru.
Ve Visual Studiu klikneme v Solution Exploreru nebo v menu Project na Add New Item. Pak v levém panelu klikneme na Resource a vpravo vybereme Resource File (.rc).
Když v Solution Exploreru dvakrát klikneme na nově přidaný
.rc
soubor, zobrazí se Resource View. V Resource
View klikneme pravým tlačítkem na .rc
soubor a zvolíme Add
Resource.
Dále zvolíme Dialog a klikneme na tlačítko New.
Objeví se editor dialogu a vlevo je toolbox se všemi možnými ovládacími prvky.
Zdrojový kód
Když se chceme podívat na zdrojový kód .rc
souboru, v
Solution Exploreru na něj klikneme pravým tlačítkem a zvolíme View
Code. V této lekci použijeme následující soubor
Resource.rc
. Můžete si ho odsud celý zkopírovat a nebo si ho
můžete zkusit sami naklikat ve Visual Studiu. Protože soubor vygenerovaný
Visual Studiem je poměrně dlouhý, zde uvedeme jen ty řádky, které jsou
nezbytné ke spuštění programu (zbytek souboru je případně ke stažení v
archivu pod lekcí):
#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 koresponduje s následujícím dialogovým oknem:
Použití resources v ASM
Visual Studio automaticky pro všechny položky generuje číselné
identifikátory a vkládá je do hlavičkového souboru
resource.h
:
#define IDD_LOGIN 102 #define IDC_REMEMBER 1001 #define IDC_NAME 1002
V assembleru nemůžeme použít přímo soubor resource.h
, ale
manuálně z něj musíme vytvořit resource.inc
, který bude
vypadat takto:
IDD_LOGIN equ 102 IDC_REMEMBER equ 1001 IDC_NAME equ 1002
Není vhodné používat názvy DIALOG1
,
CHECK1
, EDIT1
atd., ale je lepší pojmenovat si
ovládací prvky podle toho, co který ovládací prvek dělá.
Program v assembleru
Připravíme si soubor s ASM kódem:
option win64:2 include windows.inc include resource.inc .data remember dd FALSE name db "nějaké jméno", 100 dup(0) .code
Naše dialogové okno obsahuje jeden přepínač a jedno textové pole. V
sekci .data
jsou pro ně vytvořené globální proměnné.
Všimněte si, že za textem jsou vyhrazeny nulové bajty operátorem
dup
. To je kvůli tomu, že do proměnné pak zapíšeme text,
který zadal uživatel. Pokud uživatel zadá příliš dlouhý text, tak se
ořízne.
Kód
Přidejme další řádky reprezentující část s kódem ASM programu.
dlgproc
Prvně přidáme funkci pro obsluhu našeho 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ázev funkce si můžeme zvolit jaký chceme. V aplikaci často bývá více
oken, takže je rozumné si je správně pojmenovávat, abychom se v nich
vyznali. V prvním parametru hWnd
dostaneme handle našeho okna. Ve
Windows je veškerá komunikace mezi okny a systémem řešena pomocí zpráv. V
parametru msg
je typ zprávy, kterou máme obsloužit. Parametry
wParam
a lParam
závisejí na tom, o kterou zprávu se
jedná. V 64-bitové aplikaci se parametry předávají v registrech. Hned na
začátku si registr ECX
uložíme do proměnné hWnd
,
protože ho později budeme potřebovat. Dále jsme použili příkazy
.if
, .elseif
, .else
a
.endif
, které fungují podobně jako ve vyšších programovacích
jazycích a zvyšují čitelnost programu.
Ve WM_INITDIALOG
vyplníme počáteční hodnoty položek podle
hodnot z proměnných. Funkce CheckDlgButton
zaškrtne přepínač,
zatímco funkce SetDlgItemText
vyplní text. V registru
EAX
vracíme TRUE
, což znamená, že systém
automaticky aktivuje neboli nastaví focus na první položku dialogu.
Ve WM_COMMAND
se obsluhují tlačítka nebo jiné ovládací
prvky. Když uživatel stiskne tlačítko "OK", uložíme si zadané
hodnoty do proměnných a pak zavřeme okno funkcí EndDialog
.
Pokud uživatel stiskne tlačítko "Zrušit" nebo zavře okno, pak
také ukončíme dialog.
Pokud zprávu nezpracujeme, musíme v registru EAX
vrátit
FALSE
a systém zprávu zpracuje za nás a vykoná nějakou
výchozí akci.
main
A konečně dodáme i hlavní funkci main
:
main proc invoke GetModuleHandle, NULL invoke DialogBoxParam, rax, IDD_LOGIN, 0, addr dlgproc, 0 invoke ExitProcess, 0 main endp end main
Ve funkci zjistíme handle naší aplikace a zobrazíme dialogové okno.
Pokud by byl dialog zkompilován do DLL, pak by byl ve funkci
GetModuleHandle
místo NULL
název DLL souboru. Funkce
DialogBoxParam
vrací v registru RAX
hodnotu, kterou
jsme předtím zadali v EndDialog
. Můžeme si tedy z dialogu
vracet nějakou hodnotu. Pokud naopak potřebujeme předat nějakou hodnotu
směrem do dialogu, zadáme ji jako poslední parametr funkce
DialogBoxParam
a pak ji budeme mít ve WM_INITDIALOG
v
parametru lParam
.
Common controls - Manifest
Když program spustíme, bude okno vypadat jako v dávných dobách ve Windows 95:
Aby vypadalo trochu moderněji, musíme nový vzhled povolit v
manifestu. Ve vlastnostech 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='*'"
.
Pokud použijeme pokročilejší ovládací prvky, musíme je inicializovat.
Za řádek include windows.h
přidáme tyto dva řádky:
include commctrl.inc includelib comctl32.lib
Na začátek funkce main
přidáme řádky:
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
Inicializujeme jen to, co budeme skutečně potřebovat. Celkový seznam, co vše jde iniciovat, je níže:
ICC_LISTVIEW_CLASSES
- seznam položek s více sloupciICC_TREEVIEW_CLASSES
- stromové zobrazeníICC_BAR_CLASSES
- panel nástrojůICC_TAB_CLASSES
- záložkyICC_UPDOWN_CLASS
- šipky nahoru a dolů u zadávání číselICC_PROGRESS_CLASS
- ukazatel průběhuICC_HOTKEY_CLASS
- klávesová zkratkaICC_ANIMATE_CLASS
- animace, AVI klipICC_DATE_CLASSES
- datum a časICC_USEREX_CLASSES
- výběr z více položek s obrázkyICC_COOL_CLASSES
- moderní panel nástrojů jako v MS Office
dlgproc
bez .if
Na závěr si ukážeme, jak by vypadala dialogová procedura bez použití
.if
, což je samozřejmě jen nástavba překladače nad
instrukcemi:
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 příloze máte aplikaci ke stažení se zdrojovým kódem pro případ, že by vám cokoli nešlo.
Měl jsi s čímkoli problém? Stáhni si vzorovou aplikaci níže a porovnej ji se svým projektem, chybu tak snadno najdeš.
Stáhnout
Stažením následujícího souboru souhlasíš s licenčními podmínkami
Staženo 11x (5.28 kB)
Aplikace je včetně zdrojových kódů v jazyce ASM