FreeBASIC в России

   

 Главная   Исходники   Русскоязычный форум   Полезные файлы   Пользователи   Поиск

 

 FB Wiki   Уроки   Скачать FreeBASIC   Проекты   Ссылки   Загрузить   Каталог ссылок

 
 

 Замечания и предложения по работе сайта оставляйте здесь.

Сейчас на сайте:

Вы вошли как: Guest   Регистрация   

Логин:     Пароль:     

Создай бесплатно WebMoney кошелёк на своём мобильном всего за 5 минут

 

Делаем dll своими руками

Хэндл окна

Графические средства языка

Точка пересечения отрезков

Окна без рамки

Физика поведения ядра

Win32 API Введение

►Урок 1 Win32 API

►Урок 2 Win32 API

►Урок 3 Win32 API

►Урок 4 Win32 API

►Урок 5 Win32 API

►Урок 6 Win32 API

►Урок 7 Win32 API

►Урок 8 Win32 API

►Урок 9 Win32 API

►Урок 10 Win32 API

►Урок 11 Win32 API

►Урок 12 Win32 API

►Урок 13 Win32 API

►Урок 14 Win32 API

►Урок 15 Win32 API

►Урок 16 Win32 API

►Урок 17 Win32 API

►Урок 18 Win32 API

►Урок 19 Win32 API

►Урок 20 Win32 API

►Урок 21 Win32 API

►Урок 22 Win32 API

►Урок 23 Win32 API

►Урок 24 Win32 API

Ассоциация файлов

Определить OS

Выводит имя компьютера

 

 

 

Win32 API. Урок 10. Диалоговое окно как основное.

Опытом поделился и оптимизировал под FreeBASIC:   15.01.2011

 

 

Реклама:

доступный кредит в вашем городе;Курсы наращивания ресниц в Москве , f830. Курсы наращивания ресниц в Москве - репутация.

 

Теперь время для действительно интересной темы, относящейся к GUI, о диалоговом окне. В этом туториале (и в следующем) мы научимся как использовать диалоговое окно в качестве основного.


Теория:

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

Причина того, почему возникают подобные неудобства состоят в том, что дочерние окна изначально проектировались для работы с диалоговым окном, а не с обычным.
Цвет дочернего окна по умолчанию серый, так как это обычный цвет диалогового окна.

Прежде чем мы углубимся в детали, мы должны сначала узнать, что такое диалоговое окно. Диалоговое окно - это не что иное, как обычное окно, которое спроектировано для работы с дочерними элементами управления. Windows также предоставляет внутренний "менеджер диалоговых окон", который воплощает большую часть диалоговой логики, такую как перемещение фокуса ввода, когда юзер нажимает Tab, нажатие кнопки по умолчанию, если нажата кнопка 'Enter, и так далее, так чтобы программисты могли заниматься более высокоуровневыми задачами. Поскольку диалоговое окно можно считать "черным ящиком" (это означает то, что вы не обязаны знать, как
работает диалоговое окно, для того, чтобы использовать его), вы должны только знать, как с ним взаимодействовать. Это принцип объектно-ориентированного
программирования, называемого скрытием информации. Если черный ящик спроектирован совершенно, пользователь может использовать его не зная, как он работает.
Правда, загвоздка в том, что черный ящик должен быть совершенным, это труднодостижимо в реальном мире. Win32 API также спроектирован как черный ящик.

Ладно, похоже, что мы немного отклонились. Давайте вернемся к нашему сюжету. Диалоговые окна спроектированы так, чтобы снизить нагрузку на программиста.
Обычно, если вы помещаете дочерний контрол на обычное окно, вы должны сабклассить их и самостоятельно обрабатывать нажатия на клавиши. Но если вы помещаете их на диалоговое окно, оно обработает их за вас. Вы только должны как получать информацию, вводимую пользователем, или как посылать команды окну. Диалоговое окно определяется как ресурс (похожим образом, как и меню). Вы пишете шаблон диалогового окна, описывая характеристики диалогового окна и его контролов, а затем компилируете его с помощью редактора ресурсов.

