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

Образец программы

Рассмотрим простой пример. В программе MENUDEMO, представленной на рис. 10.1, в главном меню имеется пять пунктов — File, Edit, Background, Timer и Help. В каждом из этих пунктов имеется всплывающее меню. В программе MENUDEMO демонстрируется простейший и наиболее частый способ обработки сообщений меню, который подразумевает перехват сообщений WM_COMMAND и анализ младшего слова параметра wParam.

MENUDEMO.MAK

#------------------------

# MENUDEMO.MAK make file

#------------------------

menudemo.exe : menudemo.obj menudemo.res

$(LINKER) $(GUIFLAGS) -OUT:menudemo.exe menudemo.obj \

menudemo.res $(GUILIBS)

menudemo.obj : menudemo.c menudemo.h

$(CC) $(CFLAGS) menudemo.c

menudemo.res : menudemo.rc menudemo.h

$(RC) $(RCVARS) menudemo.rc

MENUDEMO.C

/*-----------------------------------------

MENUDEMO.C -- Menu Demonstration

(c) Charles Petzold, 1996

-----------------------------------------*/

#include <windows.h>

#include "menudemo.h"

LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;

char szAppName[] = "MenuDemo" ;

int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,

PSTR szCmdLine, int iCmdShow)

{

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 = (HBRUSH) GetStockObject (WHITE_BRUSH) ;

wndclass.lpszMenuName = szAppName ;

wndclass.lpszClassName = szAppName ;

wndclass.hIconSm = LoadIcon (NULL, IDI_APPLICATION) ;

RegisterClassEx (&wndclass) ;

hwnd = CreateWindow (szAppName, "Menu Demonstration",

WS_OVERLAPPEDWINDOW,

CW_USEDEFAULT, CW_USEDEFAULT,

CW_USEDEFAULT, CW_USEDEFAULT,

NULL, NULL, hInstance, NULL) ;

ShowWindow (hwnd, iCmdShow) ;

UpdateWindow (hwnd) ;

while (GetMessage (&msg, NULL, 0, 0))

{

TranslateMessage (&msg) ;

DispatchMessage (&msg) ;

}

return msg.wParam ;

}

LRESULT CALLBACK WndProc (HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam)

{

static int iColorID[5] = { WHITE_BRUSH, LTGRAY_BRUSH, GRAY_BRUSH,

DKGRAY_BRUSH, BLACK_BRUSH } ;

static int iSelection = IDM_WHITE ;

HMENU hMenu ;

switch (iMsg)

{

case WM_COMMAND :

hMenu = GetMenu (hwnd) ;

switch (LOWORD (wParam))

{

case IDM_NEW :

case IDM_OPEN :

case IDM_SAVE :

case IDM_SAVEAS :

MessageBeep (0) ;

return 0 ;

case IDM_EXIT :

SendMessage (hwnd, WM_CLOSE, 0, 0L) ;

return 0 ;

case IDM_UNDO :

case IDM_CUT :

case IDM_COPY :

case IDM_PASTE :

case IDM_DEL :

MessageBeep (0) ;

return 0 ;

case IDM_WHITE : // Note: Logic below

case IDM_LTGRAY : // assumes that IDM_WHITE

case IDM_GRAY : // through IDM_BLACK are

case IDM_DKGRAY : // consecutive numbers in

case IDM_BLACK : // the order shown here.

CheckMenuItem (hMenu, iSelection, MF_UNCHECKED) ;

iSelection = LOWORD (wParam) ;

CheckMenuItem (hMenu, iSelection, MF_CHECKED) ;

SetClassLong (hwnd, GCL_HBRBACKGROUND,

(LONG) GetStockObject

(iColorID[LOWORD (wParam) - IDM_WHITE])) ;

InvalidateRect (hwnd, NULL, TRUE) ;

return 0 ;

case IDM_START :

if (SetTimer (hwnd, 1, 1000, NULL))

{

EnableMenuItem (hMenu, IDM_START, MF_GRAYED) ;

EnableMenuItem (hMenu, IDM_STOP, MF_ENABLED) ;

}

return 0 ;

case IDM_STOP :

KillTimer (hwnd, 1) ;

EnableMenuItem (hMenu, IDM_START, MF_ENABLED) ;

EnableMenuItem (hMenu, IDM_STOP, MF_GRAYED) ;

return 0 ;

case IDM_HELP :

MessageBox (hwnd, "Help not yet implemented!",

szAppName, MB_ICONEXCLAMATION | MB_OK) ;

return 0 ;

case IDM_ABOUT :

MessageBox (hwnd, "Menu Demonstration Program.",

szAppName, MB_ICONINFORMATION | MB_OK) ;

return 0 ;

}

break ;

case WM_TIMER :

MessageBeep (0) ;

return 0 ;

case WM_DESTROY :

PostQuitMessage (0) ;

return 0 ;

}

return DefWindowProc (hwnd, iMsg, wParam, lParam) ;

}

MENUDEMO.RC

/*-----------------------------

MENUDEMO.RC resource script

-----------------------------*/

#include "menudemo.h"

MenuDemo MENU

