К вопросу о переменных

 

 

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


– 79 –


 

 

ЛЕКЦИЯ 8. МНОГООКОННЫЙ ИНТЕРФЕЙС

 

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

 

 

Многооконный интерфейс (Multiple Document Interface, MDI) является спецификацией для приложений, которые обрабатывают документы в Microsoft Windows. Спецификация описывает структуру окон и пользовательский интерфейс, который позволяет пользователю работать с несколькими документами внутри одного приложения (с документами в текстовом процессоре или с таблицами в программе электронных таблиц). Точно также, как Windows поддерживает несколько окон приложений на одном экране, приложение MDI поддерживает несколько окон документов в одной рабочей области. Первым приложением MDI для Windows была первая версия Microsoft Excel. Microsoft Word for Windows и Microsoft Access являются приложениями MDI. Хотя спецификация MDI была введена, уже начиная с Windows 2, в то время писать приложения MDI было трудно, и от программиста требовалось большая очень сложная работа. Однако, начиная с Windows 3, большая часть этой работы была сделана. Windows 95 добавляет только одну новую функцию и одно новое сообщение к набору функций, структурам данных и сообщениям, которые существуют специально для упрощения создания приложений MDI.

 

 

Элементы MDI

 

 

Главное окно приложения программы MDI обычно: в нем имеется строка заголовка, меню, рамка изменения размера, значок системного меню и значки свертывания. Рабочая область, однако, не используется непосредственно для вывода выходных данных программы. В этой рабочей области может находиться несколько дочерних окон, в каждом из которых отображается какой - документ.

 

 

Эти дочерние окна выглядят совершенно так же, как обычные окна приложений. В них имеется строка заголовка, рамка изменения размера, значок системного меню, значки свертывания и, возможно, полосы прокрутки. Однако, ни в одном из окон документов нет меню. Меню главного окна приложения относится и к окнам документов.

 

 

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

 

 

Поначалу, MDI для Windows-программиста кажется совершенно понятным. Все, что нужно сделать — это создать для каждого документа окно WS_CHILD, делая главное окно приложения родительским окном для окна документа. Но при более близком знакомстве с приложением MDI, таким как Microsoft Excel, обнаруживаются определенные трудности, требующие сложного программирования. Например:

 

 

Окно документа MDI может быть свернуто. Соответствующий значок выводится в нижней части рабочей области ( правило: в приложении MDI для главного окна приложения и для каждого типа окна документа будут использоваться разные значки).

 

 

Окно документа MDI может быть развернуто. В этом случае строка заголовка окна документа (обычно используется для вывода в окне имени файла документа) исчезает, и имя файла оказывается присоединенным к имени приложения в строке заголовка окна приложения. Значок системного меню окна документа становится первым пунктом строки основного меню окна приложения. Значок для восстановления размера окна документа становится последним пунктом строки основного меню и оказывается крайним справа.

 

 

Системные быстрые клавиши для закрытия окна документа те же , что и для закрытия главного окна, за исключением того, что клавиша <Ctrl> используется вместо клавиши <Alt>. Таким образом, комбинация <Alt>+<F4> закрывает окно приложения, а комбинация <Ctrl>+<F4> закрывает окно документа. Вдобавок к остальным быстрым клавишам, комбинация <Ctrl>+<F6> позволяет переключаться между


– 81 –

 

 

дочерними окнами документов активного приложения MDI. Комбинация <Alt>+<Spacebar>, как обычно, вызывает системное меню главного окна. Комбинация <Alt>+<-> () вызывает системное меню активного дочернего окна документа .

 

 

При использовании клавиш управления курсором для перемещения по пунктам меню, обычно происходит переход от системного меню к первому пункту строки меню. В приложении MDI порядок перехода изменяется: от системного меню приложения — к системному меню активного документа — и далее к первому пункту строки меню.

 

 

Если приложение имеет возможность поддерживать несколько типов дочерних окон (электронные таблицы и диаграммы в Microsoft Excel), то меню должно отражать операции, ассоциированные с каждым типом документа. Для этого требуется, чтобы программа изменяла меню программы, когда становится активным окно документа другого типа. Кроме этого, при отсутствии окна документа, в меню должны быть представлены только операции, связанные с открытием нового документа.

 

 

