
- •Глава 11 Окна диалога
- •Модальные окна диалога
- •Создание окна диалога About
- •Шаблон окна диалога
- •Диалоговая процедура
- •Вызов окна диалога
- •Дополнительная информация о стиле окна диалога
- •Дополнительная информация об определении дочерних окон элементов управления
- •Более сложное окно диалога
- •Работа с дочерними элементами управления окна диалога
- •Кнопки ok и Cancel
- •Позиции табуляции и группы
- •Рисование в окне диалога
- •Использование с окном диалога других функций
- •Определение собственных окон управления
- •Окна сообщений
- •Информация во всплывающих окнах
- •Немодальные окна диалога
- •Различия между модальными и немодальными окнами диалога
- •Новая программа colors
- •Программа hexcalc: обычное окно или окно диалога?
- •Творческое использование идентификаторов дочерних окон элементов управления
- •Диалоговые окна общего пользования
- •Модернизированная программа poppad
- •Изменение шрифта
- •Поиск и замена
- •Программа для Windows, содержащая всего один вызов функции
Новая программа colors
В программе COLORS1, описанной в главе 8, для вывода на экран трех полос прокрутки и шести текстовых элементов было создано девять дочерних окон. В тот момент это была одна из самых сложных наших программ. Изменим программу COLORS1 так, чтобы в ней использовались немодальные окна диалога. Эти изменения делают программу, а в особенности ее функцию WndProc, до смешного простой. Переделанная программа COLORS2 представлена на рис. 11.7.
COLORS2.MAK
#-----------------------
# COLORS2.MAK make file
#-----------------------
colors2.exe : colors2.obj colors2.res
$(LINKER) $(GUIFLAGS) -OUT:colors2.exe colors2.obj colors2.res $(GUILIBS)
colors2.obj : colors2.c
$(CC) $(CFLAGS) colors2.c
colors2.res : colors2.rc
$(RC) $(RCVARS) colors2.rc
COLORS2.C
/*------------------------------------------------
COLORS2.C -- Version using Modeless Dialog Box
(c) Charles Petzold, 1996
------------------------------------------------*/
#include <windows.h>
LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;
BOOL CALLBACK ColorScrDlg (HWND, UINT, WPARAM, LPARAM) ;
HWND hDlgModeless ;
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
PSTR szCmdLine, int iCmdShow)
{
static char szAppName[] = "Colors2" ;
HWND hwnd ;
MSG msg ;
WNDCLASSEX wndclass ;
wndclass.cbSize = sizeof (wndclass) ;
wndclass.style = CS_HREDRAW | CS_VREDRAW ;
wndclass.lpfnWndProc = WndProc ;
wndclass.cbClsExtra = 0 ;
wndclass.cbWndExtra = 0 ;
wndclass.hInstance = hInstance ;
wndclass.hIcon = LoadIcon (NULL, IDI_APPLICATION) ;
wndclass.hCursor = LoadCursor (NULL, IDC_ARROW) ;
wndclass.hbrBackground = CreateSolidBrush (0L) ;
wndclass.lpszMenuName = NULL ;
wndclass.lpszClassName = szAppName ;
wndclass.hIconSm = LoadIcon (NULL, IDI_APPLICATION) ;
RegisterClassEx (&wndclass) ;
hwnd = CreateWindow (szAppName, "Color Scroll",
WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN,
CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT,
NULL, NULL, hInstance, NULL) ;
ShowWindow (hwnd, iCmdShow) ;
UpdateWindow (hwnd) ;
hDlgModeless = CreateDialog (hInstance, "ColorScrDlg", hwnd, ColorScrDlg) ;
while (GetMessage (&msg, NULL, 0, 0))
{
if (hDlgModeless == 0 || !IsDialogMessage (hDlgModeless, &msg))
{
TranslateMessage (&msg) ;
DispatchMessage (&msg) ;
}
}
return msg.wParam ;
}
LRESULT CALLBACK WndProc (HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam)
{
switch (iMsg)
{
case WM_DESTROY :
DeleteObject (
(HGDIOBJ) SetClassLong (hwnd, GCL_HBRBACKGROUND,
(LONG) GetStockObject (WHITE_BRUSH))) ;
PostQuitMessage (0) ;
return 0 ;
}
return DefWindowProc (hwnd, iMsg, wParam, lParam) ;
}
BOOL CALLBACK ColorScrDlg (HWND hDlg, UINT iMsg, WPARAM wParam, LPARAM lParam)
{
static int iColor[3] ;
HWND hwndParent, hCtrl ;
int iCtrlID, iIndex ;
switch (iMsg)
{
case WM_INITDIALOG :
for (iCtrlID = 10 ; iCtrlID < 13 ; iCtrlID++)
{
hCtrl = GetDlgItem (hDlg, iCtrlID) ;
SetScrollRange (hCtrl, SB_CTL, 0, 255, FALSE) ;
SetScrollPos (hCtrl, SB_CTL, 0, FALSE) ;
}
return TRUE ;
case WM_VSCROLL :
hCtrl = (HWND) lParam ;
iCtrlID = GetWindowLong (hCtrl, GWL_ID) ;
iIndex = iCtrlID - 10 ;
hwndParent = GetParent (hDlg) ;
switch (LOWORD (wParam))
{
case SB_PAGEDOWN :
iColor[iIndex] += 15 ; // fall through
case SB_LINEDOWN :
iColor[iIndex] = min (255, iColor[iIndex] + 1) ;
break ;
case SB_PAGEUP :
iColor[iIndex] -= 15 ; // fall through
case SB_LINEUP :
iColor[iIndex] = max (0, iColor[iIndex] - 1) ;
break ;
case SB_TOP :
iColor[iIndex] = 0 ;
break ;
case SB_BOTTOM :
iColor[iIndex] = 255 ;
break ;
case SB_THUMBPOSITION :
case SB_THUMBTRACK :
iColor[iIndex] = HIWORD (wParam) ;
break ;
default :
return FALSE ;
}
SetScrollPos (hCtrl, SB_CTL, iColor[iIndex], TRUE) ;
SetDlgItemInt (hDlg, iCtrlID + 3, iColor[iIndex], FALSE) ;
DeleteObject (
(HGDIOBJ) SetClassLong (hwndParent, GCL_HBRBACKGROUND,
(LONG) CreateSolidBrush (
RGB (iColor[0], iColor[1], iColor[2])))) ;
InvalidateRect (hwndParent, NULL, TRUE) ;
return TRUE ;
}
return FALSE ;
}
COLORS2.RC
/*----------------------------
COLORS2.RC resource script
----------------------------*/
#include <windows.h>
#define SBS_VERT_TAB (SBS_VERT | WS_TABSTOP)
ColorScrDlg DIALOG 8, 16, 124, 132
STYLE WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_VISIBLE
CAPTION "Color Scroll Scrollbars"
{
CONTROL "&Red", -1, "static", SS_CENTER, 10, 4, 24, 8
CONTROL "", 10, "scrollbar", SBS_VERT_TAB, 10, 16, 24, 100
CONTROL "0", 13, "static", SS_CENTER, 10, 120, 24, 8
CONTROL "&Green", -1, "static", SS_CENTER, 50, 4, 24, 8
CONTROL "", 11, "scrollbar", SBS_VERT_TAB, 50, 16, 24, 100
CONTROL "0", 14, "static", SS_CENTER, 50, 120, 24, 8
CONTROL "&Blue", -1, "static", SS_CENTER, 90, 4, 24, 8
CONTROL "", 12, "scrollbar", SBS_VERT_TAB, 90, 16, 24, 100
CONTROL "0", 15, "static", SS_CENTER, 90, 120, 24, 8
}
Рис. 11.7. Программа COLORS2
Хотя в программе COLORS1 выводимые на экран полосы прокрутки зависели от размеров окна, в новой версии их размер в немодальном окне диалога остается постоянным, как это показано на рис. 11.8. В шаблоне окна диалога в файле COLORS2.RC для всех девяти дочерних окон окна диалога используются инструкции CONTROL. Немодальное окно диалога программы COLORS2 создается в функции WinMain сразу после вызова функции UpdateWindow, предназначенной для главного окна программы. Обратите внимание, что стиль главного окна включает в себя идентификатор WS_CLIPCHILDREN, что дает программе возможность перерисовать главное окно, не затирая окна диалога.
Рис. 11.8. Вид экрана программы COLORS2
Описатель окна диалога, который является возвращаемым значением функции CreateDialog, хранится в глобальной переменной hDlgModeless и проверяется в цикле обработки сообщений так, как описано выше. Однако, в данной программе нет необходимости хранить описатель в глобальной переменной и проверять его значение перед вызовом функции IsDialogMessage. При этом цикл обработки сообщений мог бы быть написан так:
while (GetMessage(&msg, NULL, 0, 0))
{
if (!IsDialogMessage(hDlgModeless, &msg))
{
TranslateMessage (&msg) ;
DispatchMessage (&msg) ;
}
}
Поскольку окно диалога создается до того, как в программе вводится цикл обработки сообщений, и окно диалога не закрывается до тех пор пока не завершится программа, значение hDlgModeless всегда будет корректным. Ниже приведен код, который может быть вставлен в оконную процедуру диалога, если вам захочется добавить возможность закрытия окна диалога:
case WM_CLOSE :
DestroyWindow (hDlg) ;
hDlgModeless = 0 ;
break ;
В программе COLORS1 функция SetWindowText отображала в текстовом виде значения трех целых, преобразованных в текст с помощью функции itoa. Это выглядело так:
SetWindowText (hwndValue[i], itoa (color[i]), szBuffer, 10)) ;
Величина i соответствовала идентификатору обрабатываемой в данный момент полосы прокрутки, а массив hwndValue содержал описатели трех (по числу цветов) статических дочерних окон управления.
В новой версии, чтобы задать выводимое на экран число для каждого текстового поля каждого окна управления используется функция SetDlgItemInt :
SetDlgItemInt (hDlg, iCtrlID + 3, iColor[iIndex], FALSE) ;
(Хотя функция SetDlgItemInt и соответствующая ей функция GetDlgItemInt чаще всего используются в окнах редактирования, они также могут применяться для задания текстового поля и в других окнах элементов управления, например статических.) Переменная iCtrlID определяет идентификатор полосы прокрутки, а добавление 3 к этому числу превращает его в идентификатор соответствующей числовой метки. Третий параметр задает цвет. Обычно четвертый параметр устанавливается в TRUE, чтобы показать, что числа большие 32767 должны отображаться как отрицательные. Однако, в нашей программы диапазон значений от 0 до 255, поэтому величина четвертого параметра значения не имеет.
В процессе превращения программы COLORS1 в COLORS2 мы передаем Windows все больше и больше задач. В первой версии функция CreateWindow вызывалась десять раз; в новой версии по одному разу вызываются функции CreateWindow и CreateDialog. Но если вам кажется, что количество вызовов функции CreateWindow сведено к минимуму, загрузите с диска следующую программу.