Проектирование программы Текстовый Редактор Блокнот
Введение
программа блокнот панель меню
Язык C был изобретён и реализован Дэнисом Ритчи
в операционной системе Unix. Этот язык был разработан на основе более старого
языка BCPL, созданного в своё время Мартином Ричардсом. В свою очередь развитие
языка B привело к созданию в 1970 году языка C. Стандарт ANSI был окончательно
принят в декабре 1989 года и впервые опубликован в начале 1990 года. Этот
стандарт был окончательно принят организацией ISO.
Любая программа на C состоит из одной или
нескольких функций. Функции в C служат для реализации отдельных исполнителей.
Обязательно должна быть определена единственная главная функция main, именно с
неё начинается выполнение программы. Именно она выполняет всю работу, обращаясь
при необходимости к другим функциям. Язык Си разрабатывался как замена или
дополнение языка Assembler` а для задач системного программирования. На этом
языке была написана первая мультиплатформенная ОС UNIX.
1. Необходимое программное обеспечение
В качестве программного обеспечения используется
студия Microsoft Visual C++ 6.0, стандартная виндоузовская программа Paint, а
также программа Help&Manual для создания файла справки.
. Основные файлы, используемые в проекте
.cpp - основной файл программы;.res - файл
ресурсов;.h - заголовочный файл ресурсов;.bmp - графический файл, изображающий
панель для меню второго уровня;.hlp - файл справки о программе.
. Проектирование программы
Сначала программа Текстовый Редактор Блокнот
проектируется на листе бумаги.
Первый этап проектирования программы. Нужно
продумать, из каких компонентов будет состоять программа. Окно должно иметь три
основные кнопки и иметь возможность изменяться в размере. Также основными
компонентами окна должны быть: строка заголовка, меню верхнего уровня, панель
инструментов для меню второго уровня и статусная панель.
Рисунок 1.
Чтобы создать меню верхнего уровня, нужно его
тоже спроектировать на листе бумаги и тщательно продумать, какой пункт меню
какие подпункты должен содержать и нарисовать схему меню. Пункт с названием
"О программе" тоже должен быть но для простоты его действие не
прописывается.
Второй этап проектирования программы. Нужно
продумать и нарисовать программу со всеми составляющими её компонентами,
включая меню второго уровня с пиктограммами (Сохранить, открыть и печать),
статусную панель и саму рабочую область, в качестве которой используется
элемент richedit. Макет этой программы приведён на рисунке 3.
Рисунок 2.
Рисунок 3.
В первую очередь программно создаётся само окно.
Для этого нужно подключить библиотеку windows.h и объявить главную функцию
программы WinMain() а также оконную функцию WndProc(). Эта функция также
называется оконной процедурой. Она связана с циклом обработки сообщений через
обратный вызов CALLBACK. Любая программа начинается писаться с функции WinMain,
то есть с основной функции программы под Microsoft Windows. Для более простых
компиляторов она имеет структуру WINAPI. Функция начинается с объявления
структуры типа класса WNDCLASS, создания переменной w и её инициализации. Затем
для более подробного описания окна через эту переменную нужное число раз
вызываются поля (методы класса) и этим методам присваиваются нужные значения.
После описания окна через функцию ветвления происходит регистрация окна с
возвращением значения 1, а иначе - 0. Затем после инициализации нужно функцией
CreateWindow создавать как само окно, так и все дочерние окна. Функция
CreateWindow имеет такие параметры как класс окна, заголовок окна, константы
для подробного описания окна через логический оператор ИЛИ, координаты окна по
осям x и y относительно точки находящейся в верхнем углу слева, размеры окна
(длину и ширину), взаимосвязи с дочерними окнами, если они имеются и главный
дескриптор окна hInstance а также редко используемые параметры.
Затем нужно отобразить окно при помощи функции
ShowWindow и по необходимости его обновить (функция UpdateWindow), но для этого
нужно осуществить проверку через функцию ветвления if(), создано ли окно. Если
окно не создано, то функция возвращает нулевое значение. После отображения окна
в программе идёт главный цикл обработки сообщений (MessageLoop). В этом цикле
содержится функция GetMessage, которая считывает сообщение, в pамках диапазона
фильтpации, из очеpеди сообщений пpикладной задачи и оставляет упpавление
дpугим пpикладным задачам, если сообщений нет или если следующим сообщением
является WM_PAINT или WM_TIMER. Она имеет параметры: Msg: пpинимающая стpуктуpа
TMsg, Wnd: Окно назначения сообщений или 0 для всех окон в пpикладной задаче.
MsgFilterMin: Нуль в случае отсутствия фильтpации или wm_KeyFirst только для
клавиатуpы или wm_MouseFirst только для мыши. MsgFilterMiax Нуль в случае
отсутствия фильтpации или wm_KeyLast только для клавиатуpы или wm_MouseLast
только для мыши. Также в основном цикле программы содержится функция
TranslateMessage для перевода комбинаций сообщений и перенаправления их в
очередь сообщений (громадный switch) и функция DispatchMessage для
осуществления всех взаимосвязей между двумя основными функциями программы.
Основная функция программы должна возвращать значение msg.wParam, то есть
младшее слово Windows-сообщений. Затем идёт функция WndProc. Она при помощи
функции обратного вызова CALLBACK взаимосвязана с циклом обработки сообщений и
имеет структуру LRESULT. Основным содержимым этой функции является очередь
сообщений. Метки case можно писать в любом порядке. Основными метками являются
метки связанные с закрытием окна WM_CLOSE и WM_DESTROY. В метке default
jgbcsdftncz любое сообщение, которое не обрабатывает оконная процедура. Оно
отправляется на обработку в функцию DefWindowProc.
Далее создаётся меню верхнего уровня, то есть
основное меню программы. Для наипростейшего создания этого меню в первую
очередь нужно объявить константы в качестве глобальных констант, а также все
глобальные переменные типа HMENU. Затем функцию CreatePopupMenu необходимо
присвоить переменным самого меню, например hFileMenu. Далее в самой очереди
сообщений прописывается сами элементы меню с помощью функции AppendMenu() через
ветвление if. Также нужно присоединить меню к главной панели управления и к
самому окну тоже при помощи функции AppendMenu(). Класс UNDO предназначен для
пункта меню Отмена, он прописывается в качестве глобальной переменной. Этот
класс называется стеком.
После создания меню верхнего уровня создаётся
статусная панель. Для её создания объявляются переменные двух типов HWND и UINT
и правильного закрепления, то есть чтобы она могла менять размеры в зависимости
от изменения размеров окна как вручную, так и автоматически. Так же для
создания этой панели нужно подключить библиотеку commctrl.h и написать функцию
hStatusWindow типа HWND. Затем переменной hStatusWindow присваивается функция с
названием CreateStatusWindow создающая эту панель и конструкция if:
hStatusWindow =
CreateStatusWindow(WS_CHILD|WS_VISIBLE,"Блокнот
Ярослава",hWnd,
wld);(!hStatusWindow)
{(NULL,"Cannot create
window","Error",MB_OK);
return 0;
}
На следующем этапе создаются акселераторы, то
есть "горячие" клавиши. Для этого нужно создать переменные типа
HACCEL и ACCEL, а также в цикле обработки прописать своего рода конструкцию, то
есть if(!TranslateAccelerator(hWnd,hAccel,&Msg)), а также все функции для
работы с акселераторами.
Для более полного описания функции работы с
акселераторами используется следующая структура:
TBBUTTON buttons[3] =
{
{0,IDP_Save,
TBSTATE_ENABLED,TBSTYLE_BUTTON, 0, NULL},
{1,IDP_Open,
TBSTATE_ENABLED,TBSTYLE_BUTTON, 0, NULL},
{2,IDP_Print,TBSTATE_ENABLED,TBSTYLE_BUTTON,
0, NULL}
};=CreateToolbarEx(hWnd,
WS_CHILD|WS_VISIBLE|TBSTYLE_TOOLTIPS,
, 3, hInstance, IDB_BITMAP1,
buttons, 3, 22, 22, 20, 20, sizeof(TBBUTTON));
Далее нужно к меню верхнего уровня присоединить
меню второго уровня. Для этого нужно панель управления для данного меню
прорисовать в программе PAINT и создать файл с названием toolbar.bmp.
Она присоединяется при помощи специального файла
ресурсов "resource.h", структуры MAKEINRESOURE и других функций.
Также она описывается следующей структурой:
icx;
icx.dwICC
= ICC_BAR_CLASSES;
icx.dwSize =
sizeof(icx);(&icx);(!toolbar2)
{(NULL,"Cannot create toolbar
window","Error",MB_OK);
return 0;
}
Самым важным этапом в проектировании программы
является создание основного элемента управления, то есть самого текстового
поля. Для этого необходимо подключить библиотеку richedit.h а также подключить
специальную lib-библиотеку. В шестой студии она называется Msftedit.dll. Также
нужна константа с названием _RICHEDIT_VER 0x0200. Она объявляется через
ключевое слово #define. Окно для редактирования считается дочерним окном для
программы и создаётся при помощи функции, но с названием CreateWindowExW и
присваивается переменной edit.
edit = CreateWindowExW
(WS_EX_CLIENTEDGE,
L"RICHEDIT50W","",WS_VISIBLE|WS_CHILD|ES_MULTILINE, 10, 10,
300, 300, hWnd, (HMENU)10,, NULL);
…(!edit)
{(hWnd,"e","e",MB_OK);
return 0;
}
Затем нужно прописать само меню верхнего уровня
в метках case. Оно прописывается в самой оконной процедуре, то есть в очереди
сообщений. Чтобы прописать метку, имеющую название созданной константы,
необходимо сначала создать метку с названием WM_COMMAND и в неё вставить
отдельный switch с параметром LOWORD(wparam) и в нём прописывать
метки-константы для меню верхнего уровня. Метка IDM_Enable_Disable переключает
меню выход, метки case IDP_Open и IDP_Save предназначены для открытия и
сохранения текстового файла, метка IDP_Print соответственно для распечатки
документов. В меню "Правка" входят такие метки как: IDP_Undo,
IDP_Cut, IDP_Copy, IDP_Paste и IDP_Find. В меню "Вставка" входят
следующие метки: IDP_Datetime, IDP_Symbol, IDP_Alpha, IDP_Sigma=19 и IDP_Omega.
В меню "Формат" входит метка IDP_Font, а в меню "Справка" -
IDP_Help. Метка WM_Notifi используется в качестве вспомогательной метки для
отмены действия а также она взаимосвязана с классом Undo.
. Описание меню верхнего уровня
Для того, чтобы прописать все подпункты меню
верхнего уровня, нужно в первую очередь создать конструкцию с меткой
WM_COMMAND, имеющую вид:
…WM_COMMAND:
{(LOWORD(wParam))
{
// Все метки меню и подменю
… … …
}
}
…
Каждое меню или подменю описывается в своей
метке case.
Меню Файл.
Это меню состоит из пунктов: Открыть, Сохранить,
Печать, Включить/выключить выход, Выход.
Каждый подпункт меню описывается соответствующим
классом, встроенным в саму библиотеку данного компилятора
case IDP_Open: {
//Открытие
файлаfilename[300];[0]
= 0;of;.lStructSize = sizeof(of);.hwndOwner = hWnd;.hInstance =
hInst;.lpstrFilter = "texts files\0*.txt\0\0";.lpstrCustomFilter =
NULL;.nMaxCustFilter = 0;.nFilterIndex = 1;.lpstrFile = filename;.nMaxFile =
sizeof(filename);.lpstrFileTitle = NULL;.nMaxFileTitle = 0;.lpstrInitialDir =
NULL;.lpstrTitle = "Открытие
файла";.Flags
= OFN_FILEMUSTEXIST;.lpstrDefExt = "bmp";.lCustData = 0;.lpfnHook =
NULL;.lpTemplateName = NULL;result=GetOpenFileName(&of);(!result)
{(hWnd,"Error","Ошибка",MB_OK);;
}f;.open(filename);.seekg(0,
f.end);size = f.tellg();.seekg(0, f.beg);* m = new char [size];.read(m,
size);(edit, m);(edit);m;
};IDP_Save:();;IDP_Print:
{(hWnd,"Print Error",
"Не
выдаёт
печать",
MB_OK);
break;
}
//Вывод тестового текста на принтер
HDC hdc = print_dlg.hDC;di = {
sizeof(di) };.lpszDocName = "qqq.txt";
//Подключение
к
RichEdit(hdc,&di);(edit,EM_SETTARGETDEVICE,(WPARAM)hdc,0);(hdc);(edit,EM_SETSEL,0,-1);
// Выделить
всёfr;.hdc=hdc;.hdcTarget
= hdc;.rcPage.left=0;.rcPage.right=100;.rcPage.top = 0;.rcPage.bottom =
100;(edit,EM_EXGETSEL,0,(LPARAM)&fr.chrg);(edit,EM_FORMATRANGE,TRUE,(LPARAM)&fr);(hdc);(hdc);
};IDM_Exit:(hWnd,WM_CLOSE,NULL,NULL);;IDM_Enable_Disable:(hFileMenu,IDM_Exit,MF_BYCOMMAND
|
nFlag);=(nFlag==MF_ENABLED)?MF_GRAYED:MF_ENABLED;=(nIndex==0)?1:0;(hFileMenu,IDM_Enable_Disable,MF_BYCOMMAND|_STRING,IDM_Enable_Disable,pContent[nIndex]);
break;
Меню Правка. Это меню состоит из подпунктов:
Отменить, Вырезать, Копировать, Вставить, Найти. Для отмены последнего действия
используется класс Undo, который называется стеком. Метка IDP_Undo ссылается на
этот класс через указатель-ссылку.
case IDP_Undo:
{* m = undo.removecopy();(edit,
m);(edit);[] m;
};IDP_Cut:
SendMessage(edit,WM_CUT,0,0);;IDP_Copy:
SendMessage(edit,WM_COPY,0,0);;IDP_Paste:
SendMessage(edit,WM_PASTE,0,0);;IDP_Find:
{.hInstance=hInst;.lStructSize=sizeof(find);.hwndOwner=hWnd;.Flags=FR_DOWN|FR_NOMATCHCASE;.lpstrFindWhat=str;.wFindWhatLen=200;.lpstrReplaceWith=NULL;.wReplaceWithLen=0;.lCustData=0;.lpfnHook=NULL;.lpTemplateName=NULL;=FindText(&find);
};
Меню Вставка. Это меню состоит из основных
пунктов: Дата и время и Символ. Пункт "Символ" состоит из трёх
подпунктов, которые по отдельности прописываются в очереди сообщений
(IDP_Alpha, IDP_Sigma, IDP_Omega). Таймер в данной программе используется для
самой вставки даты и времени.
case IDP_Datetime:
{size = GetWindowTextLength(edit);*
m = new char [size + 100];(edit, m, size + 1);_t rawtime;tm *
timeinfo;(&rawtime);= localtime(&rawtime);*
txt=asctime(timeinfo);(m+size, txt);
//SendMessage(edit,WM_SETTEXT,(WPARAM)txt,0);(edit,
m);[] m;
};IDP_Alpha:
//Вставка символа "Альфа"
{cr;.cpMin=-1;.cpMax=-1;
//Становится
в
конец
Richedit(edit,EM_EXSETSEL,0,(LPARAM)&cr);_t str[] =
L"0x0391";(edit,EM_REPLACESEL,0,(LPARAM)str);
};IDP_Sigma:
//Вставка
символа
"Сигма"
break;IDP_Omega:
//Вставка символа "Омега";
Меню Формат. Это меню состоит из одного пункта
Шрифт, то есть IDP_Font. Это меню состоит из двух основных структур -
логического и встроенного шрифтов (т.е. LOGFONT и CHOOSEFONT), а также из
множества функций для работы со шрифтом. В качестве справочника, для этих целей
используется сайт с названием msdn.microsoft.com.
case IDP_Font:
{lf;cf;.lStructSize=sizeof(cf);.hwndOwner=hWnd;.lpLogFont=&lf;.Flags=CF_EFFECTS|CF_SCREENFONTS;.hInstance=0;result=ChooseFont(&cf);(!result)
{(hWnd,"E","E",MB_OK);;
}
{=CreateFontIndirect(&lf);
textcolor = cf.rgbColors;
//Размер выделения для всего текста
CHARRANGE cr;.cpMin = 0;.cpMax =
-1;(edit, EM_EXSETSEL, 0,
(LPARAM)&cr);cf2;.cbSize=sizeof(cf2);.dwMask=CFM_COLOR|CFM_FACE|CFM_ITALIC|CFE_BOLD;.dwEffects
= cf.lpLogFont->lfItalic ? CFE_ITALIC : 0;.dwEffects |=
cf.lpLogFont->lfWeight >= 300 ? CFE_BOLD : 0;.yHeight = 20;.yOffset =
10;(cf2.szFaceName, cf.lpLogFont->lfFaceName);.crTextColor=cf.rgbColors;res
= SendMessage(edit, EM_SETCHARFORMAT,_SELECTION,(LPARAM)&cf2);(res ==
0)(hWnd, "qqqq", "qq", MB_OK);
//SendMessage(edit, WM_SETFONT,
(WPARAM)font, TRUE);
}
};
Меню Справка. Для простоты решения задачи,
проектируется меню содержащее только один пункт с названием Вызов справки.
Второй пункт в данном проекте не используется. Пункт "Вызов справки"
описан следующим образом:
case
IDP_Help:(hWnd,"myhelp.hlp", HELP_CONTENTS, 0);
break;
Для описания всех вложенных меню используется
следующая конструкция:
case
WM_MENUSELECT:(((UINT)HIWORD(wParam)==0xffff)&((HMENU)lParam==0))
{(hStatusWindow,SB_SETTEXT,(WPARAM)0,
(LPARAM)pMessages[5]);0;
}((UINT)HIWORD(wParam)&MF_SYSMENU)
{(hStatusWindow,SB_SETTEXT,(WPARAM)0,
(LPARAM)pMessages[6]);0;
}((UINT)HIWORD(wParam)&MF_POPUP)
{(hStatusWindow,SB_SETTEXT,(WPARAM)0,
(LPARAM)pMessages[3+LOWORD(wParam)]);0;
}(hStatusWindow, SB_SETTEXT,
(WPARAM)0, (LPARAM)pMessages [LOWORD(wParam)]);
return 0;
//Описывается контекстное менюWM_RBUTTONDOWN:
{hMenu1=CreatePopupMenu();(hMenu1,
MFT_STRING, IDP_All, "&Выделить
всё");(hMenu1,
MFT_SEPARATOR, 0, NULL);(hMenu1, MFT_STRING, IDM_Exit, "&Выход");(hMenu1,
TPM_RIGHTBUTTON | TPM_TOPALIGN| TPM_LEFTALIGN,(lParam), HIWORD(lParam), 0,
hWnd, NULL);(hMenu1);
};
. Листинг
программы
// Программа
БЛОКНОТ
#define _RICHEDIT_VER 0x0200
#include <windows.h>
#include <richedit.h>
#include <iostream.h>
#include <fstream.h>
#include <commctrl.h>
#include <time.h>
#include <stdlib.h>
//Библиотека <commctrl.h> создаётся для
создания строки состояния
#include "resource.h"
//Для создания шрифта используются следующие
константыfont;
//Для поиска текстаpoisk; //Хэндл диалога поиска
//Для создания меню нужно объявить следующие
константы
const
IDM_Enable_Disable=0;IDM_Exit=1;IDM_About=2;IDP_File=3;IDP_Help=4;IDP_Open=5;IDP_Save=6;IDP_Print=7;IDP_Undo=8;IDP_Cut=9;IDP_Copy=10;IDP_Paste=11;IDP_Datetime=12;IDP_Symbol=13;IDP_Font=14;IDP_All=15;IDP_Find=16;IDP_Alpha=17;IDP_Sigma=18;IDP_Omega=19;
//Объявляется массив для комментариев в нижней
строке состояния* pMessages[] =
{
"Включить или отключить выход",
"Выйти из программы",
"О программе",
"Меню Файл",
"","","","","","","","","","","",
"Меню Правка",
"Меню Вставка",
"Меню Формат",
"Меню Справка",
"Пустой блокнот. Написал Алексей",
};
//Глобальная переменная для состояния
//документа (для закрытия окна)change=FALSE;
LRESULT CALLBACK WndProc (HWND,UINT,
WPARAM, LPARAM);
//Для команды "Отмена" объявляется
этот классUndo
{:* stack_u[10]; // на 10 действий назад массив
будет хранитьnumber;//сколько проделано действий
//Объявляется конструктор()
{ number=0;}
//Добавление новой копииaddcopy(char *copy);
char * removecopy();
};Undo::addcopy(char *copy)
{(number == 10)
{[] stack_u[0];(int i=1;
i<number; i++) {_u[i-1] = stack_u[i];
}-;
}_u[number] = copy;++;
}
* Undo::removecopy()
{(number == 0)
{"";
}
//Откатить счётчик последних действий на единицу
number--;stack_u[number];
}undo;hStatusWindow; //Переменная для создания
строки состоянияtoolbar2;wld=2; //Переменная для строки состояния
HMENU
hMenu,hFileMenu,hPravkaMenu,hPasteMenu,hFormatMenu,hHelpMenu;hInst;edit;hWnd;
//Для пункта меню "Включить/отключить
віход"
RECT Rect;UINT nFlag=MF_ENABLED;
char* pContent[] =
{
"Включить выход", "Отключить
выход"
};UINT nIndex=0;
//static HBITMAP
hBitmap;nDimension;WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,
LPSTR lpszCmdParam, int nCmdShow)
{WndClass={0};Msg;=hInstance;.style=CS_HREDRAW|CS_VREDRAW;.lpfnWndProc=
WndProc;.cbClsExtra=0;.cbWndExtra=0;.hInstance=hInstance;.hIcon=NULL;.hCursor=NULL;.hbrBackground=(HBRUSH)GetStockObject(WHITE_BRUSH);.lpszMenuName=NULL;.lpszClassName="MenuExample";(!RegisterClass(&WndClass))
{(NULL,"Cannot register
class","Error",MB_OK);0;
}_msg=RegisterWindowMessage(FINDMSGSTRING);=CreateWindow("MenuExample","Блокнот
Ярослава",_OVERLAPPEDWINDOW,
CW_USEDEFAULT,_USEDEFAULT,500,300,,NULL,hInstance,NULL);(!hWnd)
{(NULL,"Cannot create
window","Error",MB_OK);0;
}(hWnd,nCmdShow);(hWnd);
//Окно для редактирования
//В зависимости от версии большое текстовой поле
называется по-разному
LoadLibrary("Msftedit.dll");=CreateWindowExW(WS_EX_CLIENTEDGE,L"RICHEDIT50W","",WS_VISIBLE|WS_CHILD|
ES_MULTILINE,10, 10,
,
300,hWnd,(HMENU)10,hInstance,NULL);(!edit)
{(hWnd,"e","e",MB_OK);0;
}
//Создание
второй
панели
инструментовicx;.dwICC
= ICC_BAR_CLASSES;.dwSize = sizeof(icx);(&icx);buttons[3] =
{
{0,IDP_Save,
TBSTATE_ENABLED,TBSTYLE_BUTTON, 0, NULL},
{1,IDP_Open,
TBSTATE_ENABLED,TBSTYLE_BUTTON, 0, NULL},
{2,IDP_Print,TBSTATE_ENABLED,TBSTYLE_BUTTON,
0, NULL}
};=CreateToolbarEx(hWnd,WS_CHILD|WS_VISIBLE|TBSTYLE_TOOLTIPS,103,3,hInstance,IDB_BITMAP1,buttons,3,22,22,20,20,sizeof(TBBUTTON));(!toolbar2)
{(NULL,"Cannot create toolbar
window","Error",MB_OK);0;
}();=CreateStatusWindow(WS_CHILD|WS_VISIBLE,"Блокнот
Ярослава",hWnd,wld);(!hStatusWindow)
{(NULL,"Cannot create
window","Error",MB_OK);0;
}
//Описывается
меню
File=CreatePopupMenu();(hFileMenu)
{
//IDP_Save(hFileMenu,MF_ENABLED|MF_STRING,IDP_Open,"&Открыть");(hFileMenu,MF_ENABLED|MF_STRING,IDP_Save,"&Сохранить");(hFileMenu,
MFT_SEPARATOR, 0, NULL);(hFileMenu,MF_ENABLED|MF_STRING,IDP_Print,"&Печать");(hFileMenu,
MF_ENABLED|MF_STRING, IDM_Enable_Disable,
}
//Описывается
меню
Правка=CreatePopupMenu();(hPravkaMenu)
{(hPravkaMenu,MF_ENABLED|MF_STRING,IDP_Undo,"&Отменить");(hPravkaMenu,MF_ENABLED|MF_STRING,IDP_Cut,"&Вырезать");(hPravkaMenu,MF_ENABLED|MF_STRING,IDP_Copy,"&Копировать");(hPravkaMenu,MF_ENABLED|MF_STRING,IDP_Paste,"&Вставить");(hPravkaMenu,MF_ENABLED|MF_STRING,IDP_Find,"&Найти");
}
//Описывается
меню
Вставка=
CreatePopupMenu();(hPasteMenu)
{(hPasteMenu, MF_ENABLED|MF_STRING,
IDP_Datetime,
"&Дата
и
время");symbol_menu=CreatePopupMenu();(symbol_menu,MF_ENABLED|MF_STRING,IDP_Alpha,"ALPHA");(symbol_menu,MF_ENABLED|MF_STRING,IDP_Sigma,"SIGMA");(symbol_menu,MF_ENABLED|MF_STRING,IDP_Omega,"OMEGA");(hPasteMenu,
MF_ENABLED|MF_POPUP,
(DWORD)symbol_menu,"Символ");
}
//Описывается меню Формат=CreatePopupMenu();(hFormatMenu)
{(hFormatMenu,MF_ENABLED|MF_STRING,
IDP_Font,"&Шрифт");
}
//Описывается
меню
Help=CreatePopupMenu();(hHelpMenu)
{(hHelpMenu,MF_ENABLED|MF_STRING,IDP_Help,"&Вызов
справки");(hHelpMenu,
MFT_SEPARATOR, 0, NULL);(hHelpMenu,MF_ENABLED|MF_STRING,IDM_About,"&О
программе");
}
//Функцию CreateMenu() обязательно нужно
присвоить этой переменной=CreateMenu();
//Присоединяется меню к главной панели
управления и к окну
AppendMenu(hMenu,MF_ENABLED|MF_POPUP,
(DWORD)hFileMenu,"&Файл");(hMenu,MF_ENABLED|MF_POPUP,
(DWORD)hPravkaMenu,"&Правка");(hMenu,MF_ENABLED|MF_POPUP,
(DWORD)hPasteMenu,"&Вставка");(hMenu,MF_ENABLED|MF_POPUP,
(DWORD)hFormatMenu,"&Формат");(hMenu,MF_ENABLED|MF_POPUP,
(DWORD)hHelpMenu,"&Справка");(hWnd,hMenu);
//Загрузка
акселераторовactable[]
=
{
{ FCONTROL|FVIRTKEY, 0x53, IDP_Save
},
{ FALT|FVIRTKEY, 0x50, IDP_Print }
};hAccel=CreateAcceleratorTable(actable,
2);(!hAccel)
{(hWnd,"E","E",MB_OK);
}=GetSystemMetrics(SM_CYMENU);(hWnd,nCmdShow);(hWnd);(GetMessage(&Msg,NULL,0,0))
{(!TranslateAccelerator(hWnd,hAccel,&Msg))
{(&Msg);(&Msg);
}
}Msg.wParam;
}x;y;nWidth;nHeight;*lpszChar;hdc;
// контекст
устройстваtextcolor;Save()
{
//Сохранение
файлаfilename_s[300];_s[0]
= 0;of;.lStructSize = sizeof(of);.hwndOwner = hWnd;.hInstance =
hInst;.lpstrFilter = "texts files\0*.txt\0\0";.lpstrCustomFilter =
NULL;.nMaxCustFilter = 0;.nFilterIndex = 1;.lpstrFile = filename_s;.nMaxFile =
sizeof(filename_s);.lpstrFileTitle = NULL;.nMaxFileTitle = 0;.lpstrInitialDir =
NULL;.lpstrTitle = "Сохранение
файла";.Flags
= OFN_FILEMUSTEXIST;.lpstrDefExt = "bmp";.lCustData = 0;.lpfnHook =
NULL;.lpTemplateName = NULL;result=GetSaveFileName(&of);fout;.open(filename_s,ios::out|ios::binary);(!fout)
{(hWnd,"Error","Открыть
не
удалось",MB_OK);;
}f;.open(filename_s);size =
GetWindowTextLength(edit);* m = new char [size];(edit, m, size);.write(m,
size);m;.close();
}CALLBACK WndProc (HWND hWnd,UINT
Message,WPARAM wParam,LPARAM lParam)
{
//Для
поиска(Message==find_msg)
{(find.Flags & FR_FINDNEXT)
//Выделяется найденное слово
/*FINDTEXT ft;
ft.lpstrText=str;.chrg.cpMin=0;.chrg.cpMax=-1;(edit,EM_FINDTEXT,FR_DOWN,&ft);*/0;
}(Message)
{WM_CREATE:0;WM_COMMAND:(LOWORD(wParam))
{IDM_Enable_Disable:(hFileMenu,IDM_Exit,MF_BYCOMMAND
|
nFlag);=(nFlag==MF_ENABLED)?MF_GRAYED:MF_ENABLED;=(nIndex==0)?1:0;(hFileMenu,IDM_Enable_Disable,MF_BYCOMMAND|MF_STRING,IDM_Enable_Disable,[nIndex]);;IDP_Open:
{
//Открытие
файлаfilename[300];[0]
= 0;of;.lStructSize = sizeof(of);.hwndOwner = hWnd;.hInstance =
hInst;.lpstrFilter = "texts files\0*.txt\0\0";.lpstrCustomFilter =
NULL;.nMaxCustFilter = 0;.nFilterIndex = 1;.lpstrFile = filename;.nMaxFile =
sizeof(filename);.lpstrFileTitle = NULL;.nMaxFileTitle = 0;.lpstrInitialDir =
NULL;.lpstrTitle = "Открытие
файла";.Flags
= OFN_FILEMUSTEXIST;.lpstrDefExt = "bmp";.lCustData = 0;.lpfnHook =
NULL;.lpTemplateName = NULL;result=GetOpenFileName(&of);(!result)
{(hWnd,"Error","Ошибка",MB_OK);;
}f;.open(filename);.seekg(0,
f.end);size = f.tellg();.seekg(0, f.beg);* m = new char [size];.read(m,
size);(edit, m);(edit);m;
};IDP_Save:();;IDP_Undo:
{* m = undo.removecopy();(edit,
m);(edit);[] m;
};IDP_Print:
{print_dlg = {0};_dlg.lStructSize =
sizeof(print_dlg);_dlg.Flags =
PD_RETURNDC;result=PrintDlg(&print_dlg);(!result)
{(hWnd,"Print Error",
"Не
выдаёт
печать",
MB_OK);
break;
}
//Вывод тестового текста на принтер
HDC hdc = print_dlg.hDC;di = {
sizeof(di) };.lpszDocName = "qqq.txt";
//Подключение
к
RichEdit(hdc,&di);(edit,EM_SETTARGETDEVICE,(WPARAM)hdc,0);(hdc);
//Выделить
всё(edit,EM_SETSEL,0,-1);fr;.hdc=hdc;.hdcTarget
= hdc;.rcPage.left=0;.rcPage.right=100;.rcPage.top = 0;.rcPage.bottom =
100;(edit,EM_EXGETSEL,0,(LPARAM)&fr.chrg);(edit,EM_FORMATRANGE,TRUE,(LPARAM)&fr);(hdc);(hdc);
};IDM_Exit:(hWnd,WM_CLOSE,NULL,NULL);;IDP_Cut:(edit,WM_CUT,0,0);;IDP_Copy:(edit,WM_COPY,0,0);;IDP_Paste:(edit,WM_PASTE,0,0);;IDP_Find:
{.hInstance=hInst;.lStructSize=sizeof(find);.hwndOwner=hWnd;.Flags=FR_DOWN|FR_NOMATCHCASE;.lpstrFindWhat=str;.wFindWhatLen=200;.lpstrReplaceWith=NULL;.wReplaceWithLen=0;.lCustData=0;.lpfnHook=NULL;.lpTemplateName=NULL;=FindText(&find);
};IDP_Font:
{lf;cf;.lStructSize=sizeof(cf);.hwndOwner=hWnd;.lpLogFont=&lf;.Flags=CF_EFFECTS|CF_SCREENFONTS;.hInstance=0;result=ChooseFont(&cf);(!result)
{(hWnd,"E","E",MB_OK);;
}
{=CreateFontIndirect(&lf);
textcolor = cf.rgbColors;
//Размер выделения для всего текста
CHARRANGE cr;.cpMin = 0;.cpMax =
-1;(edit, EM_EXSETSEL, 0, (LPARAM)&cr);cf2;.cbSize=sizeof(cf2);.dwMask=CFM_COLOR|CFM_FACE|CFM_ITALIC|CFE_BOLD;.dwEffects
= cf.lpLogFont->lfItalic ? CFE_ITALIC : 0;.dwEffects |=
cf.lpLogFont->lfWeight >= 300 ? CFE_BOLD : 0;.yHeight = 20;.yOffset =
10;(cf2.szFaceName, cf.lpLogFont->lfFaceName);.crTextColor=cf.rgbColors;res
= SendMessage(edit,EM_SETCHARFORMAT,SCF_SELECTION,(LPARAM)&cf2);(res ==
0)(hWnd, "qqqq", "qq", MB_OK);
//SendMessage(edit, WM_SETFONT,
(WPARAM)font, TRUE);
};IDP_Datetime:
{size = GetWindowTextLength(edit);*
m = new char [size + 100];(edit, m, size + 1);_t rawtime;tm *
timeinfo;(&rawtime);= localtime(&rawtime);*
txt=asctime(timeinfo);(m+size, txt);
//SendMessage(edit,WM_SETTEXT,(WPARAM)txt,0);(edit,
m);[] m;
};IDP_Alpha:
//Вставка символа "Альфа"
{cr;.cpMin=-1;.cpMax=-1;
//Становится
в
конец
Richedit(edit,EM_EXSETSEL,0,(LPARAM)&cr);_t str[] =
L"0x0391";(edit,EM_REPLACESEL,0,(LPARAM)str);
};IDP_Sigma:
//Вставка
символа
"Сигма"
break;IDP_Omega:
//Вставка символа "Омега"
break;IDP_Help:(hWnd,"myhelp.hlp",
HELP_CONTENTS, 0);;:
return
DefWindowProc(hWnd,Message,wParam,lParam);
}0;WM_SIZE:(edit,0,0,25,LOWORD(lParam),HIWORD(lParam)-25-20,0);(edit);(hStatusWindow,
Message, wParam,
lParam);;WM_MENUSELECT:(((UINT)HIWORD(wParam)==0xffff)&((HMENU)lParam==0))
{(hStatusWindow,SB_SETTEXT,(WPARAM)0,
(LPARAM)pMessages[5]);0;
}
//
??((UINT)HIWORD(wParam)&MF_SYSMENU)
{(hStatusWindow,SB_SETTEXT,(WPARAM)0,
(LPARAM)pMessages[6]);0;
}((UINT)HIWORD(wParam)&MF_POPUP)
{(hStatusWindow,SB_SETTEXT,(WPARAM)0,
(LPARAM)pMessages[3+LOWORD(wParam)]);0;
}(hStatusWindow,SB_SETTEXT,(WPARAM)0,(LPARAM)pMessages[LOWORD(wParam)]);
return 0;
//Описывается контекстное менюWM_RBUTTONDOWN:
{hMenu1=CreatePopupMenu();(hMenu1,
MFT_STRING, IDP_All, "&Выделить
всё");(hMenu1,
MFT_SEPARATOR, 0, NULL);(hMenu1, MFT_STRING, IDM_Exit, "&Выход");(hMenu1,
TPM_RIGHTBUTTON | TPM_TOPALIGN| TPM_LEFTALIGN,(lParam), HIWORD(lParam), 0,
hWnd, NULL);
DestroyMenu(hMenu1);
};
//Уведомление об изменении
case WM_NOTIFY:
{size = GetWindowTextLength(edit);*
m = new char [size+1];(edit, m, size);[size] = 0;.addcopy(m);= TRUE;
};WM_CLOSE:
{(change)
{
int res = MessageBox(hWnd,"Cохранить
изменения в документе?",
"Cохранение
документа",MB_YESNO);(res==IDYES)
Save();
}
}DefWindowProc(hWnd,Message,wParam,lParam);WM_DESTROY:(0);0;:DefWindowProc(hWnd,Message,wParam,lParam);
}0;
}
Литература
1.
П.В. Румянцев. Азбука программирования в Win32 API.
.
П.В. Румянцев. Работа с файлами в Win32 API.
.
К.Г. Финогенов. Win32 Основы программирования.
.
Джеффри Ріхтер. Создание эффективных Win32 приложений.
.
Джефф Элджер. Библиотека программиста.
.
Герберт Шилдт. С++ Базовый курс.
.
Т.А. Павловская, Ю.А. Щупак С++ Объектно-ориентированное программирование.
.
Msdn.microsoft.com - основной сайт для решения сложных задач по
программированию.
9.
<http://www.ixbt.com/soft/help-and-manual.shtml> - ссылка для создания
файлов справки.