В строке основного меню имеется пункт Window. По соглашению, он является последним пунктом строки основного меню, исключая Help. В подменю Window обычно имеются опции для упорядочивания окон документов внутри рабочей области. Окна документов можно расположить cascaded, начиная от верхнего левого угла , или tiled так , что окно каждого документа будет полностью видимо .

 

 

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

 

 

Все эти аспекты MDI поддерживаются в Windows.

 

 

Windows и MDI

 

 

При знакомстве с поддержкой MDI в Windows требуется новая терминология. Окно приложения в целом называется главным окном (frame window). Также как в традиционной программе для Windows, это окно имеет стиль WS_OVERLAPPEDWINDOW.

 

 

Приложение MDI также создает окно - (client window) на основе предопределенного класса окна MDICLIENT. Окно создается с помощью вызова функции CreateWindow с использованием этого класса окна и стиля WS_CHILD. Последним параметром функции CreateWindow является указатель на небольшую структуру типа CLIENTCREATESTRUCT. Это окно - охватывает всю рабочую область главного окна и обеспечивает основную поддержку MDI. Цветом окна - является системный цвет COLOR_APPWORKSPACE.


 

Рис . 11.1. Иерархия родительских и дочерних окон приложения MDI в Windows

 

 

Окна документов называются дочерними окнами (child windows). Эти окна создаются путем инициализации структуры типа MDICREATESTRUCT и посылки окну - сообщения WM_MDICREATE с указателем на эту структуру.

 

 

Окна документов являются дочерними окнами окна-клиента, которое, в свою очередь, является дочерним окном главного окна. Эта иерархия показана на рис. 11.1

 

 

Для главного окна и для каждого типа дочерних окон, которые поддерживаются в приложении, необходим класс окна ( оконная процедура ). Для окна администратора - оконная процедура не нужна, поскольку ее класс окна предварительно зарегистрирован в системе.

 

 

Для поддержки MDI в Windows имеется один класс окна, пять функций, две структуры данных и двенадцать сообщений. О классе окна MDICLIENT и структурах данных CLIENTCREATESTRUCT и MDICREATESTRUCT уже упоминалось. Две из пяти функций заменяют в приложениях MDI функцию DefWindowPro c: вместо вызова функции DefWindowProc для всех необрабатываемых сообщений, оконная процедура главного окна вызывает функцию DefFramePro c, а оконная процедура дочернего окна вызывает функцию DefMDIChildPro c. Другая характерная функция MDI TranslateMDISysAccel используется также, как функция TranslateAccelerato r, о которой рассказывалось в Лекции 10.

 

 

Если в дочерних окнах MDI выполняются протяженные во времени операции, рассмотрите возможность их запуска в отдельных потоках. Это позволит пользователю покинуть дочернее окно и продолжить работу в другом окне, пока первое дочернее окно решает свою задачу в фоновом режиме. В Windows специально для этой цели имеется новая функция CreateMDIWindo w. Поток вызывает функцию CreateMDIWindow для создания дочернего окна MDI; таким образом окно действует исключительно внутри контекста потока. В программе, имеющей один поток, для создания дочернего окна функция CreateMDIWindow не требуется, поскольку то же самое выполняет сообщение WM_MDICREATE.

 

 

Приведем пример - потоковую программы, в которой будет показано девять из двенадцати сообщений MDI. Эти сообщения имеют префикс WM_MDI. Главное окно посылает одно из этих сообщений окну -для выполнения операции над дочерним окном или для получения информации о дочернем окне (главное окно посылает сообщение WM_MDICREATE окну - для создания дочернего окна). Исключение


– 83 –

 

 

составляет сообщение WM_MDIACTIVATE: в то время, как главное окно может послать это сообщение окну – для активизации одного из дочерних окон, окно - также посылает сообщение тем дочерним окнам, которые будут активизированы и тем, которые потеряют активность, чтобы проинформировать их о предстоящем изменении.

 

 

Пример программы

 

 

#include <windows.h>

 

 

#include< stdlib.h>

 

 

#include "mdidemo.h"

 

 

// Предварительное объявление функций

 

 

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

 

 

