![]() |
Wyjście Spis treści Poprzedni Następny
Autor:
©Iczelion |
©2008 mgr
Jerzy Wałaszek
|
Na tej lekcji nauczymy się nowych rzeczy na temat okien dialogowych. W szczególności przerobimy temat używania okien dialogowych w formie narzędzi wprowadzania i wyprowadzania informacji w naszych programach. Jeśli przestudiowałeś lekcję poprzednią, to ta będzie dla ciebie jak bułka z masłem, ponieważ wymagane są tylko kosmetyczne zmiany w kodzie, aby móc używać okna dialogowe jako dodatki do naszego okna głównego. Również lekcja ta obejmie stosowanie typowych okien dialogowych.

Pobierz przykłady okien dialogowych {z tego archiwum}
oraz {z tego archiwum}. Pobierz przykład Typowych
Okien Dialogowych {z tego archiwum}.
O użyciu okien dialogowych w charakterze narzędzi wprowadzania i wyprowadzania informacji nie musimy już wiele mówić. Twój program tworzy główne okno w zwykły sposób, a gdy chcesz wyświetlić okno dialogowe, po prostu wywołujesz funkcję CreateDialogParam lub DialogBoxParam. Przy wywołaniu DialogBoxParam nie musisz już nic więcej robić, tylko wystarczy obsługiwać wiadomości w procedurze okna dialogowego. Przy CreateDialogParam musisz wstawić do pętli wiadomości wywołanie IsDialogMessage w celu umożliwienia zarządcy okna dialogowego obsługi nawigacji z klawiatury wśród kontrolek na twoim oknie dialogowym.
Plik DIALOG.ASM wersja z
CreateDialogParam
.386
.MODEL FLAT, STDCALL
OPTION CASEMAP:NONE
INCLUDE \masm32\INCLUDE\windows.inc
INCLUDE \masm32\INCLUDE\user32.inc
INCLUDE \masm32\INCLUDE\kernel32.inc
INCLUDELIB \masm32\lib\user32.lib
INCLUDELIB \masm32\lib\kernel32.lib
WinMain PROTO :DWORD, :DWORD, :DWORD, :DWORD
DlgProc PROTO :HWND, :DWORD, :DWORD, :DWORD
.DATA
ClassName DB "SimpleWinClass", 0
AppName DB "Nasze okno główne", 0
MenuName DB "FirstMenu", 0
DlgName DB "MyDialog", 0
TestString DB "Cześć wszystkim", 0
hwndDlg DD 0 ; Uchwyt do okna dialogowego
.DATA?
hInstance HINSTANCE ?
CommandLine LPSTR ?
.CONST
IDM_EXIT EQU 1
IDM_ABOUT EQU 2
IDC_EDIT EQU 3000
IDC_BUTTON EQU 3001
IDC_EXIT EQU 3002
.CODE
start:
INVOKE GetModuleHandle, NULL
mov hInstance, eax
INVOKE GetCommandLine
mov CommandLine, eax
INVOKE WinMain, hInstance, NULL, CommandLine, SW_SHOWDEFAULT
INVOKE ExitProcess, eax
WinMain PROC hInst: HINSTANCE,\
hPrevInst: HINSTANCE,\
CmdLine: LPSTR,\
CmdShow: DWORD
LOCAL wc: WNDCLASSEX
LOCAL msg: MSG
LOCAL hwnd: HWND
mov wc.cbSize, SIZEOF WNDCLASSEX
mov wc.style, CS_HREDRAW OR CS_VREDRAW
mov wc.lpfnWndProc, OFFSET WndProc
mov wc.cbClsExtra, NULL
mov wc.cbWndExtra, NULL
push hInst
pop wc.hInstance
mov wc.hbrBackground, COLOR_WINDOW+1
mov wc.lpszMenuName, OFFSET MenuName
mov wc.lpszClassName, OFFSET ClassName
INVOKE LoadIcon, NULL, IDI_APPLICATION
mov wc.hIcon, eax
mov wc.hIconSm, eax
INVOKE LoadCursor, NULL, IDC_ARROW
mov wc.hCursor, eax
INVOKE RegisterClassEx, ADDR wc
INVOKE CreateWindowEx, WS_EX_CLIENTEDGE,\
ADDR ClassName, ADDR AppName,\
WS_OVERLAPPEDWINDOW, CW_USEDEFAULT,\
CW_USEDEFAULT, 300, 200, NULL, NULL,\
hInst, NULL
mov hwnd, eax
INVOKE ShowWindow, hwnd, SW_SHOWNORMAL
INVOKE UpdateWindow, hwnd
.WHILE TRUE
INVOKE GetMessage, ADDR msg, NULL, 0, 0
.BREAK .IF (!eax)
.IF hwndDlg!=0
INVOKE IsDialogMessage, hwndDlg, ADDR msg
.IF eax==TRUE
.CONTINUE
.ENDIF
.ENDIF
INVOKE TranslateMessage, ADDR msg
INVOKE DispatchMessage, ADDR msg
.ENDW
mov eax, msg.wParam
ret
WinMain ENDP
WndProc PROC hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM
.IF uMsg==WM_DESTROY
INVOKE PostQuitMessage, NULL
.ELSEIF uMsg==WM_COMMAND
.IF WORD PTR wParam==IDM_ABOUT
INVOKE CreateDialogParam, hInstance,\
ADDR DlgName, hWnd,\
OFFSET DlgProc, NULL
mov hwndDlg, eax
.ELSE
INVOKE DestroyWindow, hWnd
.ENDIF
.ELSE
INVOKE DefWindowProc, hWnd, uMsg, wParam, lParam
ret
.ENDIF
xor eax, eax
ret
WndProc ENDP
DlgProc PROC hWnd:HWND, iMsg:DWORD, wParam:WPARAM, lParam:LPARAM
.IF iMsg==WM_INITDIALOG
INVOKE GetDlgItem, hWnd, IDC_EDIT
INVOKE SetFocus, eax
.ELSEIF iMsg==WM_CLOSE
INVOKE EndDialog, hWnd, NULL
mov hwndDlg, 0
.ELSEIF iMsg==WM_COMMAND
mov ax, WORD PTR wParam
.IF WORD PTR wParam+2==BN_CLICKED
.IF ax==IDC_EXIT
INVOKE SendMessage, hWnd, WM_CLOSE, NULL, NULL
.ELSEIF ax==IDC_BUTTON
INVOKE SetDlgItemText, hWnd, IDC_EDIT, ADDR TestString
.ENDIF
.ENDIF
.ELSE
mov eax, FALSE
ret
.ENDIF
mov eax, TRUE
ret
DlgProc ENDP
END start
Plik DIALOG.RC
// stałe dla okna dialogowego
#define IDC_EDIT 3000
#define IDC_BUTTON 3001
#define IDC_EXIT 3002
#define DS_CENTER 0x0800L
#define DS_CENTER 0x0800L
#define WS_MINIMIZEBOX 0x00020000L
#define WS_SYSMENU 0x00080000L
#define WS_VISIBLE 0x10000000L
#define WS_OVERLAPPED 0x00000000L
#define DS_MODALFRAME 0x80L
#define DS_3DLOOK 0x0004L
#define WS_CAPTION 0xC00000L
#define ES_AUTOHSCROLL 0x80L
#define ES_LEFT 0
// stałe dla menu
#define IDM_EXIT 1
#define IDM_ABOUT 2
FirstMenu MENU
{
POPUP "&Plik"
{
MENUITEM "&Koniec", IDM_EXIT
}
MENUITEM "O programie", IDM_ABOUT
}
MyDialog DIALOG 10, 10, 205, 60
STYLE 0x0004 | DS_CENTER | WS_CAPTION | WS_MINIMIZEBOX |
WS_SYSMENU | WS_VISIBLE | WS_OVERLAPPED | DS_MODALFRAME |
DS_3DLOOK
CAPTION "Nasze drugie okno dialogowe"
{
EDITTEXT IDC_EDIT, 15, 17, 111, 13, ES_AUTOHSCROLL | ES_LEFT
DEFPUSHBUTTON "Cześć", IDC_BUTTON, 141, 10, 52, 13
PUSHBUTTON "&Koniec", IDC_EXIT, 141, 26, 52, 13
}
Plik DIALOG.ASM wersja z DialogBoxParam
.386
.MODEL FLAT, STDCALL
OPTION CASEMAP:NONE
INCLUDE \masm32\include\windows.inc
INCLUDE \masm32\include\user32.inc
INCLUDE \masm32\include\kernel32.inc
INCLUDELIB \masm32\lib\user32.lib
INCLUDELIB \masm32\lib\kernel32.lib
WinMain PROTO :DWORD, :DWORD, :DWORD, :DWORD
DlgProc PROTO :HWND, :DWORD, :DWORD, :DWORD
.DATA
ClassName DB "SimpleWinClass",0
AppName DB "Nasze okno główne",0
MenuName DB "FirstMenu",0
DlgName DB "MyDialog",0
TestString DB "Cześć wszystkim",0
.DATA?
hInstance HINSTANCE ?
CommandLine LPSTR ?
.CONST
IDM_EXIT EQU 1
IDM_ABOUT EQU 2
IDC_EDIT EQU 3000
IDC_BUTTON EQU 3001
IDC_EXIT EQU 3002
.CODE
start:
INVOKE GetModuleHandle, NULL
mov hInstance, eax
INVOKE GetCommandLine
mov CommandLine, eax
INVOKE WinMain, hInstance, NULL, CommandLine, SW_SHOWDEFAULT
INVOKE ExitProcess, eax
WinMain PROC hInst: HINSTANCE,\
hPrevInst: HINSTANCE,\
CmdLine: LPSTR,\
CmdShow: DWORD
LOCAL wc: WNDCLASSEX
LOCAL msg: MSG
LOCAL hwnd: HWND
mov wc.cbSize, SIZEOF WNDCLASSEX
mov wc.style, CS_HREDRAW OR CS_VREDRAW
mov wc.lpfnWndProc, OFFSET WndProc
mov wc.cbClsExtra, NULL
mov wc.cbWndExtra, NULL
push hInst
pop wc.hInstance
mov wc.hbrBackground, COLOR_WINDOW+1
mov wc.lpszMenuName, OFFSET MenuName
mov wc.lpszClassName, OFFSET ClassName
INVOKE LoadIcon, NULL, IDI_APPLICATION
mov wc.hIcon, eax
mov wc.hIconSm, eax
INVOKE LoadCursor, NULL, IDC_ARROW
mov wc.hCursor, eax
INVOKE RegisterClassEx, ADDR wc
INVOKE CreateWindowEx, WS_EX_CLIENTEDGE,\
ADDR ClassName, ADDR AppName,\
WS_OVERLAPPEDWINDOW, CW_USEDEFAULT,\
CW_USEDEFAULT, 300, 200, NULL, NULL,\
hInst, NULL
mov hwnd, eax
INVOKE ShowWindow, hwnd, SW_SHOWNORMAL
INVOKE UpdateWindow, hwnd
.WHILE TRUE
INVOKE GetMessage, ADDR msg, NULL, 0, 0
.BREAK .IF (!eax)
INVOKE TranslateMessage, ADDR msg
INVOKE DispatchMessage, ADDR msg
.ENDW
mov eax, msg.wParam
ret
WinMain ENDP
WndProc PROC hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM
.IF uMsg==WM_DESTROY
INVOKE PostQuitMessage, NULL
.ELSEIF uMsg==WM_COMMAND
.IF WORD PTR wParam==IDM_ABOUT
INVOKE DialogBoxParam, hInstance,\
ADDR DlgName, hWnd,\
OFFSET DlgProc, NULL
.ELSE
INVOKE DestroyWindow, hWnd
.ENDIF
.ELSE
INVOKE DefWindowProc, hWnd, uMsg, wParam, lParam
ret
.ENDIF
xor eax, eax
ret
WndProc ENDP
DlgProc PROC hWnd:HWND, iMsg:DWORD, wParam:WPARAM, lParam:LPARAM
.IF iMsg==WM_INITDIALOG
INVOKE GetDlgItem, hWnd, IDC_EDIT
INVOKE SetFocus, eax
.ELSEIF iMsg==WM_CLOSE
INVOKE EndDialog, hWnd, NULL
.ELSEIF iMsg==WM_COMMAND
mov ax, WORD PTR wParam
.IF WORD PTR wParam+2==BN_CLICKED
.IF ax==IDC_EXIT
INVOKE SendMessage, hWnd, WM_CLOSE, NULL, NULL
.ELSEIF ax==IDC_BUTTON
INVOKE SetDlgItemText, hWnd, IDC_EDIT, ADDR TestString
.ENDIF
.ENDIF
.ELSE
mov eax, FALSE
ret
.ENDIF
mov eax, TRUE
ret
DlgProc ENDP
END start
Przejdźmy do typowych okien dialogowych. System Windows przygotował predefiniowane okna dialogowe do użytku przez twoje aplikacje. Istnieją one w celu zapewnienia standartowego interfejsu użytkownika. Składają się z okienek dialogowych pliku, drukowania, koloru, czcionki i wyszukiwania. Powinieneś z nich zawsze korzystać. Zawarte są one w bibliotece comdlg32.dll. Aby ich użyć, musisz dołączyć do swojej aplikacji bibliotekę exportu comdlg32.lib. Tworzysz te okna dialogowe poprzez wywołanie odpowiednich funkcji z biblioteki. Dla okienka dialogowego otwarcia pliku będzie to funkcja GetOpenFileName, dla okienka dialogowego zapisu jest to GetSaveFileName, okienko dialogowe wydruku to PrintDlg i tak dalej. Każda z tych funkcji przyjmuje jako parametr wskazanie pewnej struktury, której dokładny opis znajdziesz w plikach pomocy dla API biblioteki Win32. Na tej lekcji zademonstruję, jak utworzyć i zastosować okno dialogowe odczytu pliku z dysku.

