- •ВВЕДЕНИЕ
- •1. ОБЩАЯ СТРУКТУРА ПРИЛОЖЕНИЯ WINDOWS
- •1.1. Главная функция WinMain()
- •1.2. Класс окна и его характеристики
- •1.3. Создание и показ окна
- •1.4. Обработка сообщений
- •1.5. Оконная функция
- •1.6. Сообщения Windows
- •1.7. Создание приложения с главным окном
- •1.7.1. Окна сообщений
- •1.7.2. Вывод текстовых строк
- •1.7.3. Атрибуты цвета и фона выводимого текста
- •1.7.4. Приложение с главным окном
- •2. МЕНЮ
- •2.1. Организация и виды меню
- •2.2. Приложение с главным окном и меню
- •3. ЭЛЕМЕНТЫ УПРАВЛЕНИЯ ОБЩЕГО ПОЛЬЗОВАНИЯ
- •3.1. Панель инструментов
- •3.1.1. Приложение с главным меню и панелью инструментов
- •3.2. Строка состояния
- •Библиографический список
Значения параметра uFlags (полный список см. в MSDN):
∙MF_POPUP – создается всплывающее меню;
∙MFS_CHECKED – помещается отметка рядом с пунктом ме-
ню;
∙MFS_DEFAULT – пункт меню, применяемый по умолча-
нию;
∙MFS_GRAYED – пункт меню выделяется серым цветом и
запрещается его выбор;
∙MFS_HILITE – пункт меню высвечивается;
∙MFT_STRING – пункт меню отображается с использовани-
ем текстовой строки.
Функция DestroyMenu уничтожает меню, созданное с при- менением файла ресурса, или меню, созданное в теле программы с помощью функций CreateMenu и CreatePopupMenu. По за-
вершении приложения будет уничтожено только одно меню, под- ключенное к окну приложения. Меню, не подключенные в данный момент к окну, останутся в памяти, поэтому функция
DestroyMenu должна обязательно применяться в приложениях с несколькими меню. Прототип функции DestroyMenu:
BOOL DestroyMenu(HMENU hMenu);
2.2. Приложение с главным окном и меню
/*Операторы препроцессора*/ #define STRICT
#include <windows.h> #include <windowsx.h>
/*Прототип оконной функции, используемый в программе*/
LRESULT WINAPI WndProc(HWND,UINT,WPARAM,LPARAM); #define ID_FILE_TEST 0
#define ID_FILE_EXIT 1 #define ID_HELP_ABOUT 2
/*Дескрипторы всплывающих меню и дескриптор главного меню*/
HMENU hFileMenu,hHelpMenu,hMenu; /*Главная функция WinMain*/
int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE, LPSTR lpCmdLine, int nCmdShow)
{
54
/* Произвольное имя класса */ char szClassName[]="qwerty";
//или LPCTSTR lpszClassName="qwerty"; /* Произвольный заголовок окна */ char szAppTitle[]="BGTU";
//или LPCTSTR lpszAppName="BGTU"; /*
Cтруктурная переменная wc типа WNDCLASSEX для задания характеристик окна
*/
WNDCLASSEX wc;
HWND hWnd; //дескриптор окна
/*
Структурная переменная Msg типа MSG для получения сообщений Windows
*/
MSG Msg;
/*Проверяем, было ли это приложение запущено ранее*/
if(hWnd=FindWindow(szClassName, NULL))
{
/*Поверяем, было ли это окно свернуто в пиктограмму */
if(IsIconic(hWnd)) ShowWindow(hWnd,SW_RESTORE);
/*Выдвигаем окно приложения на передний план*/
SetForegroundWindow(hWnd); return FALSE;
}
/*Регистрируем класс главного окна*/ memset(&wc,0,sizeof(wc)); wc.cbSize=sizeof(WNDCLASSEX); /*Стандартная пиктограмма*/ wc.hIcon =
(HICON)LoadImage(hInstance,IDI_APPLICATION, IMAGE_ICON,32,32,0);
/*Стандартный курсор мыши*/ wc.hCursor=LoadCursor(NULL, IDC_ARROW); wc.style = CS_HREDRAW|CS_VREDRAW;
/*Определяем оконную процедуру для главного окна*/
wc.lpfnWndProc = (WNDPROC)WndProc; wc.cbClsExtra = 0;
55
wc.cbWndExtra = 0; wc.hInstance=hInstance;//дескриптор приложения wc.hIconSm=NULL;
/*Определяем кисть фона и ее цвет*/ wc.hbrBackground=(HBRUSH)GetStockObject(
WHITE_BRUSH); //или макрос-GetStockBrush(WHITE_BRUSH) //или (HBRUSH)(COLOR_APPWORKSPACE+1)
wc.lpszClassName=szClassName; if(!RegisterClassEx(&wc)) return FALSE; /*Создаем главное окно*/ hWnd=CreateWindowEx(WS_EX_WINDOWEDGE,
szClassName,
szAppTitle, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT,10, CW_USEDEFAULT,100, HWND_DESKTOP,
NULL,
hInstance,
NULL); if(!hWnd)return FALSE;
/*
Пересылаем содержимое сегментных регистров кода, данных и стека в переменные Reg1,Reg2 и Reg3
*/
char szTxt[80];
USHORT Reg1, Reg2, Reg3; __asm{
mov Reg1,CS mov Reg2,DS mov Reg3,SS
}
/*
Выводим окно сообщений со значениями сегментных регистров, смещения (адреса) главной функции и смещения(адреса) строки с именем класса
*/
wsprintf(szTxt,"CS=%XDS=%XSS=%X\nWinMain=%X\n szClassName=%X",Reg1, Reg2, Reg3, WinMain, szClassName);
MessageBox(hWnd, szTxt, "Регистры", MB_ICONINFORMATION);
/*
56
Создаем пустое всплывающее меню самого низкого уровня hFileMenu=CreatePopupMenu() и добавляем в него конечный элемент "Test"
*/
AppendMenu((hFileMenu = CreatePopupMenu()), MF_ENABLED|MFT_STRING, ID_FILE_TEST,"&Test");
/*Добавляем в созданное меню конечный элемент
"Exit"*/ AppendMenu(hFileMenu,MF_GRAYED|MFT_STRING,
ID_FILE_EXIT,"E&xit");
/*
Создаем пустое меню самого низкого уровня (hHelpMenu)и добавляем в него конечный элемент
"About"
*/
AppendMenu((hHelpMenu=CreatePopupMenu()), MF_GRAYED|MFT_STRING, ID_HELP_ABOUT,"&About");
/*
Создаем меню верхнего уровня - главное меню hMenu=CreateMenu();и присоединяем созданное подменю "File" к главному меню
*/
AppendMenu(hMenu=CreateMenu(), MF_ENABLED|MF_POPUP, (UINT)hFileMenu,"&File");
/*Присоединяем созданное подменю "Help" к главному меню*/ AppendMenu(hMenu,MF_ENABLED|MF_POPUP,
(UINT)hHelpMenu,"&Help"); /*Добавляем в конец главного меню конечный пункт
"Quit"*/ AppendMenu(hMenu,MF_GRAYED,(UINT)11,"QUIT"); /*Присоединяем созданное меню к окну приложения*/
SetMenu(hWnd,hMenu);
/*Делаем главное окно видимым на экране*/ ShowWindow(hWnd,SW_SHOWNORMAL);
/*
Функця UpdateWindow() вызывает передачу сообщения WM_PAINT непосредственно оконной процедуре, а функция InvalidateRect() вызывает постановку
57
сообщения WM_PAINT в очередь приложения, которое там обрабатывается с самым низким приоритетом
*/
UpdateWindow(hWnd); /*Отображаем меню*/ DrawMenuBar(hWnd);
/*Цикл обработки сообщений*/ while(GetMessage(&Msg,NULL,0,0))
{
TranslateMessage(&Msg);
DispatchMessage(&Msg);
}
return Msg.wParam;//Код возврата
}
/*Оконная функция главного окна*/
LRESULT CALLBACK WndProc(HWND hWnd,UINT msg, WPARAM wParam,LPARAM lParam)
{
HDC hDc; PAINTSTRUCT ps; RECT rect;
UINT width,height;
/*Строка текста для вывода в главное окно*/ LPCTSTR lpszTxt="Б Г Т У";
switch(msg)
{
/*Переход по значению кода сообщения(msg)*/
case WM_CREATE: /*
Здесь можно произвести модификацию класса окна, например,
SetClassLong(hWnd, GCL_HBRBACKGROUND, (LONG)CreateSolidBrush(RGB(200,160,255)); */ //…
return TRUE; case WM_KEYDOWN:
/*
Обрабатываем сообщение нажатие клавиши
*/
switch(wParam)
{
58
/*Клавиша Esc*/ case VK_ESCAPE:
/*
Посылаем сообщение WM_CLOSE окну (hWnd), после того, как оконная процедура обработает это сообщение, система передаст управление инструкции следующей за SendMessage
*/ SendMessage(hWnd,WM_CLOSE,0,0); break;
}
break;
case WM_COMMAND: switch(wParam)
{
case ID_FILE_TEST: /*Изменяем статус пункта меню
ID_FILE_EXIT */
EnableMenuItem(hFileMenu,ID_FILE_EXIT, MF_BYCOMMAND|MF_ENABLED);
/*Ставим отметку на пункте меню
ID_FILE_TEST*/ CheckMenuItem(hFileMenu,
ID_FILE_TEST, MF_BYCOMMAND|MF_CHECKED);
/*Изменяем статус пункта главного меню
"QUIT"*/
EnableMenuItem(GetMenu(hWnd), (UINT)11,MF_BYCOMMAND|MF_ENABLED);
/*
Так как изменился статус пункта главного меню, вызываем функцию
DrawMenuBar для повторного отображения изменившейся полосы меню
*/
DrawMenuBar(hWnd);
break;
case ID_FILE_EXIT: /*
Без запроса на закрытие окна - функция PostQuitMessage посылает сообще-
ние WM_QUIT
59
*/
PostQuitMessage(0);
/*
С запросом на закрытие, т.е. окно еще не разрушено
SendMessage(hWnd,WM_CLOSE,0,0); */
break;
case ID_HELP_ABOUT: //...
break;
case (UINT)11: //...
/*
Без запроса на закрытие окна - функ-
ция PostQuitMessage посылает сообщение WM_QUIT
*/
PostQuitMessage(0);
break;
}
break; case WM_PAINT:
/*Получаем контекст устройства*/ hDc=BeginPaint(hWnd,&ps);
/*
Определяем размеры клиентской области окна
*/
GetClientRect(hWnd,&rect);
/*
TRANSPARENT - в этом режиме вывода текста цвет фона графического элемента игнорируется, т.е. символ выводится на существующем фоне.
*/
SetBkMode(hDc,TRANSPARENT); DrawText(hDc,lpszTxt,-1,&rect,
DT_SINGLELINE|DT_CENTER|DT_VCENTER); /*Освобождаем контекст устройства*/ EndPaint(hWnd,&ps);
break; case WM_CLOSE:
/*
60
Сообщение появляется при щелчке на кнопке закрытия окна - здесь предназначено для вывода пре-
дупреждающего сообщения
*/
if(MessageBox(hWnd,"Вы уверены???","",
MB_YESNO | MB_ICONQUESTION)== IDYES) DestroyWindow(hWnd);
break; case WM_SIZE:
/*
Ширина width и высота height клиентской области окна в пикселях
*/
width=LOWORD(lParam);
height=HIWORD(lParam);
//…
break;
case WM_LBUTTONDOWN: /*нажата клавиша Shift ?*/ if(wParam & MK_SHIFT)
{
MessageBox(hWnd,"Нажата клавиша\nShift", "Shift,Ctrl", MB_ICONINFORMATION);
}
break;
case WM_DESTROY: PostQuitMessage(0);
/*PostQuitMessage() выполняет только одно действие - ставит в очередь сообщение WM_QUIT. Параметр у этой функции - код возврата, который помещается в wParam
*/
break;
default:
/*Обработка прочих сообщений по умолчанию*/
return DefWindowProc(hWnd, msg,wParam,lParam);
}
return 0L;
}
61