{

POPUP "&File"

{

MENUITEM "&New", IDM_NEW

MENUITEM "&Open...", IDM_OPEN

MENUITEM "&Save", IDM_SAVE

MENUITEM "Save &As...", IDM_SAVEAS

MENUITEM SEPARATOR

MENUITEM "E&xit", IDM_EXIT

}

POPUP "&Edit"

{

MENUITEM "&Undo", IDM_UNDO

MENUITEM SEPARATOR

MENUITEM "Cu&t", IDM_CUT

MENUITEM "&Copy", IDM_COPY

MENUITEM "&Paste", IDM_PASTE

MENUITEM "De&lete", IDM_DEL

}

POPUP "&Background"

{

MENUITEM "&White", IDM_WHITE, CHECKED

MENUITEM "&Lt Gray", IDM_LTGRAY

MENUITEM "&Gray", IDM_GRAY

MENUITEM "&Dk Gray", IDM_DKGRAY

MENUITEM "&Black", IDM_BLACK

}

POPUP "&Timer"

{

MENUITEM "&Start" IDM_START

MENUITEM "S&top" IDM_STOP, GRAYED

}

POPUP "&Help"

{

MENUITEM "&Help...", IDM_HELP

MENUITEM "&About MenuDemo...", IDM_ABOUT

}

}

MENUDEMO.H

/*------------------------

MENUDEMO.H header file

------------------------*/

#define IDM_NEW 1

#define IDM_OPEN 2

#define IDM_SAVE 3

#define IDM_SAVEAS 4

#define IDM_EXIT 5

#define IDM_UNDO 10

#define IDM_CUT 11

#define IDM_COPY 12

#define IDM_PASTE 13

#define IDM_DEL 14

#define IDM_WHITE 20

#define IDM_LTGRAY 21

#define IDM_GRAY 22

#define IDM_DKGRAY 23

#define IDM_BLACK 24

#define IDM_START 30

#define IDM_STOP 31

#define IDM_HELP 40

#define IDM_ABOUT 41

Рис. 10.1. Программа MENUDEMO

Все идентификаторы пунктов меню определяются в заголовочном файле MENUDEMO.Н. Этот файл должен быть включен (с помощью инструкции #include) в файл описания ресурсов и в файл с исходным текстом программы на С. Идентификаторы начинаются с букв IDM. Значения идентификаторов не обязательно должны быть последовательными. Однако, если в программе эти идентификаторы обрабатываются с помощью операторов switch и case, то запомните, что компилятор С гораздо лучше оптимизирует этот код, если значения идентификаторов будут последовательными.

Программа MENUDEMO просто издает звуковой сигнал (гудок) при получении сообщения WM_COMMAND для большинства пунктов всплывающих меню File и Edit. Во всплывающем меню Background перечисляются пять стандартных кистей, которые программа MENUDEMO может использовать для закрашивания фона. В файле описания ресурсов MENUDEMO.RC пункт меню White (с идентификатором меню IDM_WHITE) устанавливается в состояние CHECKED, что вызывает появление метки около этого элемента. В исходном тексте программы MENUDEMO.C начальное значение iSelection устанавливается равным IDM_WHITE.

Пять кистей всплывающего меню Background являются взаимоисключающими. Когда программа MENUDEMO.C получает сообщение WM_COMMAND, в котором младшее слово параметра wParam является одним из этих пяти пунктов всплывающего меню Background, она должна удалить метку от ранее выбранного цвета фона и поместить ее к новому цвету фона. Для этого, сначала программа получает описатель этого меню:

hMenu = GetMenu (hwnd) ;

Функция CheckMenuItem используется для снятия метки отмеченного в данный момент пункта меню:

CheckMenuItem (hMenu, iSelection, MF_UNCHECKED) ;

Затем значение iSelection устанавливается равным младшему слову параметра wParam, и новый цвет фона помечается:

iSelection = LOWORD (wParam) ;

CheckMenuItem (hMenu, iSelection, MF_CHECKED) ;

Цвет фона, заданный в классе окна, заменяется новым, и рабочая область окна делается недействительной. Используя новый цвет фона, Windows обновляет окно.

Во всплывающем меню Timer имеется две опции — Start и Stop. В начальный момент времени опция Stop недоступна (так задано в определении меню файла описания ресурсов). При выборе опции Start, программа MENUDEMO пытается запустить таймер и, если это получается, делает недоступной опцию Start, а опцию Stop доступной:

EnableMenuItem (hMenu, IDM_START, MF_GRAYED) ;

EnableMenuItem (hMenu, IDM_STOP, MF_ENABLED) ;

При получении сообщения WM_COMMAND с младшим словом параметра wParam равным IDM_STOP, программа MENUDEMO останавливает таймер, делает опцию Start доступной, а опцию Stop — недоступной:

EnableMenuItem (hMenu, IDM_START, MF_ENABLED) ;

EnableMenuItem (hMenu, IDM_STOP, MF_GRAYED) ;

Обратите внимание, что, пока таймер работает, программа MENUDEMO не может получить сообщение WM_COMMAND с младшим словом параметра wParam равным IDM_START. Аналогично, если таймер не работает, то программа MENUDEMO не может получить сообщение WM_COMMAND с младшим словом параметра wParam равным IDM_STOP.

Когда программа получает сообщение WM_COMMAND с младшим словом параметра wParam равным IDM_ABOUT или IDM_HELP, на экран выводится окно сообщения. (В следующей главе мы поменяем его на окно диалога.)

Когда программа получает сообщение WM_COMMAND с младшим словом параметра wParam равным IDM_EXIT, она сама себе посылает сообщение WM_CLOSE. Это то самое сообщение, которое DefWindowProc посылает оконной процедуре при получении сообщения WM_SYSCOMMAND с параметром wParam равным SC_CLOSE. Ближе к окончанию главы, в программе POPPAD2, мы исследуем этот вопрос более подробно.

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