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