Обратите внимание, что все ресурсы располагаются в одном скрипте ресурсов. Вы можете использовать любой текстовый редактор, чтобы написать шаблон диалогового окна, но я бы не рекомендовал это. Вы должны использовать редактор ресурсов, чтобы сделать визуально расположить дочерние окна. Существует несколько прекрасных редакторов ресурсов. К большинству из основных компиляторов прилагаются подобные редакторы. Вы можете использовать их, чтобы создать скрипт ресурса. После этого стоит вырезать лишние линии, например, те, которые относятся к MFC.

Есть два основных вида диалоговых окон: модальные и независимые. Независимые диалоговые окна дают вам возможность перемещать фокус ввода на другие окна.
Пример - диалоговое окно 'Find' в MS Word. Есть два подтипа модальных диалоговых окон: модальные к приложению и модальные к системе. Первые не дают вам переключаться на другое окно того же приложения, но вы можете переключиться на другое приложение. Вторые не дают вам возможности переключиться на любое другое окно.

Независимое диалоговое окно создается с помощью вызова функции CreateDialogParam. Модальное диалоговое окно создается вызовом DialogBoxParam. Единственное Различие между диалоговым окном, модальным отношению к приложению, и диалоговым окном, модальным по отношению к системе, - это стиль DS_SYSMODAL. Если вы включите стиль DS_SYSMODAL в шаблон диалогового окна, это диалоговое окно будет модальным к системе.

Вы можете взаимодействовать с любым дочерним элементом управления на диалоговом окне с помощью функции SendDlgItemMessage. Ее синтакс следующий:

function SendDlgItemMessage _
(byval hwndDlg as HWND, _
byval idControl as integer, _
byval uMsg as UINT, _
byval wParam as WPARAM, _
byval lParam as LPARAM) as LRESULT

Эта API-функция неоценимо полезна при взаимодействии с дочерним окном. Например, если вы хотите получить текст с контрола edit, вы можете сделать следующее:

SendDlgItemMessage(hDlg, ID_EDITBOX, WM_GETTEXT, 256, @text_buffer)

Чтобы знать, какое сообщение когда посылать, вы должны проконсультироваться с вашим Win32 API-справочником.

Windows также предоставляет несколько специальных API-функций, заточенных под дочерние окна, для быстрого получения и установки нужных данных, например, GetDlgItemText, CheckDlgButton и т.д. Эти специальные функции созданы, чтобы программисту не приходилось выяснять каждый раз значения wparam и lparam.
Как правило, вы должны использовать данные функции, если хотите, чтобы управление кодом было легче. Используйте SendDlgItemMessage только, если нет соответствующей API-функции. Менеджер диалоговых окон посылает некоторые сообщения специальной callback-функции, называемой процедурой диалогового окна, которая имеет следующий формат:

function DlgProc _
(byval hDlg as HWND
uMsg as UINT, _
byval wparam as WPARAM, byval lparam as LPARAM) as BOOL

Процедура диалогового окна очень похожа на процедуру окна, если не считать тип возращаемого значения - TRUE/FALSE, вместо обычных LRESULT. Внутренний менеджер диалоговых окон внутри Windows - истинная процедура для диалоговых окон. Она вызывает нашу процедуру диалоговых окон, передавая некоторые из полученных сообщений. Поэтому главное правило следующее: если наша процедура диалогового окна обрабатывает сообщение, она должна вернуть TRUE и если она не обрабатывает сообщение, тогда она должна вернуть FALSE. Заметьте, что процедура диалогового окна не передает сообщения функции DefWindowProc, так как это не настоящая процедура окна.

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

"Использование диалогового окна как основное окно" можно понимать двояко.

• Вы можете использовать шаблон диалогового окна как шаблон класса, который вы регистрируете с помощью функции RegisterClassEx. В этом случае, диалоговое окно ведет себя как "нормальное": оно получает сообщения через процедуру окна, на которую ссылается lрfnWndProc, а не через процедуру диалогового окна.
Выгода данного подхода состоит в том, что вы не должны самостоятельно создавать дочерние элементы управления, Windows создает их во время создания диалогового окна. Также Windows берет на себя логику нажатий на клавиши (Tab и т.д.). Плюс вы можете указать курсор и иконку вашего окна в структуре класса окна.

