платформа Win32 - Туториалы Iczelion'a на русском, адаптированные для FreeBasic. Урок 11 - Больше о диалоговых окнах

Предыдущая тема Следующая тема Перейти вниз

платформа Win32 - Туториалы Iczelion'a на русском, адаптированные для FreeBasic. Урок 11 - Больше о диалоговых окнах

Сообщение  electrik в Пн Июн 29, 2009 5:57 pm

Win32 API. Урок 11. Больше о диалоговых окнах

В этом туториале мы узнаем больше о диалоговых окнах. В частности, мы узнаем, как использовать диалоговые окна в качестве устройств ввода- вывода. Если вы читали предыдущий туториал, то этот будет для вас достаточно прост, так как небольшая модификация - все, что требуется для использования диалоговых окон как дополнение к основному окну. Также в этом туториале мы научимся тому, как использовать предопределенные диалоговые окна.

Теория:

Очень немногое будет сказано о том, как использовать диалоговые окна в качестве устройств ввода-вывода. Программа создает основное окно как обычно, и когда вы хотите отобразить диалоговое окно, просто-напросто вызовите CreateDialogparam или DialogBoxparam. Вызвав DialogBoxparam, вам не нужно делать что-либо еще, просто обработайте сообщения в процедуре диалогового окна. При использовании CreateDialogParam, вам будет нужно вставить вызов IsDialogMessage в цикле сообщений, чтобы позволить менеджеру диалогового окна обработать навигацию клавиатуры в вашем диалоговом окне за вас. Поскольку эти два случая тривиальны, я не привожу здесь исходный код.

Давайте перейдем к предопределенным диалоговым окнам, которые Windows предоставляет для использования вашими приложениями. Эти диалоговые окна существуют, чтобы обеспечить стандартизованный пользовательский  iнтерфейс. Существует файловое диалоговое окно, принтер, цвет, фонт и поисковое диалоговое окно. Вам следует использовать их так часто, как это возможно.

Вы создаете эти диалоговые окна вызовом соответствующих
функций из библиотеки предопределенных диалоговых окон. Для открытия файлового диалогового окна существует функция GetOpenFileName, для сохранения - GetSaveFileName, для диалогового окна принтера - PrintDlg и так далее. Каждая из этих функций берет указатель на структуру в качестве параметра. Вам следует посмотреть их в справочнике Win32 API. В этом туториале я продемонстрирую как создавать и использовать файловое диалоговое окно.

Ниже приведено описание функции GetOpenFileName.

function GetOpenFileName (byval as LPOPENFILENAME) as BOOL

Вы можете видеть, что она получает только один параметр, указатель на структуру OPENFILENAME. Возвращаемое значение TRUE показывает, что пользователь выбрал файл, который нужно открыть, FALSE означает обратное. Сейчас мы рассмотрим структуру OPENFILENAME:

type OPENFILENAME
lStructSize as DWORD
hwndOwner as HWND
hInstance as HINSTANCE
lpstrFilter as LPCSTR
lpstrCustomFilter as LPSTR
nMaxCustFilter as DWORD
nFilterIndex as DWORD
lpstrFile as LPSTR
nMaxFile as DWORD
lpstrFileTitle as LPSTR
nMaxFileTitle as DWORD
lpstrInitialDir as LPCSTR
lpstrTitle as LPCSTR
Flags as DWORD
nFileOffset as WORD
nFileExtension as WORD
lpstrDefExt as LPCSTR
lCustData as DWORD
lpfnHook as LPOFNHOOKPROC
lpTemplateName as LPCSTR
end type

Давайте рассмотрим значение часто используемых параметров.