BOOL CALLBACK CloseEnumProc(HWND, LPARAM);

 

 

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

 

 

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

 

 

// Глобальные переменнве

 

 

char szFrameClass[] = "MdiFrame";

 

 

char szHelloClass[] = "MdiHelloChild";

 

 

char szRectClass[] = "MdiRectChild";

 

 

HINSTANCE hInst;

 

 

HMENU hMenuInit, hMenuHello, hMenuRect;

 

 

HMENU hMenuInitWindow, hMenuHelloWindow, hMenuRectWindow;

 

 

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,

 

 

PSTR szCmdLine, int iCmdShow)

 

 

{

 

 

HACCEL hAccel;

 

 

HWND hwndFrame, hwndClient;


 

 

MSG msg;

 

 

WNDCLASSEX wndclass;

 

 

hInst = hInstance;

 

 

if(!hPrevInstance)

 

 

{

 

 

// Регистрация класса главного окна

 

 

wndclass.cbSize = sizeof(wndclass);

 

 

wndclass.style = CS_HREDRAW | CS_VREDRAW;

 

 

wndclass.lpfnWndProc = FrameWndProc;

 

 

wndclass.cbClsExtra = 0;

 

 

wndclass.cbWndExtra = 0;

 

 

wndclass.hInstance = hInstance;

 

 

wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);

 

 

wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);

 

 

wndclass.hbrBackground =(HBRUSH)(COLOR_APPWORKSPACE + 1);

 

 

wndclass.lpszMenuName = NULL;

 

 

wndclass.lpszClassName = szFrameClass;

 

 

wndclass.hIconSm = LoadIcon(NULL, IDI_APPLICATION);

 

 

RegisterClassEx(&wndclass);

 

 

// Регистрация класса окна, в котором выводится фраза "Привет, мир!"

 

 

wndclass.cbSize = sizeof(wndclass);

 

 

wndclass.style = CS_HREDRAW | CS_VREDRAW;

 

 

wndclass.lpfnWndProc = HelloWndProc;

 

 

wndclass.cbClsExtra = 0;

 

 

wndclass.cbWndExtra = sizeof(HANDLE);

 

 

wndclass.hInstance = hInstance;

 

 

wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);


– 85 –

 

 

wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);

 

 

wndclass.hbrBackground =(HBRUSH) GetStockObject(WHITE_BRUSH);

 

 

wndclass.lpszMenuName = NULL;

 

 

wndclass.lpszClassName = szHelloClass;

 

 

wndclass.hIconSm = LoadIcon(NULL, IDI_APPLICATION);

 

 

RegisterClassEx(&wndclass);

 

 

// Регистрация класса окна, в котором выводится прямоугольник

 

 

wndclass.cbSize = sizeof(wndclass);

 

 

wndclass.style = CS_HREDRAW | CS_VREDRAW;

 

 

wndclass.lpfnWndProc = RectWndProc;

 

 

wndclass.cbClsExtra = 0;

 

 

wndclass.cbWndExtra = sizeof(HANDLE);

 

 

wndclass.hInstance = hInstance;

 

 

wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);

 

 

wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);

 

 

wndclass.hbrBackground =(HBRUSH) GetStockObject(WHITE_BRUSH);

 

 

wndclass.lpszMenuName = NULL;

 

 

wndclass.lpszClassName = szRectClass;

 

 

wndclass.hIconSm = LoadIcon(NULL, IDI_APPLICATION);

 

 

RegisterClassEx(&wndclass);

 

 

}

 

 

// Формирование описателей меню для разных окон

 

 

hMenuInit = LoadMenu(hInst, "MdiMenuInit");

 

 

hMenuHello = LoadMenu(hInst, "MdiMenuHello");

 

 

hMenuRect = LoadMenu(hInst, "MdiMenuRect");

 

 

hMenuInitWindow = GetSubMenu(hMenuInit, INIT_MENU_POS);


 

 

hMenuHelloWindow = GetSubMenu(hMenuHello, HELLO_MENU_POS);

 

 

hMenuRectWindow = GetSubMenu(hMenuRect, RECT_MENU_POS);

 

 

// Чтение горячих клавиш

 

 

hAccel = LoadAccelerators(hInst, "MdiAccel");

 

 

// Создание главного окна

 

 