• Ваша программа создает диалоговое окно без создания родительского окна. Этот подход делает цикл сообщений ненужным, так как сообщения шлются напрямую процедуре диалогового окна. Вам даже не нужно регистрировать класс окна!

Похоже, что этот туториал будет довольно долгим.

Пример:

файл dialog.bas

Скопировать данный код в буфер обмена

файл dialog.rc

Скопировать данный код в буфер обмена

Анализ:

Давайте проанализируем первый пример.
Этот пример показывает, как зарегистрировать диалоговый шаблон как класс окна и создает "окно" из этого класса. Это упрощает вашу программу, так как вам не нужно создавать дочерние контролы самостоятельно.

Давайте проанализируем шаблон диалогового окна.

MyDialog DIALOG 10, 10, 205, 60

Объявление имя диалога, в данном случае - "MyDialog", за которым следует ключевое слово "DIALOG". Следующие четыре номера - это x, y, ширина и высота диалогового окна в специальных единицах (не в пикселях).

STYLE 0x0004 | DS_CENTER | WS_CAPTION | WS_MINIMIZEBOX |
WS_SYSMENU | WS_VISIBLE | WS_OVERLAPPED | DS_MODALFRAME | DS_3DLOOK

Объявление стилей диалогового окна.

CAPTION "Our First Dialog Box"

Это текст, который появится в title bar'е.

CLASS "DLGCLASS"

Это ключевая строка. Ключевое слово 'CLASS' позволяет нам использовать шаблон диалогового окна в качестве класса окна. Следующее слово - это имя "класса окна".

{
EDITTEXT IDC_EDIT, 15,17,111,13, ES_AUTOHSCROLL | ES_LEFT
DEFPUSHBUTTON "Say Hello", IDC_BUTTON, 141,10,52,13
PUSHBUTTON "E&xit", IDC_EXIT, 141,26,52,13
}

Данный блок определяет дочерние элементы управления в диалоговом окне. Они определены между фигурными скобками { }. Общий синтаксис таков:

control-type "text" ,controlID, x, y, width, height [,styles]

control-type'ы - это константы компилятора ресурсов, вам нужно свериться с руководством.

Теперь мы углубляемся непосредственно в код. Интересующая нас часть находится в структуре класса окна.

.cbWndExtra = DLGWINDOWEXTRA
.lpszClassName = @"DLGCLASS"

Обычно этот параметр оставляется равным нулю, но если мы хотим зарегистрировать шаблон диалогового окна как класс окна, мы должны установить этот параметр равным DLGWINDOWEXTRA. Заметьте, что имя класса должно совпадать с именем, что определено в шаблоне диалогового окна. Остающиеся параметры инициализируются как обычно. После того, как вы заполните структуру класса окна, зарегистрируйте ее с помощью RegisterClassEx. Звучит знакомо. Точно также вы регистрируете
обычный класс окна.

' Создадим диалог
hDlg = CreateDialogParam _
(hInst, _
"MyDialog", _
NULL,NULL,NULL)

После регистрации "класса окна", мы создаем наше диалоговое окно. В этом примере я создал его как независимое диалоговое окно функцией CreateDialogParam.
Эта функция получает 5 параметров, но вам нужно заполнить только первые два: хэндл процесса и указатель на имя шаблона диалогового окна. Заметьте, что второй параметр - это не указатель на имя класса.

В этот момент, диалоговое окно и его дочерние элементы управления создаются Windows. Ваша процедура окна получит сообщение WM_CREATE как обычно.

SetFocus(GetDlgItem _
(hDlg,_
IDC_EDIT))

После того, как диалоговое окно создано, я хочу установить фокус ввода на edit control. Если я помещу соответствующий код в секцию WM_CREATE, вызов GetDlgItem провалится, так как дочерние окна еще не созданы. Единственный путь сделать это - вызвать эту функцию после того, как диалоговое окно и все его дочерние окна будут созданы. Поэтому я помещаю данные две линии после вызова UpdateWindow. Функция GetDlgItem получает ID контрола и возвращает соответствующий хэндл окна. Так вы можете получить хэндл окна, если вы знаете его control ID.