lStructSize
размер структуры OPENFILENAME в байтах.
hwndOwner
Хэндл файлового диалогового окна.
hInstance
Хэндл процесса, который создает файловое диалоговое окно.
lpstrFilter
Строка-фильтр состоит из парных строк, разделенных null'ом. Первая строка в
каждой паре - это описание. Вторая строка - это шаблон фильтра. Например:
.lpstrFilter = @!"All Files, (*.*)\0*.*\0Bas Files, (*.BAS)\0*.bas\0\0" )
во второй строке каждой пары действительно используется для отфильтровки файлов. Также отметьте, что вам нужно добавить дополнительный 0 в конце фильтровых строк, чтобы указать конец.
Определите, какая пара фильтровых строк будет использоваться при первом отображении файлового диалогового окна. Индекс основывается на единице, то есть первая пара - 1, вторая - 2 и так далее. Поэтому в вышеприведенном экземпляре, если мы укажем nFilterIndex как 2, будет использован второй шаблон - "*.bas".
lpstrFile
Указатель на буфер, который содержит имя файла, используемого для инициализации edit control'а имени файла на диалоговом окне. Буфер должен быть длиной по крайней мере 260 байтов.
После того, как юзер выберет файл для открытия, имя файла с полным путем будет сохранено в этом буфере. Вы можете извлечь информацию из него позже.
nMaxFile
размер буфера.
lрstrTitle
Указатель на заголовок открытого файлового диалогового окна.
Flags
Определяет стили и характеристики диалогового окна.
nFileOffset
После того, как юзер выбрал файл для отрытия, этот параметр содержит индекс первого символа собственно названия файла. Например, если полное имя с путем
"c:\windows\system\lz32.dll", то этот параметр будет содержать значение 18.
nFileExtension
После того, как пользователь выберет файл для открытия, этот параметр содержит индекс первого символа расширения файла.

Пример:

Нижеприведенная программа отображает диалоговое окно открытия файла, когда пользователь выбирает пункт File->Open в меню. Когда пользователь выберет файл
в диалоговом окне, программа отобразит сообщение, содержащее полное имя, собственно имя файла и расширение выбранного файла.

файл fileopen.bas

Код:

' диалог открытия файла
#define WIN_INCLUDEALL
#include "windows.bi"
#include "fileopen.bi"
declare function WinMain ( byval hInst as HINSTANCE, _
byval hPrevInst as HINSTANCE, _
  byval szCmdLine as LPSTR, _
  byval iCmdShow as integer ) as integer

' начало программы
dim shared hModule as HINSTANCE
dim shared ofn as OPENFILENAME ' структура OPENFILENAME
dim shared as zString * MAXSIZE buffer' буфер для имен файлов
dim shared as zString * OUTPUTSIZE OutputString  ' результирующая строка
hModule =  GetModuleHandle( NULL )
end WinMain(hModule,NULL,GetCommandLine() , SW_SHOWNORMAL ) ' вызвать основную функцию
' здесь заканчивается программа

' процедура окна
function  WndProc _
(byval hwnd as HWND, _ ' хэндл окна
byval uMsg as UINT, _ ' сообщение
byval wParam as WPARAM, _ ' дополнительный  параметр сообщений
byval lParam as LPARAM) as LRESULT ' дополнительный параметр сообщений

function = 0
select case uMsg  'начинаем обработку сообщений
case WM_DESTROY ' если пользователь закрывает окно
PostQuitMessage(0) ' выходим из программы
exit function
case WM_COMMAND ' если получили сообщение WM_COMMAND
select case loword(wParam) ' читаем нижнее слово из wParam
case IDM_OPEN ' если выбрали в меню Open

' заполняем структуру OPENFILENAME
ofn.lStructSize = SIZEOF(OPENFILENAME) ' размер структуры OPENFILENAME
ofn.hwndOwner = hWnd ' Хэндл файлового диалогового окна
ofn.hInstance = hModule ' хэндл модуля

' настроим фильтр файлов, чтоб в типах файлов отображал только нужные нам расширения
ofn.lpstrFilter = _
@!"Text files, *.txt\0*.txt\0Bas files, *.bas\0*.bas\0All files, *.*\0*.*\0\0"
ofn.lpstrFile = @buffer ' указатель набуфер содержащий имя файла
ofn.nMaxFile = MAXSIZE ' размер буфера
ofn.Flags = OFN_FILEMUSTEXIST or _
OFN_PATHMUSTEXIST or OFN_LONGNAMES or _
OFN_EXPLORER or OFN_HIDEREADONLY ' стили и характеристики диалогового окна
ofn.lpstrTitle = @"-=Our First Open File Dialog Box=-: Choose the file to open"

' покажем диалог открытия файла
if GetOpenFileName(@ofn) = TRUE then' если выбрали файлы