hwndFrame = CreateWindow(szFrameClass, "MDI Demonstration",

 

 

WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN,

 

 

CW_USEDEFAULT, CW_USEDEFAULT,

 

 

CW_USEDEFAULT, CW_USEDEFAULT,

 

 

NULL, hMenuInit, hInstance, NULL);

 

 

hwndClient = GetWindow(hwndFrame, GW_CHILD);

 

 

ShowWindow(hwndFrame, iCmdShow);

 

 

UpdateWindow(hwndFrame);

 

 

// Цикл обработки сообщений

 

 

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

 

 

{

 

 

if(!TranslateMDISysAccel(hwndClient,& msg) &&

 

 

!TranslateAccelerator(hwndFrame, hAccel, &msg))

 

 

{

 

 

TranslateMessage(&msg);

 

 

DispatchMessage(&msg);

 

 

}

 

 

}

 

 

// Удаление меню

 

 

DestroyMenu(hMenuHello);


– 87 –

 

 

DestroyMenu(hMenuRect);

 

 

return msg.wParam;

 

 

}

 

 

// оконная процедура главного окна

 

 

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

 

 

{

 

 

static HWND hwndClient;

 

 

CLIENTCREATESTRUCT clientcreate;

 

 

HWND hwndChild;

 

 

MDICREATESTRUCT mdicreate;

 

 

switch(iMsg)

 

 

{

 

 

case WM_CREATE : // Создание клиентского окна

 

 

clientcreate.hWindowMenu = hMenuInitWindow;

 

 

clientcreate.idFirstChild = IDM_FIRSTCHILD;

 

 

hwndClient = CreateWindow("MDICLIENT", NULL,

 

 

WS_CHILD | WS_CLIPCHILDREN | WS_VISIBLE,

 

 

0, 0, 0, 0, hwnd,(HMENU) 1, hInst, (LPSTR) &clientcreate);

 

 

return 0;

 

 

case WM_COMMAND:

 

 

switch(wParam)

 

 

{

 

 

case IDM_NEWHELLO: // Создание дочернего окна, в котором выводится фраза "Привет, мир!"

 

 

mdicreate.szClass = szHelloClass;

 

 

mdicreate.szTitle = "Hello";

 

 

mdicreate.hOwner = hInst;

 

 

mdicreate.x = CW_USEDEFAULT;


 

 

mdicreate.y = CW_USEDEFAULT;

 

 

mdicreate.cx = CW_USEDEFAULT;

 

 

mdicreate.cy = CW_USEDEFAULT;

 

 

mdicreate.style = 0;

 

 

mdicreate.lParam = 0;

 

 

hwndChild =(HWND) SendMessage(hwndClient, WM_MDICREATE, 0,

 

 

(LPARAM)(LPMDICREATESTRUCT)& mdicreate);

 

 

return 0;

 

 

case IDM_NEWRECT : // Создание дочернего окна , в котором выводится прямоугольник

 

 

mdicreate.szClass = szRectClass;

 

 

mdicreate.szTitle = "Rectangles";

 

 

mdicreate.hOwner = hInst;

 

 

mdicreate.x = CW_USEDEFAULT;

 

 

mdicreate.y = CW_USEDEFAULT;

 

 

mdicreate.cx = CW_USEDEFAULT;

 

 

mdicreate.cy = CW_USEDEFAULT;

 

 

mdicreate.style = 0;

 

 

mdicreate.lParam = 0;

 

 

hwndChild =(HWND) SendMessage(hwndClient, WM_MDICREATE, 0,

 

 

(LPARAM)(LPMDICREATESTRUCT)& mdicreate);

 

 

return 0;

 

 

case IDM_CLOSE : // Закрыти активного окна

 

 

hwndChild =(HWND) SendMessage(hwndClient, WM_MDIGETACTIVE, 0, 0);

 

 

if (SendMessage(hwndChild, WM_QUERYENDSESSION, 0, 0))

 

 

SendMessage(hwndClient, WM_MDIDESTROY, (WPARAM) hwndChild, 0);

 

 

return 0;

 

 

case IDM_EXIT: // Выход из программы

 

 

SendMessage(hwnd, WM_CLOSE, 0, 0);


– 89 –

 

 

return 0;

 

 

//Сообщения о сортироке окон

 

 

case IDM_TILE :

 

 

SendMessage(hwndClient, WM_MDITILE, 0, 0);

 

 

return 0;

 

 

case IDM_CASCADE :

 

 

SendMessage(hwndClient, WM_MDICASCADE, 0, 0);

 

 

return 0;

 

 

case IDM_ARRANGE :

 

 

SendMessage(hwndClient, WM_MDIICONARRANGE, 0, 0);

 

 

return 0;

 

 

case IDM_CLOSEALL : // Закрыть все дочерние окна

 

 

EnumChildWindows(hwndClient,& CloseEnumProc, 0);

 

 

return 0;

 

 

default :

 

 

hwndChild =(HWND) SendMessage(hwndClient, WM_MDIGETACTIVE, 0, 0);

 

 

if(IsWindow(hwndChild))

 

 

SendMessage(hwndChild, WM_COMMAND, wParam, lParam);

 

 

break; // ...and then to DefFrameProc

 

 

}

 

 

break;

 

 

case WM_QUERYENDSESSION:

 

 

case WM_CLOSE: // Attempt to close all children

 

 

SendMessage(hwnd, WM_COMMAND, IDM_CLOSEALL, 0);

 

 

if(NULL != GetWindow(hwndClient, GW_CHILD))

 

 

return 0;

 

 

break;

 

 

case WM_DESTROY :


 

 

PostQuitMessage(0);

 

 

return 0;

 

 

}

 

 

// Использоваие DefFrameProc(not вместо DefWindowProc

 

 

return DefFrameProc(hwnd, hwndClient, iMsg, wParam, lParam);

 

 

}

 

 

