Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Ch-11.doc
Скачиваний:
0
Добавлен:
01.05.2025
Размер:
1.26 Mб
Скачать

Новая программа 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 сведено к минимуму, загрузите с диска следующую программу.

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]