NOVINKA - Online rekvalifikační kurz Java programátor. Oblíbená a studenty ověřená rekvalifikace - nyní i online.
NOVINKA – Víkendový online kurz Software tester, který tě posune dál. Zjisti, jak na to!

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).

Programování v ASM pro Windows

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.

Programování v ASM pro Windows

Dále zvolíme Dialog a klikneme na tlačítko New.

Programování v ASM pro Windows

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:

Programování v ASM pro Windows

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:

Programování v ASM pro Windows

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 sloupci
  • ICC_TREEVIEW_CLASSES - stromové zobrazení
  • ICC_BAR_CLASSES - panel nástrojů
  • ICC_TAB_CLASSES - záložky
  • ICC_UPDOWN_CLASS - šipky nahoru a dolů u zadávání čísel
  • ICC_PROGRESS_CLASS - ukazatel průběhu
  • ICC_HOTKEY_CLASS - klávesová zkratka
  • ICC_ANIMATE_CLASS - animace, AVI klip
  • ICC_DATE_CLASSES - datum a čas
  • ICC_USEREX_CLASSES - výběr z více položek s obrázky
  • ICC_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

 

Všechny články v sekci
Programování v ASM pro Windows
Článek pro vás napsal Petr Laštovička
Avatar
Uživatelské hodnocení:
Ještě nikdo nehodnotil, buď první!
Autor se věnuje vývoji webových aplikací v ASP.NET a aplikací pro Windows v C++ nebo C#.
Aktivity