if IsDialogMessage(hDlg, @wMsg) = FALSE then
TranslateMessage( @wMsg )
DispatchMessage( @wMsg )
end if

Программа входит в цикл сообщений и перед тем, как мы транслируем и передаем сообщения, мы вызываем функцию IsDialogMessage, чтобы позволить менеджеру диалоговых сообщений обрабатывать логику сообщений за нас. Если эта функция возвращает TRUE, это значит, что сообщение сделано для диалогового окна и обрабатывается менеджером диалоговых сообщений. Отметьте другое отличие от предыдущего туториала. Когда процедура окна хочет получить текст с edit контрола, она вызывает функцию GetDlgItemText, вместо функции GetWindowText. GetDlgItemText принимает ID контрола вместо хэндла окна. Это делает вызов проще в том случае, если вы используете диалоговое окно.

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

Скопировать данный код в буфер обмена

файл dialog_p2.bi

Скопировать данный код в буфер обмена

файл dialog_p2.rc

Скопировать данный код в буфер обмена

Анализ:

Function DlgProc (byval hwnd as HWND, byval uMsg as UINT, _
byval wparam as WPARAM, byval lparam as LPARAM) as BOOL

Мы объявляем прототип функции для DlgProc, так что мы можем ссылаться на нее оператором @:

end DialogBoxParam _
(hModule, _ '
"MyDialog", _
NULL, _
@DlgProc, _
NULL)

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

case WM_INITDIALOG
SetFocus(GetDlgItem _
(hWnd, _
IDC_EDIT))
case WM_CLOSE
SendMessage _
(hWnd, _
WM_COMMAND, _
IDM_EXIT, _
0)

Процедура диалогового окна выглядит как процедура окна, не считая того, что она не получает сообщение WM_CREATE. Первое сообщение, которое она получает- это WM_INITDIALOG. Обычно вы помещаете здесь инициализационный код. Заметьте, что вы должны вернуть значение TRUE, если вы обрабатываете это сообщение.

Внутренний менеджер диалогового окна не посылает нашей процедуре сообщение WM_DESTROY, а вот WM_CLOSE шлет. Поэтому если мы хотим отреагировать на то, что юзер нажимает кнопку закрытия на нашем диалоговом окне, мы должны обработать сообщение WM_CLOSE. В нашем примере мы посылаем сообщение WM_CLOSE со значением IDM_EXIT в wParam. Это произведет тот же эффект, что и выбор пункта 'Exit' в меню. EndDialog вызывается в ответ на IDM_EXIT.

Обработка сообщений WM_COMMAND остается такой же.

Когда вы хотите уничтожить диалоговое окно, единственный путь - это вызов функции EndDialog. Не пробуйте DestroyWindow! EndDialog не уничтожает диалоговое окно немедленно. Она только устанавливает флаг для внутреннего менеджера диалогового окна и продолжает выполнять следующие инструкции.

Теперь давайте изучим файл ресурсов. Заметное изменение - это то, что вместо использования текстовой строки в качестве имени меню, мы используем значение IDR_MENU1. Это необходимо, если вы хотите прикрепить меню к диалоговому окну, созданному DialogBoxParam'ом. Заметьте, что в шаблоне диалогового окна вы должны добавить ключевое слово 'MENU', за которым будет следовать ID ресурса меню.

различие между двумя примерами в этом туториале, которое вы можете легко заметить - это отсутствие иконки в последнем примере. Тем не менее, вы можете установить иконку, послав сообщение WM_SETICON диалоговому окну во время обработки WM_INITDIALOG.

[C] Iczelion, пер. Aquila.

 

 

Прокомментировать

Ваше имя:  

Ваш e-mail:  

Сообщение:



Введите код: 

 

 

   Спасибо можно сказать, посетив любую ссылку:

 

 

© 2010-2012

DEPOzit (Попов Денис Владимирович)

WebMoney кошелёк: WMID#302963000004

ICQ:279786014 или R549103331586   Z116647355686