Автор работы: Пользователь скрыл имя, 22 Июня 2014 в 18:15, курсовая работа
Особую роль в интерпретаторе на Prolog играют конкретные запросы к базам знаний, на которые система логического программирования генерирует ответы «истина» и «ложь». Для обобщённых запросов с переменными в качестве аргументов созданная система на Prolog выводит конкретные данные в подтверждение истинности обобщённых сведений и правил вывода.
Теоретической основой Prolog является раздел символьной логики, называемый исчислением предикатов. Исчисление предикатов и логический вывод являются базой Prolog. В отличие от процедурных языков Prolog можно рассматривать как язык описаний. Используемый в Prolog подход состоит в описании известных фактов и отношений, касающихся данной задачи. Решение на Prolog следует из составленного описания.
ВВЕДЕНИЕ 5
1 АНАЛИЗ СОСТОЯНИЯ ВОПРОСА 7
1.1 Общие сведения о реестре 7
1.2 Описание разделов реестра 7
2 ПОСТАНОВКА ЗАДАЧИ 10
3 ПРОЕКТИРОВАНИЕ ПО 11
3.1 Интерфейс программы 11
3.1 Структура программы 11
4 РЕАЛИЗАЦИЯ ПО 13
4.1 Описание интерфейса программы 13
4.2 Использование переменных и функций 14
5 ТЕСТИРОВАНИЕ ПО 19
5.1 Функциональное тестирование 19
5.2 Полное тестирование 23
ВЫВОДЫ 25
СПИСОК ИСПОЛЬЗОВАННЫХ ИСТОЧНИКОВ 26
ПРИЛОЖЕНИЕ A 27
Протестируем каждое из них.
При нажатии на любой пункт меню появляется всплывающее меню выбора действия (рисунок 5.2).
Рисунок 5.2 – Демонстрация меню приложения
При нажатии на кнопку «Обновить», произойдет обновление реестра, который синхронизируется с реестром Windows. При нажатии на кнопку «Выход», произойдет выход из приложения.
Стоит отметить, что почти каждому пункту меню соответствует своя горячая клавиша.
Для выбора раздела, воспользуемся списком всех разделов и перейдем в какой-нибудь раздел (рисунок 5.3).
Рисунок 5.3 – Выбранный раздел и запись
Чтобы создать новый раздел, нужно нажать на соответсвующий пункт меню. Появится следующее окно (рисунок 5.4).
Рисунок 5.4 – Создание раздела
Вписав имя раздела, нажимает «Ок» и он создается.
Перейдем к описанию следующего пункта меню «Раздел» - «Переименовать». При нажатии на его, у нас появляется окно «Переименоваьт» (рисунок 5.5). После ввода нового имени, раздел переименовывается.
Рисунок 5.5 – Переименовать
Следующий пункт меню «Раздел» - «Удалить». При нажатии на его, появляется диалоговое окно с вопросом об удалении (рисунок 5.6).
Рисунок 5.6 – Удаление раздела
При выборе «Да», раздел удаляется, при выборе «Нет», раздел остается без изменения.
Подменю «Создать» (меню «Запись») содержит другое подменю (рисунок 5.7), опишем его.
Рисунок 5.7 – Подменю «Создать»
При нажатии на пункт «Раздел», произайдет все то же, что было описано выше для меню «Раздел-Новый». При нажатии на подменю ниже – создает запись вида «Строка» или «DWORD» (рисунок 5.8). Так как создание этих записей идентично, опишем только одну из них.
Рисунок 5.8 – Создание записи
После ввода названия и нажатия на «ОК», запись создается.
Выберем какую-нибудь запись для редактирования данных. Появляется сообщение об изменении записи (рисунок 5.9).
Рисунок 5.9 – Изменение записи
При выборе другого пункта меню появляются аналогичное меню, поэтому описывать их нет смысла.
При нажатии на подменю «Найти…» появляется окно поиска записи (рисунок 5.10)
Рисунок 5.10 – Поиск
Есть два типа поиска: по разделам и по записям. Поиск по разделам осуществляет поиск разделов, а поиск по записям осуществляет поиск по всем записям, во всех разделах.
После ввода текста для поиска и нажатия на кнопку «ОК», происходит поиск. Если запись найдена, она автоматически выделится, иначе появится сообщение об ошибке (рисунок 5.11).
Рисунок 5.11 – Сообщение о поиске
После успешного завершения функционального тестирования проведем полное тестирование. Здесь рассматриваются варианты неправильной эксплуатации программы пользователем.
При создании нового раздела пользователь должен учитывать, что раздел нельзя создать в корне.
При нажатии на пункт «Новый» появляется ошибка (рисунок 5.12).
Рисунок 5.12 – Ошибка, связанная с пунктом «Новый»
Данная ошибка появляется из-за того, что мы не выбрали раздел, в котором необходимо создать.
Рассмотрим процесс изменения записи. Следующая ошибка может возникнуть из-за того, что пользователь не выбрал запись, которую требуется изменить. Ошибка представлена на рисунке
Перейдем к следующему пункту меню «Запись» - «Изменить». Если не выбрать запись, то появляется сообщение об ошибке (рисунок 5.13).
Рисунок 5.13 – Ошибка изменения записи
На этом меню тестирование оканчивается. Все пункты меню протестированы.
Результат тестирования: Программа работает верно и никаких сбоев не было замечено.
Реестр Windows – это большая база данных, которая хранит в себе все настройки Windows. Системный реестр операционной системы Windows имеет очень важное значение в ее работе, функциональности и быстродействии.
К основным достоинствам системного реестра можно отнести следующие особенности:
1) высокая скорость чтения/
2) безопасность хранения
3) возможность защиты от
4) возможность поддерживать тысячи обращений к базе данных.
В процессе разработки данного курсового проекта были изучены и закреплены знания по работе с Microsoft Visual Studio и Visual C++, а так же WinAPI.
Тестирование данного продукта показало хорошую работоспособность и отсутствие ошибок и недочётов в программе, а также в выполнении требований задания курсового проекта.
#include <windows.h>
#include <commctrl.h>
#include "resource.h"
#define MAX_KEY_LENGTH 256
#define MAX_PATH_LENGTH 2048
LRESULT CALLBACK WindowProcedure(HWND, UINT, WPARAM, LPARAM);
BOOL CALLBACK DialogProcedureRename(HWND, UINT, WPARAM, LPARAM);
BOOL CALLBACK DialogProcedureFind(HWND, UINT, WPARAM, LPARAM);
BOOL CALLBACK DialogProcedureAbout(HWND, UINT, WPARAM, LPARAM);
HINSTANCE hInst;
HWND hTV, hLV;
char szClassName[] = "RegEdit";
char szTitleName[] = "Редактор реестра";
HTREEITEM tiRoot, tiRoots[4];
HKEY hkRoots[4] = {HKEY_CLASSES_ROOT, HKEY_CURRENT_USER, HKEY_LOCAL_MACHINE, HKEY_USERS};
HKEY ghKey;
char gszName[MAX_KEY_LENGTH] = "";
int isRename;
byte isFindNext = 0;
byte cFinded;
struct node
{
HTREEITEM hti;
node *next;
};
struct nodeStr
{
char szName[MAX_KEY_LENGTH];
nodeStr *next;
};
node *nodeList;
nodeStr *nodePath;
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
{
hInst = hInstance;
HWND hwnd;
MSG msg;
WNDCLASSEX wc;
wc.hInstance = hInstance;
wc.lpszClassName = szClassName;
wc.lpfnWndProc = WindowProcedure;
wc.style = CS_DBLCLKS;
wc.cbSize = sizeof(WNDCLASSEX);
wc.hIcon = LoadIcon(hInst, MAKEINTRESOURCE(IDI_ICON));
wc.hIconSm = LoadIcon(hInst, MAKEINTRESOURCE(IDI_ICON));
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.lpszMenuName = MAKEINTRESOURCE(IDR_MENU1);
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hbrBackground = (HBRUSH)COLOR_WINDOW;
if(!RegisterClassEx(&wc)) return 0;
hwnd = CreateWindowEx(0, szClassName, szTitleName, WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT, 750, 400, HWND_DESKTOP, NULL, hInstance, NULL);
ShowWindow(hwnd, nShowCmd);
HACCEL hAccel = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDR_ACCEL));
while(GetMessage(&msg, NULL, 0, 0))
{
if(!TranslateAccelerator(hwnd, hAccel, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
return msg.wParam;
}
bool OpenKey(HTREEITEM ti, DWORD dwType)
{
char szPath[MAX_PATH_LENGTH] = "";
char szTemp[MAX_PATH_LENGTH];
TV_ITEM tvi;
tvi.mask = TVIF_TEXT;
tvi.pszText = szTemp;
tvi.cchTextMax = MAX_KEY_LENGTH;
HTREEITEM tiTempB, tiTemp = ti;
while(!(tiRoot == (tiTempB = TreeView_GetParent(hTV, tiTemp))))
{
tvi.hItem = tiTemp;
TreeView_GetItem(hTV, &tvi);
strcat_s(szTemp, "\\");
strcat_s(szTemp, szPath);
strcpy_s(szPath, szTemp);
tiTemp = tiTempB;
}
HKEY hkRoot;
for(int i=0; i<4; i++)
{
if(tiTemp == tiRoots[i])
{
hkRoot = hkRoots[i];
break;
}
}
if(!(RegOpenKeyEx(hkRoot, szPath, 0, dwType, &ghKey) == ERROR_SUCCESS)) return false;
RegCloseKey(hkRoot);
return true;
}
bool ShowSubKeys(HTREEITEM ti)
{
node *nodeTemp = nodeList;
while(nodeTemp->next != NULL)
{
if(nodeTemp->next->hti == ti) return false;
nodeTemp = nodeTemp->next;
}
node *nodeCurrent = new node;
nodeCurrent->hti = ti;
nodeCurrent->next = NULL;
nodeTemp->next = nodeCurrent;
DWORD dwKeyCount, dwSubKeyCount;
char szName[MAX_KEY_LENGTH];
TV_INSERTSTRUCT tvIS;
HKEY hkTemp;
tvIS.item.hItem = NULL;
tvIS.item.cchTextMax = MAX_KEY_LENGTH;
tvIS.hParent = ti;
tvIS.hInsertAfter = TVI_LAST;
tvIS.item.cChildren = 1;
RegQueryInfoKey(ghKey, NULL, NULL, NULL, &dwKeyCount, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
for(int i=0; i<(int)dwKeyCount; i++)
{
RegEnumKey(ghKey, i, szName, MAX_KEY_LENGTH);
tvIS.item.pszText = szName;
tvIS.item.mask = TVIF_TEXT;
if(RegOpenKeyEx(ghKey, szName, 0, KEY_READ, &hkTemp) == ERROR_SUCCESS)
{
RegQueryInfoKey(hkTemp, NULL, NULL, NULL, &dwSubKeyCount, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
if(dwSubKeyCount) tvIS.item.mask = TVIF_TEXT|TVIF_CHILDREN;
RegCloseKey(hkTemp);
}
TreeView_InsertItem(hTV, &tvIS);
}
return true;
}
bool ShowValues()
{
ListView_DeleteAllItems(hLV);
DWORD dwValueCount, dwValueSize, dwType, dwDataSize;
LVITEM lvi;
lvi.mask = LVIF_TEXT;
char szName[MAX_KEY_LENGTH];
RegQueryInfoKey(ghKey, NULL, NULL, NULL, NULL, NULL, NULL, &dwValueCount, NULL, NULL, NULL, NULL);
for(int i=0; i<(int)dwValueCount; i++)
{
dwValueSize = MAX_KEY_LENGTH;
RegEnumValue(ghKey, i, szName, &dwValueSize, NULL, &dwType, NULL, NULL);
lvi.iItem = i;
lvi.iSubItem = 0;
lvi.pszText = szName;
ListView_InsertItem(hLV, &lvi);
lvi.iSubItem = 1;
lvi.pszText = "Unknown";
switch(dwType)
{
case REG_SZ:
{
lvi.pszText = "REG_SZ";
ListView_SetItem(hLV, &lvi);
lvi.iSubItem = 2;
dwDataSize = 1024;
char szData[1024] = "";
RegQueryValueEx(ghKey, szName, NULL, NULL, (LPBYTE)szData, &dwDataSize);
lvi.pszText = szData;
break;
}
case REG_EXPAND_SZ:
{
lvi.pszText = "REG_EXPAND_SZ";
ListView_SetItem(hLV, &lvi);
lvi.iSubItem = 2;
lvi.pszText = "Unknown";
dwDataSize = 1024;
char szData[1024];
if(RegQueryValueEx(ghKey, szName, NULL, NULL, (LPBYTE)szData, &dwDataSize) == ERROR_SUCCESS)
{
lvi.pszText = szData;
}
break;
}
case REG_MULTI_SZ:
{
lvi.pszText = "REG_MULTI_SZ";
ListView_SetItem(hLV, &lvi);
lvi.iSubItem = 2;
lvi.pszText = "Unknown";
dwDataSize = 1024;
char szData[1024];
if(RegQueryValueEx(ghKey, szName, NULL, NULL, (LPBYTE)szData, &dwDataSize) == ERROR_SUCCESS)
{
lvi.pszText = szData;
}
break;
}
case REG_DWORD:
{
lvi.pszText = "REG_DWORD";
ListView_SetItem(hLV, &lvi);
lvi.iSubItem = 2;
lvi.pszText = "Unknown";
dwDataSize = sizeof(DWORD);
DWORD dwData;
if(RegQueryValueEx(ghKey, szName, NULL, NULL, (LPBYTE)&dwData, &dwDataSize) == ERROR_SUCCESS)
{
char szBuff[16];
char szText[32];
_itoa_s(dwData, szBuff, 16);
strcpy_s(szText, "0x");
strcat_s(szText, szBuff);
strcat_s(szText, " (");
_itoa_s(dwData, szBuff, 10);
strcat_s(szText, szBuff);
strcat_s(szText, ")");
lvi.pszText = szText;
}
break;
}
case REG_QWORD:
{
lvi.pszText = "REG_QWORD";
ListView_SetItem(hLV, &lvi);
lvi.iSubItem = 2;
lvi.pszText = "Unknown";
dwDataSize = 8;
DWORD qwData[2];
if(RegQueryValueEx(ghKey, szName, NULL, NULL, (LPBYTE)&qwData, &dwDataSize) == ERROR_SUCCESS)
{
DWORD dwData = qwData[0];
char szBuff[16];
char szText[32];
_itoa_s(dwData, szBuff, 16);
strcpy_s(szText, "0x");
strcat_s(szText, szBuff);
strcat_s(szText, " (");
_itoa_s(dwData, szBuff, 10);
strcat_s(szText, szBuff);
strcat_s(szText, ")");
lvi.pszText = szText;
}
break;
}
case REG_BINARY:
{
lvi.pszText = "REG_BINARY";
ListView_SetItem(hLV, &lvi);
lvi.iSubItem = 2;
lvi.pszText = "Неизвестный тип данных";
}
}
ListView_SetItem(hLV, &lvi);
}
return true;
}
bool CreateValue(HWND hwnd, DWORD dwType)
{
HTREEITEM tiSelected;
tiSelected = TreeView_GetSelection(hTV);
if(tiSelected == tiRoot)
{
MessageBox(hwnd, "Нельзя создать запись в корневом разделе", szTitleName, MB_ICONWARNING);
return false;
}
strcpy_s(gszName, "");
isRename = false;
DialogBox(hInst, MAKEINTRESOURCE(IDD_RENAME), hwnd, DialogProcedureRename);
if(strcmp(gszName, "") != 0)
{
if(OpenKey(tiSelected, KEY_ALL_ACCESS))
{
if(RegQueryValueEx(ghKey, gszName, NULL, NULL, NULL, NULL) == ERROR_SUCCESS)
{
MessageBox(hwnd, "Запись с таким именем уже существует", szTitleName, MB_ICONERROR);
return false;
}
if(dwType == REG_DWORD)
{
DWORD dwData = 0;
RegSetValueEx(ghKey, gszName, NULL, dwType, (LPBYTE)&dwData, sizeof(DWORD));
}
if(dwType == REG_SZ) RegSetValueEx(ghKey, gszName, NULL, dwType, NULL, NULL);
RegCloseKey(ghKey);
OpenKey(tiSelected, KEY_READ);
ShowValues();
RegCloseKey(ghKey);
return true;
}
else
{
MessageBox(hwnd, "Нет прав на создание записи", szTitleName, MB_ICONERROR);
return false;
}
}
return false;
}
bool FindRegistry(HKEY hKey, char *szParentName, char *szFind, bool isKey)
{
HKEY hkTemp;
bool isFinded = false;
if(RegOpenKey(hKey, szParentName, &hkTemp) == ERROR_SUCCESS)
{
DWORD dwSubKeyCount, dwValueCount, dwValueSize;
RegQueryInfoKey(hkTemp, NULL, NULL, NULL, &dwSubKeyCount, NULL, NULL, &dwValueCount, NULL, NULL, NULL, NULL);
char szName[MAX_KEY_LENGTH];
if(!isKey)
{
for(int i=0; i<(int)dwValueCount; i++)
{
dwValueSize = MAX_KEY_LENGTH;
RegEnumValue(hkTemp, i, szName, &dwValueSize, NULL, NULL, NULL, NULL);
if(strcmp(szName, szFind) == 0)
{
cFinded++;
if(cFinded > isFindNext) isFinded = true;
break;
}
}
}
for(int i=0; i<(int)dwSubKeyCount; i++)
{
RegEnumKey(hkTemp, i, szName, MAX_KEY_LENGTH);
if(isKey)
{
if(strcmp(szName, szFind) == 0)
{
cFinded++;
if(cFinded > isFindNext)
{
isFinded = true;
nodeStr *nodeCurrent = new nodeStr;
nodeCurrent->next = nodePath;
strcpy_s(nodeCurrent->szName, szName);
nodePath = nodeCurrent;
break;
}
}
}
if(FindRegistry(hkTemp, szName, szFind, isKey))
{
isFinded = true;
nodeStr *nodeCurrent = new nodeStr;
nodeCurrent->next = nodePath;
strcpy_s(nodeCurrent->szName, szName);
nodePath = nodeCurrent;
break;
}
}
RegCloseKey(hkTemp);
}
return isFinded;
}
LRESULT CALLBACK WindowProcedure(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch(msg)
{
case WM_CREATE:
{
hTV = CreateWindowEx(0, WC_TREEVIEW, TEXT("Tree View"),
WS_VISIBLE|WS_CHILD|WS_BORDER|
0, 0, 0, 0, hwnd, NULL, hInst, NULL);
hLV = CreateWindow(WC_LISTVIEW, NULL,
WS_VISIBLE|WS_CHILD|LVS_
0, 0, 0, 0, hwnd, NULL, hInst, NULL);
LVCOLUMN lvc;
lvc.mask = LVCF_TEXT|LVCF_WIDTH;
lvc.pszText = "Название";
lvc.cx = 150;
SendMessage(hLV, LVM_INSERTCOLUMN, 0, (LPARAM)&lvc);
lvc.pszText = "Тип";
lvc.cx = 120;
SendMessage(hLV, LVM_INSERTCOLUMN, 1, (LPARAM)&lvc);
lvc.pszText = "Информация";
lvc.cx = 400;
SendMessage(hLV, LVM_INSERTCOLUMN, 2, (LPARAM)&lvc);
SendMessage(hLV, LVM_SETEXTENDEDLISTVIEWSTYLE, 0, LVS_EX_FULLROWSELECT);
SendMessage(hwnd, WM_COMMAND, ID_FILE_REFRESH, 0);
break;
}
case WM_COMMAND:
switch(LOWORD(wParam))
{
case ID_FILE_REFRESH:
{
node *nodeDelete, *nodeTemp = nodeList;
while(nodeTemp != NULL)
{
nodeDelete = nodeTemp;
nodeTemp = nodeTemp->next;
delete(nodeDelete);
}
nodeList = new node;
nodeList->hti = NULL;
nodeList->next = NULL;
nodeStr *nodeDeleteStr, *nodeTempStr = nodePath;
while(nodeTempStr != NULL)
{
nodeDeleteStr = nodeTempStr;
nodeTempStr = nodeTempStr->next;
delete(nodeDeleteStr);
}
nodePath = NULL;
TreeView_DeleteAllItems(hTV);
ListView_DeleteAllItems(hLV);
TV_INSERTSTRUCT tvIS;
tvIS.item.mask = TVIF_TEXT|TVIF_CHILDREN;
tvIS.item.hItem = NULL;
tvIS.item.pszText = "[Компьютер]";
tvIS.item.cchTextMax = MAX_KEY_LENGTH;
tvIS.item.cChildren = 1;
tvIS.hParent = TVI_ROOT;
tvIS.hInsertAfter = TVI_LAST;
tiRoot = TreeView_InsertItem(hTV, &tvIS);
tvIS.hParent = tiRoot;
tvIS.item.pszText = "HKEY_CLASSES_ROOT";
tiRoots[0] = TreeView_InsertItem(hTV, &tvIS);
tvIS.item.pszText = "HKEY_CURRENT_USER";
tiRoots[1] = TreeView_InsertItem(hTV, &tvIS);
tvIS.item.pszText = "HKEY_LOCAL_MACHINE";
tiRoots[2] = TreeView_InsertItem(hTV, &tvIS);
tvIS.item.pszText = "HKEY_USERS";
tiRoots[3] = TreeView_InsertItem(hTV, &tvIS);
TreeView_Expand(hTV, tiRoot, TVE_EXPAND);
TreeView_Select(hTV, tiRoot, TVGN_CARET);
break;
}
case ID_FILE_EXIT:
{
PostQuitMessage(0);
break;
}
case ID_KEY_NEW:
{
HTREEITEM tiSelected;
tiSelected = TreeView_GetSelection(hTV);
if(tiSelected == tiRoot)
{
MessageBox(hwnd, "Нельзя создать раздел в корне", szTitleName, MB_ICONERROR);
break;
}
if(OpenKey(tiSelected, KEY_ALL_ACCESS))
{
strcpy_s(gszName, "");
isRename = false;
DialogBox(hInst, MAKEINTRESOURCE(IDD_RENAME), hwnd, DialogProcedureRename);