// Функция закрытия окон

 

 

BOOL CALLBACK CloseEnumProc(HWND hwnd, LPARAM lParam)

 

 

{

 

 

if(GetWindow(hwnd, GW_OWNER)) return 1;

 

 

SendMessage(GetParent(hwnd), WM_MDIRESTORE,(WPARAM) hwnd, 0);

 

 

if(!SendMessage(hwnd, WM_QUERYENDSESSION, 0, 0)) return 1;

 

 

SendMessage(GetParent(hwnd), WM_MDIDESTROY,(WPARAM) hwnd, 0);

 

 

return 1;

 

 

}

 

 

// Оконная процедура первого окна

 

 

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

 

 

{

 

 

static COLORREF clrTextArray[] = { RGB(0, 0, 0), RGB(255, 0, 0),

 

 

RGB(0, 255, 0), RGB( 0, 0, 255),

 

 

RGB(255, 255, 255) };

 

 

static HWND hwndClient, hwndFrame;

 

 

HDC hdc;

 

 

HMENU hMenu;

 

 

LPHELLODATA lpHelloData;

 

 

PAINTSTRUCT ps;


– 91 –

 

 

RECT rect;

 

 

switch(iMsg)

 

 

{

 

 

case WM_CREATE :

 

 

// Save some window handles

 

 

hwndClient = GetParent(hwnd);

 

 

hwndFrame = GetParent(hwndClient);

 

 

return 0;

 

 

case WM_PAINT :

 

 

// Рисование

 

 

hdc = BeginPaint(hwnd, &ps);

 

 

GetClientRect(hwnd,& rect);

 

 

DrawText(hdc, " Привет , Мир !", -1, &rect, DT_SINGLELINE | DT_CENTER | DT_VCENTER);

 

 

EndPaint(hwnd,& ps);

 

 

return 0;

 

 

case WM_MDIACTIVATE :

 

 

// Установка нового меню

 

 

if(lParam ==(LPARAM) hwnd)

 

 

SendMessage(hwndClient, WM_MDISETMENU,

 

 

(WPARAM) hMenuHello,(LPARAM) hMenuHelloWindow);

 

 

DrawMenuBar(hwndFrame);

 

 

return 0;

 

 

case WM_QUERYENDSESSION :

 

 

case WM_CLOSE :

 

 

if(IDOK != MessageBox(hwnd, "OK to close window?", "Hello",

 

 

MB_ICONQUESTION | MB_OKCANCEL))

 

 

return 0;

 

 

break;


 

 

case WM_DESTROY :

 

 

return 0;

 

 

}

 

 

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

 

 

}

 

 