' соберем все в одну строку функцией lstrcat
'первый параметр- указатель на результирующую строку,
' второй указатель на присоединяемую строку
lstrcat(@OutputString,"The Full Filename with Path is: ")
lstrcat(@OutputString,ofn.lpstrFile)
lstrcat(@OutputString,CrLf)
lstrcat(@OutputString,"The Filename is: ")
lstrcat(@OutputString,(ofn.lpstrFile + ofn.nFileOffset))
lstrcat(@OutputString,CrLf)
lstrcat(@OutputString,"The Extension is: ")
lstrcat(@OutputString,(ofn.lpstrFile + ofn.nFileExtension))

' отобразим OutputString в MessageBoxе
MessageBox(hWnd,@OutputString,"Result",MB_OK)

RtlZeroMemory(@OutputString,OUTPUTSIZE) ' очистим OutputString
end if
case IDM_EXIT
DestroyWindow(hWnd) ' разрушим окно
end select
end select
function = DefWindowProc(hWnd,uMsg,wParam,lParam) ' Дефаултная функция обработки окна
end function


'функция WinMain
function WinMain _
(byval hInst as HINSTANCE, _ ' хэндл программы
byval hPrevInst as HINSTANCE, _ 'в win32 всегда 0
byval szCmdLine as LPSTR, _  'указатель на командную строку
byval iCmdShow as integer ) as integer  ' состояние окна при первом появлении

dim wc as WNDCLASSEX ' структура параметров окна
dim wMsg as MSG  ' структура сообщений
dim hWnd as HWND ' хэндл окна

 'структура класса окна wc
with wc ' заполняем структуру wc
.cbSize = SIZEOF( WNDCLASSEX )  ' размер структуры WNDCLASSEX
.style = CS_HREDRAW or CS_VREDRAW  ' Стиль окна
.lpfnWndProc = @WndProc ' Адрес процедуры окна WndProc
.cbClsExtra = NULL  ' резервирование  дополнительных байт за концом структуры
.cbWndExtra = NULL
.hInstance = hInst  ' хэндл модуля
.hbrBackground = cast(HGDIOBJ, COLOR_WINDOW+1) ' Цвет фона
.lpszMenuName = @"FirstMenu" ' хэндл меню
.lpszClassName = @ClassName ' имя класса окна
.hIcon = LoadIcon( NULL,IDI_APPLICATION ) ' Хэндл иконки
.hIconSm = .hIcon 'Хэндл маленькой иконки
.hCursor = LoadCursor( NULL,IDC_ARROW) ' Хэндл курсора
end with

' регистрация нашего класса окна
if(RegisterClassEx(@wc) = FALSE) then
MessageBox(0,"Не могу зарегистрировать класс окна","Ошибка",0)
end 1
end if

' Создадим окно
hwnd = CreateWindowEx _
(WS_EX_CLIENTEDGE, _ ' дополнительные стили
ClassName, _ ' строка с именем класса окна
AppName, _ ' строка с именем окна
WS_OVERLAPPEDWINDOW, _ ' стиль окна
CW_USEDEFAULT, _ ' X
CW_USEDEFAULT, _ ' Y
CW_USEDEFAULT, _ ' ширина окна
CW_USEDEFAULT, _ ' высота окна
NULL, _ ' хэндл родительского окна
NULL, _ ' хэндл меню
hInst, _ ' хэндл модуля
NULL) ' указатель на структуру данных

ShowWindow( hwnd,iCmdShow) ' отобразить наше окно на десктопе
UpdateWindow( hwnd) ' обновить клиентскую область

while( GetMessage( @wMsg, NULL, 0, 0 ) <> FALSE )  'цикл сообщений
TranslateMessage( @wMsg )
DispatchMessage( @wMsg )
wend
function = wMsg.wParam
end function

файл fileopen.bi

Код:

#define ClassName "SimpleWinClass"
#define AppName "Our Main Window"
#define IDM_OPEN  1
#define IDM_EXIT  2
#define MAXSIZE  260
#define OUTPUTSIZE  512
#define CrLf chr(13) & chr(10) ' перевод строки

файл fileopen.rc

Код:

#include "fileopen.bi"
FirstMenu MENU
{
POPUP "&File"
{
MENUITEM "&Open",IDM_OPEN
MENUITEM "E&xit",IDM_EXIT
}
}

Анализ:

ofn.lStructSize = SIZEOF(OPENFILENAME)
ofn.hwndOwner = hWnd
ofn.hInstance = hModule

Мы заполняем в процедуре члены структуры ofn.

ofn.lpstrFilter = _
@!"Text files, *.txt\0*.txt\0Bas files, *.bas\0*.bas\0All files, *.*\0*.*\0\0"

Заметьте, что все пять строк заканчиваются нулем. Первая строка - это описание следующей строки. Первая строка является описанием первой. В качестве
фильтра мы можем определить все, что захотим. Мы должны добавить дополнительный ноль после последнего фильтра, чтобы указать конец. Не забудьте сделать это, иначе ваше диалоговое окно поведет себя весьма странно.

ofn.lpstrFile = @buffer
ofn.nMaxFile = MAXSIZE

Мы указываем, где диалоговое окно должно поместить имена файлов, выбранные пользователем. Учтите, что мы должны указать размер буфера в nMaxFile. Мы можем затем извлечь имя файла из этого буфера.

ofn.Flags = OFN_FILEMUSTEXIST or _
OFN_PATHMUSTEXIST or OFN_LONGNAMES or _
OFN_EXPLORER or OFN_HIDEREADONLY

Флаги определяют характеристики окна.

• OFN_FILEMUSTEXIST и OFN_PATHMUSTEXIST указывают то, что имя файла и путь, который пользователь набирает в edit control'е имени файла, должен существовать.
• OFN_LONGNAMES указывает диалоговому окну показывать длинные имена.
• OFN_EXPLORER указывает на то, что появление диалогового окна должно быть похоже на explorer.
• OFN_HIDEREADONLY прячет неизменяемый checkbox на диалоговом окне. Есть много других флагов, которые вы можете использовать. Проконсультируйтесь с вашим справочником по Win32 API.

ofn.lpstrTitle = @"-=Our First Open File Dialog Box=-: Choose the file to open"

Указываем имя диалогового окна.

if GetOpenFileName(@ofn) = TRUE then

Вызов функции GetOpenFileName. Передача указателя на структуру ofn в качестве параметров.
В тоже время, диалоговое окно открытия файла отображается на экране. Функция не будет возвращаться, пока пользователь не выберет файл или не нажмет кнопку 'Cancel' или закроет диалоговое окно.
Функция возвратит TRUE, если пользователь выбрал файл, в противном случае FALSE.

lstrcat(@OutputString,"The Full Filename with Path is: ")
lstrcat(@OutputString,ofn.lpstrFile)
lstrcat(@OutputString,CrLf)
lstrcat(@OutputString,"The Filename is: ")
lstrcat(@OutputString,(ofn.lpstrFile + ofn.nFileOffset))
lstrcat(@OutputString,CrLf)
lstrcat(@OutputString,"The Extension is: ")
lstrcat(@OutputString,(ofn.lpstrFile + ofn.nFileExtension))

В случае, если пользователь выбирает файл, мы подготавливаем строку вывода, которая будет отображаться в окне сообщения. Мы резервируем блок памяти в переменной OutputString и затем используем API-функцию, lstrcat, чтобы соединить обе строки. Чтобы разместить строку в несколько рядов, мы должны использовать символы переноса каретки.

MessageBox(hWnd,@OutputString,"Result",MB_OK)

Мы отображаем строку в окне сообщения.

RtlZeroMemory(@OutputString,OUTPUTSIZE)

Мы должны очистить OutputString перед тем, как заполнить его другой строкой. Поэтому мы используем для этого функцию RtlZeroMemory .

[C] Iczelion, пер. Aquila.

electrik

Сообщения : 391
Дата регистрации : 2008-09-02
Возраст : 37
Откуда : галактика Млечный путь, система Солнечная, планета Земля, страна россия, город Санкт Петербург

Посмотреть профиль

Вернуться к началу Перейти вниз

Предыдущая тема Следующая тема Вернуться к началу

- Похожие темы

 
Права доступа к этому форуму:
Вы не можете отвечать на сообщения