Poniżej mamy prototyp funkcji GetOpenFileName:
GetOpenFileName PROTO lpofn:DWORD
Jak widać funkcja ta otrzymuje tylko jeden parametr, wskazanie do struktury
OPENFILENAME. Wartość zwrotna
TRUE oznacza, iż użytkownik wybrał plik do
otwarcia, a FALSE oznacza przypadek odwrotny. Przyjrzyjmy
się następnie strukturze OPENFILENAME.
OPENFILENAME STRUCT
lStructSize DWORD ?
hwndOwner HWND ?
hInstance HINSTANCE ?
lpstrFilter LPCSTR ?
lpstrCustomFilter LPSTR ?
nMaxCustFilter DWORD ?
nFilterIndex DWORD ?
lpstrFile LPSTR ?
nMaxFile DWORD ?
lpstrFileTitle LPSTR ?
nMaxFileTitle DWORD ?
lpstrInitialDir LPCSTR ?
lpstrTitle LPCSTR ?
Flags DWORD ?
nFileOffset WORD ?
nFileExtension WORD ?
lpstrDefExt LPCSTR ?
lCustData LPARAM ?
lpfnHook DWORD ?
lpTemplateName LPCSTR ?
OPENFILENAME ENDS
Zobaczmy na znaczenie często używanych pól tej struktury:
FilterString DB "Wszystkie pliki (*.*)", 0, "*.*", 0
DB "Pliki tekstowe (*.txt)", 0,"*.txt", 0, 0
Zauważ, iż tylko szablon w drugim tekście każdej pary jest w rzeczywistości
wykorzystywany przez system Windows do filtrowania
plików. Również zauważ, iż na końcu łańcuchów filtrów musisz dodać dodatkowe
zero, aby zaznaczyć koniec tej listy filtrów.
Poniższy program wyświetla okna dialogowe otwierania pliku, gdy użytkownik wybierze opcję menu Plik ® Otwórz. Gdy w oknie dialogowym użytkownik wybierze jakiś plik, program wyświetli okno wiadomości z pełną nazwą, nazwą oraz z rozszerzeniem wybranego pliku.
Plik OPEN.ASM
.386
.MODEL FLAT, STDCALL
OPTION CASEMAP:NONE
WinMain PROTO :DWORD, :DWORD, :DWORD, :DWORD
INCLUDE \masm32\include\windows.inc
INCLUDE \masm32\include\user32.inc
INCLUDE \masm32\include\kernel32.inc
INCLUDE \masm32\include\comdlg32.inc
INCLUDELIB \masm32\lib\user32.lib
INCLUDELIB \masm32\lib\kernel32.lib
INCLUDELIB \masm32\lib\comdlg32.lib
.CONST
IDM_OPEN EQU 1
IDM_EXIT EQU 2
MAXSIZE EQU 260
OUTPUTSIZE EQU 512
.DATA
ClassName DB "SimpleWinClass",0
AppName DB "Nasze okno główne",0
MenuName DB "FirstMenu",0
ofn OPENFILENAME <>
FilterString DB "Wszystkie pliki (*.*)",0,"*.*",0
DB "Pliki tekstowe (*.txt)",0,"*.txt",0,0
buffer DB MAXSIZE DUP(0)
OurTitle DB "Okno dialogowe otwarcia pliku: wybierz plik",0
FullPathName DB "Pełna nazwa pliku ze ścieżką to: ",0
FullName DB "Nazwa pliku to: ",0
ExtensionName DB "Rozszerzenie nazwy to: ",0
OutputString DB OUTPUTSIZE DUP(0)
CrLf DB 0Dh,0Ah,0 ;znaki końca wiersza i powrotu karetki
.DATA?
hInstance HINSTANCE ?
CommandLine LPSTR ?
.CODE
start:
INVOKE GetModuleHandle, NULL
mov hInstance, eax
INVOKE GetCommandLine
mov CommandLine, eax
INVOKE WinMain, hInstance, NULL, CommandLine, SW_SHOWDEFAULT
INVOKE ExitProcess, eax
WinMain PROC hInst: HINSTANCE,\
hPrevInst: HINSTANCE,\
CmdLine: LPSTR,\
CmdShow: DWORD
LOCAL wc: WNDCLASSEX
LOCAL msg: MSG
LOCAL hwnd: HWND
mov wc.cbSize, SIZEOF WNDCLASSEX
mov wc.style, CS_HREDRAW OR CS_VREDRAW
mov wc.lpfnWndProc, OFFSET WndProc
mov wc.cbClsExtra, NULL
mov wc.cbWndExtra, NULL
push hInst
pop wc.hInstance
mov wc.hbrBackground, COLOR_WINDOW+1
mov wc.lpszMenuName, OFFSET MenuName
mov wc.lpszClassName, OFFSET ClassName
INVOKE LoadIcon, NULL, IDI_APPLICATION
mov wc.hIcon, eax
mov wc.hIconSm, eax
INVOKE LoadCursor, NULL, IDC_ARROW
mov wc.hCursor, eax
INVOKE RegisterClassEx, ADDR wc
INVOKE CreateWindowEx, WS_EX_CLIENTEDGE,\
ADDR ClassName, ADDR AppName,\
WS_OVERLAPPEDWINDOW, CW_USEDEFAULT,\
CW_USEDEFAULT, 300, 200, NULL, NULL,\
hInst, NULL
mov hwnd, eax
INVOKE ShowWindow, hwnd, SW_SHOWNORMAL
INVOKE UpdateWindow, hwnd
.WHILE TRUE
INVOKE GetMessage, ADDR msg, NULL, 0, 0
.BREAK .IF (!eax)
INVOKE TranslateMessage, ADDR msg
INVOKE DispatchMessage, ADDR msg
.ENDW
mov eax, msg.wParam
ret
WinMain ENDP
WndProc PROC hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM
.IF uMsg==WM_DESTROY
INVOKE PostQuitMessage, NULL
.ELSEIF uMsg==WM_COMMAND
mov eax, wParam
.IF ax==IDM_OPEN
mov ofn.lStructSize, SIZEOF ofn
push hWnd
pop ofn.hWndOwner
push hInstance
pop ofn.hInstance
mov ofn.lpstrFilter, OFFSET FilterString
mov ofn.lpstrFile, OFFSET buffer
mov ofn.nMaxFile, MAXSIZE
mov ofn.Flags, OFN_FILEMUSTEXIST OR OFN_PATHMUSTEXIST OR \
OFN_LONGNAMES OR OFN_EXPLORER OR \
OFN_HIDEREADONLY
mov ofn.lpstrTitle, OFFSET OurTitle
INVOKE GetOpenFileName, ADDR ofn
.IF eax==TRUE
INVOKE lstrcat, ADDR OutputString, ADDR FullPathName
INVOKE lstrcat, ADDR OutputString, ofn.lpstrFile
INVOKE lstrcat, ADDR OutputString, ADDR CrLf
INVOKE lstrcat, ADDR OutputString, ADDR FullName
mov eax, ofn.lpstrFile
xor edx, edx
mov dx, ofn.nFileOffset
add eax, edx
INVOKE lstrcat, ADDR OutputString, eax
INVOKE lstrcat, ADDR OutputString, ADDR CrLf
INVOKE lstrcat, ADDR OutputString, ADDR ExtensionName
mov eax, ofn.lpstrFile
xor edx, edx
mov dx, ofn.nFileExtension
add eax, edx
INVOKE lstrcat, ADDR OutputString, eax
INVOKE MessageBox, hWnd,\
ADDR OutputString,\
ADDR AppName, MB_OK
INVOKE RtlZeroMemory, ADDR OutputString, OUTPUTSIZE
.ENDIF
.ELSE
INVOKE DestroyWindow, hWnd
.ENDIF
.ELSE
INVOKE DefWindowProc, hWnd, uMsg, wParam, lParam
ret
.ENDIF
xor eax, eax
ret
WndProc ENDP
END start
Plik OPEN.RC
// Stałe dla menu
#define IDM_OPEN 1
#define IDM_EXIT 2
FirstMenu MENU
{
POPUP "&Plik"
{
MENUITEM "&Otwórz",IDM_OPEN
MENUITEM SEPARATOR
MENUITEM "&Koniec",IDM_EXIT
}
}
mov ofn.lStructSize, SIZEOF ofn
push hWnd
pop ofn.hWndOwner
push hInstance
pop ofn.hInstance
Wypełniamy rutynowe pola struktury ofn.
mov ofn.lpstrFilter, OFFSET FilterString
Zmienna FilterString jest filtrem nazw plików, który
określamy w sposób następujący:
FilterString DB "Wszystkie pliki (*.*)",0,"*.*",0
DB "Pliki tekstowe (*.txt)",0,"*.txt",0,0
Zwróć uwagę, iż wszystkie cztery łańcuchy tekstowe kończą się zerem. Pierwszy
tekst opisuje filtr zawarty w drugim tekście. Właściwe szablony to "*.*" oraz
"*.txt". Nic nie stoi na przeszkodzie, aby tutaj określić dowolny szablon. Po
ostatnim szablonie
MUSIMY umieścić dodatkowe zero, aby oznaczyć koniec
listy filtrów. Nie zapominaj o tej drobnostce, albo twoje okno dialogowe będzie
się dziwnie zachowywało.
mov ofn.lpstrFile, OFFSET buffer
mov ofn.nMaxFile, MAXSIZE
Określamy, gdzie okno dialogowe ma umieścić nazwę pliku wybranego przez
użytkownika. Zwróć uwagę, iż w polu nMaxFile
musimy podać maksymalny rozmiar przeznaczonego na nazwę bufora. Później z
bufora możemy wydobyć nazwę.
mov ofn.Flags, OFN_FILEMUSTEXIST OR OFN_PATHMUSTEXIST OR \
OFN_LONGNAMES OR OFN_EXPLORER OR \
OFN_HIDEREADONLY
Znaczniki określają charakterystykę tego okna dialogowego.
Istnieje o wiele więcej znaczników, które możesz wykorzystać. Jak zwykle zaglądnij do plików pomocy dla API biblioteki Win32.
mov ofn.lpstrTitle, OFFSET OurTitle
Określamy tytuł okna dialogowego.
INVOKE GetOpenFileName, ADDR ofn
Wywołujemy funkcję GetOpenFileName
przekazując wskazanie do struktury ofn jako
parametr.
W tym momencie na ekranie zostaje wyświetlone okno dialogowe otwierania pliku. Funkcja nie zwróci sterowania dopóki użytkownik nie wybierze jakiegoś pliku do otwarcia, nie kliknie przycisku Anuluj lub nie zamknie tego okna dialogowego. W rejestrze eax zostanie zwrócona wartość TRUE, jeśli użytkownik wybierze jakiś plik do otwarcia. W przeciwnym przypadku rejestr eax będzie zawierał wartość FALSE.
.IF eax==TRUE
INVOKE lstrcat, ADDR OutputString, ADDR FullPathName
INVOKE lstrcat, ADDR OutputString, ofn.lpstrFile
INVOKE lstrcat, ADDR OutputString, ADDR CrLf
INVOKE lstrcat, ADDR OutputString, ADDR FullName
W przypadku, gdy użytkownik dokona wyboru jakiegoś pliku do otwarcia, przygotowujemy tekst wyjściowy do wyświetlenia w okienku wiadomości. Rezerwujemy odpowiedni blok pamięci w zmiennej OutputString, a następnie stosujemy funkcję API lstrcat do połączenia ze sobą kilku tekstów. Aby teksty te znalazły się w osobnych wierszach, musimy każdy z nich rozdzielić parą znaków CR i LF.
mov eax, ofn.lpstrFile
xor edx, edx
mov dx, ofn.nFileOffset
add eax, edx
INVOKE lstrcat, ADDR OutputString, eax
Powyższe wiersze wymagają nieco wyjaśnienia. Pole nFileOffset
zawiera indeks w buforze ofn.lpstrFile. Jednakże nie
możemy ich po prostu dodać do siebie bezpośrednio, ponieważ
nFileOffset ma rozmiar WORD (16
bitów), a lpstrFile jest wskazaniem o
rozmiarze DWORD (32 bity).
Dlatego pobieramy ten indeks do młodszego słowa rejestru edx
i dodajemy do wartości lpstrFile.
INVOKE MessageBox, hWnd, ADDR OutputString, ADDR AppName, MB_OK
Wyświetlamy tekst w oknie wiadomości.
INVOKE RtlZeroMemory, ADDR OutputString, OUTPUTSIZE
Musimy wyczyścić bufor OutputString przed
wstawieniem do niego nowego tekstu, więc stosujemy do tego celu funkcję
RtlZeroMemory
Ta sama aplikacja w Pascalu. Program używa tego samego pliku zasobów, co wersja asemblerowa. Powinieneś go umieścić w katalogu projektu pod nazwą RSRC.RC.
Wersja z CreateDialogParam:
{********************************
** I Liceum Ogólnokształcące **
** w Tarnowie **
** mgr Jerzy Wałaszek **
********************************}
program MoreDialog1;
uses Windows;
const
ClassName = 'SimpleWinClass';
AppName = 'Nasze okno główne';
MenuName = 'FirstMenu';
DlgName = 'MyDialog';
TestString = 'Cześć wszystkim';
IDM_EXIT = 1;
IDM_ABOUT = 2;
IDC_EDIT = 3000;
IDC_BUTTON = 3001;
IDC_EXIT = 3002;
var
hwnddlg : HWND; //uchwyt do okna dialogowego
hInstance : HInst; //uchwyt egzemplarza aplikacji
function DlgProc(hWnd:HWND;iMsg:DWORD;wParam:WPARAM;lParam:LPARAM) : longint;
begin
DlgProc := longint(true);
case iMsg of
WM_INITDIALOG : SetFocus(GetDlgItem(hWnd,IDC_EDIT));
WM_CLOSE : begin
EndDialog(hWnd,0);
hwndDlg := 0;
end;
WM_COMMAND : if (wParam shr 16) = BN_CLICKED then
case (wParam and $ffff) of
IDC_EXIT : SendMessage(hWnd,WM_CLOSE,0,0);
IDC_BUTTON : SetDlgItemText(hWnd,IDC_EDIT,TestString);
end;
else DlgProc := longint(false);
end;
end;
function WndProc(hWnd:HWND;uMsg:UINT;wParam:WPARAM;lParam:LPARAM) : longint;
begin
WndProc := 0;
case uMsg of
WM_DESTROY: PostQuitMessage(0);
WM_COMMAND: if (wParam and $ffff) = IDM_ABOUT then
hwndDlg := CreateDialogParam(hInstance,DlgName,hWnd,@DlgProc,0)
else DestroyWindow(hWnd);
else WndProc := DefWindowProc(hWnd,uMsg,wParam,lParam);
end;
end;
function WinMain(hInst,hPrevInst:HINST;CmdLine:LPSTR;CmdShow:longint) : longint;
var
wc : WNDCLASSEX;
msg : MSG;
hwnd : HWND;
begin
wc.cbSize := sizeof(WNDCLASSEX);
wc.style := CS_HREDRAW or CS_VREDRAW;
wc.lpfnWndProc := @WndProc;
wc.cbClsExtra := 0;
wc.cbWndExtra := 0;
wc.hInstance := hInst;
wc.hbrBackground := COLOR_WINDOW + 1;
wc.lpszMenuName := MenuName;
wc.lpszClassName := ClassName;
wc.hIcon := LoadIcon(0,IDI_APPLICATION);
wc.hIconSm := wc.hIcon;
wc.hCursor := LoadCursor(0,IDC_ARROW);
RegisterClassEx(wc);
hwnd := CreateWindowEx(WS_EX_CLIENTEDGE,ClassName,AppName,
WS_OVERLAPPEDWINDOW,CW_USEDEFAULT,
CW_USEDEFAULT,300,200,0,0,hInst,0);
ShowWindow(hwnd,SW_SHOWNORMAL);
UpdateWindow(hwnd);
while GetMessage(msg,0,0,0) do
begin
if (hwndDlg <> 0) and IsDialogMessage(hwndDlg,msg) then continue;
TranslateMessage(msg);
DispatchMessage(msg);
end;
WinMain := msg.wParam;
end;
begin
hInstance := GetModuleHandle(0);
ExitProcess(WinMain(hInstance,0,GetCommandLine,SW_SHOWDEFAULT));
end.
Program z wspólnym oknem dialogowym otwarcia pliku. Plik zasobów z wersji asemblerowej proszę umieścić w katalogu projektowym pod nazwą RSRC.RC.
{********************************
** I Liceum Ogólnokształcące **
** w Tarnowie **
** mgr Jerzy Wałaszek **
********************************}
program OpenDialog;
uses Windows;
const
IDM_OPEN = 1;
IDM_EXIT = 2;
MAXSIZE = 260;
OUTPUTSIZE = 512;
ClassName = 'SimpleWinClass';
AppName = 'Nasze okno główne';
MenuName = 'FirstMenu';
FilterString = 'Wszystkie pliki (*.*)'#0'*.*'#0 +
'Pliki tekstowe (*.txt)'#0'*.txt'#0#0;
OurTitle = 'Okno dialogowe otwarcia pliku: wybierz plik';
FullPathName = 'Pełna nazwa pliku ze ścieżką to: ';
FullName = 'Nazwa pliku to: ';
ExtensionName = 'Rozszerzenie nazwy to: ';
CrLf = #13#10#0; //znaki końca wiersza i powrotu karetki
var
ofn : OPENFILENAME;
buffer : array[0..MAXSIZE] of char;
OutputString : array[0..OUTPUTSIZE] of char;
hInstance : HINST;
function WndProc(hWnd:HWND;uMsg:UINT;wParam:WPARAM;lParam:LPARAM) : longint;
begin
WndProc := 0;
case uMsg of
WM_DESTROY : PostQuitMessage(0);
WM_COMMAND : if (wParam and $ffff) = IDM_OPEN then
begin
ofn.lStructSize := sizeof(ofn);
ofn.hWndOwner := hWnd;
ofn.hInstance := hInstance;
ofn.lpstrFilter := FilterString;
ofn.lpstrFile := @buffer;
ofn.nMaxFile := MAXSIZE;
ofn.Flags := OFN_FILEMUSTEXIST or
OFN_PATHMUSTEXIST or
OFN_LONGNAMES or
OFN_EXPLORER or
OFN_HIDEREADONLY;
ofn.lpstrTitle := OurTitle;
if GetOpenFileName(@ofn) then
begin
lstrcat(@OutputString,FullPathName);
lstrcat(@OutputString,ofn.lpstrFile);
lstrcat(@OutputString,CrLf);
lstrcat(@OutputString,FullName);
lstrcat(@OutputString,ofn.lpstrFile+ofn.nFileOffset);
lstrcat(@OutputString,CrLf);
lstrcat(@OutputString,ExtensionName);
lstrcat(@OutputString,ofn.lpstrFile+ofn.nFileExtension);
MessageBox(hWnd,@OutputString,AppName,MB_OK);
FillChar(OutputString,OUTPUTSIZE,0);
end;
end
else DestroyWindow(hWnd);
else WndProc := DefWindowProc(hWnd,uMsg,wParam,lParam);
end;
end;
function WinMain(hInst,hPrevInst:HINST;CmdLine:LPSTR;CmdShow:longint) : longint;
var
wc : WNDCLASSEX;
msg : MSG;
hwnd : HWND;
begin
wc.cbSize := sizeof(WNDCLASSEX);
wc.style := CS_HREDRAW or CS_VREDRAW;
wc.lpfnWndProc := @WndProc;
wc.cbClsExtra := 0;
wc.cbWndExtra := 0;
wc.hInstance := hInst;
wc.hbrBackground := COLOR_WINDOW + 1;
wc.lpszMenuName := MenuName;
wc.lpszClassName := ClassName;
wc.hIcon := LoadIcon(0,IDI_APPLICATION);
wc.hIconSm := wc.hIcon;
wc.hCursor := LoadCursor(0,IDC_ARROW);
RegisterClassEx(wc);
hwnd := CreateWindowEx(WS_EX_CLIENTEDGE,ClassName,AppName,
WS_OVERLAPPEDWINDOW,CW_USEDEFAULT,
CW_USEDEFAULT,300,200,0,0,hInst,0);
ShowWindow(hwnd,SW_SHOWNORMAL);
UpdateWindow(hwnd);
while GetMessage(msg,0,0,0) do
begin
TranslateMessage(msg);
DispatchMessage(msg);
end;
WinMain := msg.wParam;
end;
begin
hInstance := GetModuleHandle(0);
ExitProcess(WinMain(hInstance,0,GetCommandLine,SW_SHOWDEFAULT));
end.
|
Autorem
kursu jest
Iczelion. Kurs
programowania Windows znalazł się na serwerze I LO w Tarnowie za pisemną
zgodą autora. |
![]() | I Liceum Ogólnokształcące |
Pytania proszę przesyłać na adres email: i-lo@eduinf.waw.pl
W artykułach serwisu są używane cookies. Jeśli nie chcesz ich otrzymywać,
zablokuj je w swojej przeglądarce.
Informacje dodatkowe