// Оконная процедура второго дочернего окна

 

 

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

 

 

{

 

 

static HWND hwndClient, hwndFrame;

 

 

HBRUSH hBrush;

 

 

HDC hdc;

 

 

LPRECTDATA lpRectData;

 

 

PAINTSTRUCT ps;

 

 

int xLeft, xRight, yTop, yBottom;

 

 

short nRed, nGreen, nBlue;

 

 

switch(iMsg)

 

 

{

 

 

case WM_CREATE :

 

 

// Save some window handles

 

 

hwndClient = GetParent(hwnd);

 

 

hwndFrame = GetParent(hwndClient);

 

 

return 0;

 

 

case WM_PAINT : // Рисование

 

 

hdc = BeginPaint(hwnd, &ps);

 

 

Rectangle(hdc,10,10,200,200);

 

 

EndPaint(hwnd,& ps);

 

 

return 0;


– 93 –

 

 

case WM_MDIACTIVATE : // Установка меню.

 

 

if(lParam ==(LPARAM) hwnd)

 

 

SendMessage(hwndClient, WM_MDISETMENU,(WPARAM) hMenuRect,

 

 

(LPARAM) hMenuRectWindow);

 

 

else

 

 

SendMessage(hwndClient, WM_MDISETMENU,(WPARAM) hMenuInit,

 

 

(LPARAM) hMenuInitWindow);

 

 

DrawMenuBar(hwndFrame);

 

 

return 0;

 

 

case WM_DESTROY :

 

 

return 0;

 

 

}

 

 

// Пересылка необработанных сообщений в DefMDIChildProc

 

 

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

 

 

}

 

 

Рис . 11.2 Текст программы MDIDEMO

 

 

Программа MDIDEMO поддерживает два типа предельно простых окон документов: в одном в центре рабочей области выводится фраза "Hello, World!", а во втором отображается прямоугольник. С каждым из этих двух типов окон документов связано свое меню.

 

 

Три меню

 

 

Начнем анализ программы с файла описания ресурсов MDIDEMO.RC. В нем определяются три шаблона меню, используемые в программе. Программа выводит на экран меню MdiMenuInit при отсутствии окон документов. Это меню просто позволяет создать новый документ или завершить программу. Меню MdiMenuHello связано с окном документа, в котором выводится фраза "Hello, World!". Подменю File позволяет открыть новый документ любого типа, закрыть активный документ и завершить программу. В подменю Window имеются опции для упорядочивания окон документов в каскадном или мозаичном виде, упорядочивания значков документов и закрытия всех окон. В этом подменю также имеется список всех открытых окон документов.

 

 

Меню MdiMenuRect связано с документом с прямоугольником. В заголовочном файле MDIDEMO.Н все идентификаторы меню определяются как три константы:

 

 

#define INIT_MENU_POS 0


 

 

#define HELLO_MENU_POS 2

 

 

#define RECT_MENU_POS 1

 

 

Эти идентификаторы задают положение подменю Window в каждом из трех шаблонов меню. Эта информация необходима программе, чтобы информировать окно -клиент о том , когда должен появиться список документов. Конечно, в меню MdiMenuInit нет подменю Window, поэтому в файле обозначено, что список должен быть присоединен к первому подменю. Однако, фактически здесь список никогда не появится. ( он нужен станет ясно при дальнейшем анализе программы .)

 

 

Идентификатор IDM_FIRSTCHILD не соответствует ни одному пункту меню. Этот идентификатор будет связан с первым окном документа в списке, который появляется в подменю Window. Значение этого идентификатора должно быть больше, чем значение всех остальных идентификаторов меню.

 

 








Дата добавления: 2016-11-22; просмотров: 471;


Поиск по сайту:

При помощи поиска вы сможете найти нужную вам информацию.

Поделитесь с друзьями:

Если вам перенёс пользу информационный материал, или помог в учебе – поделитесь этим сайтом с друзьями и знакомыми.
helpiks.org - Хелпикс.Орг - 2014-2024 год. Материал сайта представляется для ознакомительного и учебного использования. | Поддержка
Генерация страницы за: 0.392 сек.