for(int i=0;i<80;i++)
CDialog::OnOK();
void CMyDialog::OnCancel()
CDialog::OnCancel();
Після цього відбувається передача даних із ЕК у змінні-властивості класу діалогу згідно з DDX-макросами методу DoDataExchange().
void CMyDialog::DoDataExchange(CDataExchange* pDX)
CDialog::DoDataExchange(pDX);
DDX_Control(pDX, IDC_EDIT1, edit1);
DDX_Control – покажчик на об’єкт класу елементаму керування.
Якщо введені дані не потрібно зберігати або обробляти, тоді діалогове вікно закривається натисненням кнопки Cancel[1]. Введені за допомогою діалогового вікна дані далі можуть бути використані в функціях інших класів програми. Діалогове вікно даної програми зображене на рисунку 11.
Рисунок 11 – Діалог для введення даних
В функції OnInitDialog() проведено початкову ініціалізацію для поля edit1, а саме за допомогою методу SetWindowText(CString("0")) значення, яке може вводитись користувачем, в даному випадку початкове значення 0.
За допомогою функції GetWindowText данні з поля Edit зчитуються в змінні типу char – str. Потім за допомогою функції atof перетворюються в дані типу float.
Аналогічно створювалось інше діалогове вікно, в якому виводилась інформація про розробника програми. Зовнішній вигляд показано на рис. 12.
Рисунок 12 – Зовнішній вигляд діалогу при натисканні на кнопку «Info»
6. РЕАЛІЗАЦІЯ МАТЕМАТИЧНОЇ ФУНКЦІЇ МОВОЮ ASSEMBLER
При програмуванні математичного співпроцесора може бути використано або програмування співпроцесора для роботи з числами з фіксованою комою, або програмування співпроцесора – з числами з плаваючою комою. В даній програмі використовується програмування співпроцесора для роботи з плаваючою комою. Він має вісім регістрів, які організовані у вигляді стека.(рисунок 13)[8].
Рисунок 13 – Організація стека математичного співпроцесора
Основні команди, що використовуються при програмуванні:
- Finit – команда ініціалізації;
- Fcom src – порівняти значення першого регістру з другим;
- Fld src – завантажити регістр;
- Fst dst – зберегти значення у регістр;
- Fadd dst, src – додати до першого регістра другий;
- Fmul dst, src – помножити перший регістр на другий і зберегти результат в першому;
- Fdiv dst, src – поділити перший регістр на другий і зберегти результат в першому[6].
Всі данні необхідні для обчислення, ініціалізація програми, та вивід данних здійснюється за допомогою C++:
Розглянемо частину коду яка виконує обчислення коли х=4:
_asm
{
FINIT;
FLDE;//ST(6)
FLD D;//ST(5)
FLD A;//ST(4)
FLD B;//ST(3)
FLD C;//ST(2)
FLD X;//ST(1)
FLD Y;//ST(0)
FADD ST(0),ST(1);//Y=X
FMUL ST(0),ST(4);//Y=X*A
FXCH ST(5);//D=A*X
FADD ST(0),ST(1);//Y=X
FMUL ST(0),ST(3);//Y=X*B
FXCH ST(6);//E=X*B
FADD ST(0),ST(3);//Y=B
FMUL ST(0),ST(4);//Y=A*B
FADD ST(0),ST(5);//Y=A*X+A*B
FSUB ST(0),ST(6);//Y=A*X+A*B-B*X
FSTY; вивантажуємо ST(0) в Y
};
7. СТВОРЕННЯ ТА ПІДКЛЮЧЕННЯ БІБЛІОТЕКИ DLL
Бібліотеки DLL – це програмний код або дані, які динамічно доступні всім процесам операційної системи[5].
Динамічне завантаження DLL дозволяє програмі визначити, яка з бібліотек і коли буде завантажуватись, а також задати дію при невдалому завантаженні бібліотеки. Спочатку необхідно помістити модуль бібліотеки в пам’ять процесу. Дана операція виконується за допомогою функції LoadLibrary(), що має один аргумент – ім'я завантажуваного модуля.
HINSTANCE hDll;
hDll=::LoadLibrary("MandroDLL");
Опрацювання помилки завантаження DLL та повідомлення про помилку:
if (LoadLibrary("MandroDLL ") == NULL)
MessageBox("Cannot find or open file MandroDLL ");
Стандартним розширення ім’я бібліотеки вважається .dll, якщо не вказувати інше. Так як в імені файлу вказано лише його назву, то цей файл повинен знаходитись в одному каталозі з основним файлом типу *.exe. Для визначення адрес окремих функцій всередині бібліотеки використовується функція GetProcAddress():
FUN func;
func=(FUN)::GetProcAddress(hDll,"calc");
Для вивантаження бібліотеки з пам'ятті процесу використовується функція FreeLibrary().
Для створення самої бібліотеки DLL був створений новий проект типу Win32 Dynamic-Link Library та вибраний перемикач Simply DLL.
В результаті було автоматично створено файл, що містить функцію DllMain(), яка є одночасно і функцією входу, і функцією виходу:
BOOL APIENTRY DllMain( HANDLE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
return TRUE;
}
Далі у файлі бібліотеки DLL описана експортована функція. Дана функція має повертати значення змінної «Y». Для цього слід функцію main() замінити на функцію, ім'я якої ми використовуємо для визначення адрес:
float Calc(float X)
Експортованій функції з головної програми передається операнди типу float.
Слід записати, що буде повернуто до основної програми:
return Y;
Ім’я експортованої функції потрібно вказати в окремому файлі визначень (файл типу *.def)[1]. Цей файл необхідно приєднати до проекту.
В текстовому редакторі в цьому файлі набрати текст файлу визначень:
LIBRARY "MandroDLL"
DESCRIPTION 'This library has one function'
EXPORTS
calc @1
У файлі визначень вказується ім’я експортованої функції та її номер, по якому функцію теж можна викликати[1].
Скомпільований файл необхідно скопіювати до каталогу, в якому знаходиться основна програма.
Лістинг бібліотеки наведено в Додатку Б.
8. ОСНОВНІ ОПЕРАЦІЇ НАД ФАЙЛАМИ
8.1 Відкриття файлу
Клас CFileDialog забезпечує створення і функціонування двох діалогових вікон, що використовуються для відкриття та збереження файлів[11].
Для відкриття файлу використовується конструктор класу:
CFileDialog dlgOpen(TRUE, "txt","", OFN_HIDEREADONLY, "Text file (*.txt)| *.txt| ALL Files(*.*)|*.*|", this); Діалогове вікно, що відкриває текстовий файл на рис. 14.
Рисунок 14 – Діалогове вікно «Открыть»
Для створення об’єкта Windows потрібно використати метод DoModal з наступним прототипом:
virtual int DoModal();
Цей метод повертає значення IDOK або IDCANCEL, в залежності від того, які кнопки були натиснуті при закриті діалогового вікна[4]. Коли файл відкривається на читання, його режим також повинен бути вказанним на читання:
CFile::modeRead|CFile::typeBinary);
Для виведення данних відкриваємого файлу створено цикл, в якому виділяється необхідна кількість рядків для тексту.
dc.SetTextColor(RGB(255,0,0));
while(File.ReadString(m_Text))
dc.TextOut(10,0,Text,Text.GetLength());
OpenWnd -> UpdateWindow();
File.Close();
Завдяки функції file.ReadString(m_Text); відбувається зчитування файлу. dc.SetTextColor(RGB(255,0,0)); – вказує стиль, в якому буде виведено на екран текст. Діалогове вікно, що відображає вміст файлу з даними для обчислення на рис. 15.
Рисунок 15 – Діалогове вікно «Відкрити файл»
8.2 Збереження файлу
Якщо змінити в конструкторі класу TRUE на FALSE, то отримається конструктор класу для збереження файлу[11]:
CFile DialogDlgSave(FALSE,"txt","",OFN_HIDEREADONLY,"Text file (*.txt)|*.txt| All Files(*.*)|*.*|",this);
де OFN_HIDEREADONLY – знімає прапорець Read-Only;
OFN_CREATEPROMPT – дозволяє створення неіснуючих файлів.
Діалогове вікно, що зберігає результати виконання програми в текстовий файл на рис. 16.
Рисунок 16 – Діалогове вікно «Сохранить как»
Для запису даних використовується наступна конструкція:
CStdioFile file(DlgSaveAs.GetPathName(),
CFile::modeCreate|CFile::modeWrite);
Функція GetPathName()повертає ім’я вибраного файла та шлях. modeWrite– довзоляє створювати файл на запис.
В данній програмі відбувається збереження результату обчислення в тектсовому файлі. Це реалізується за допомогою:
CString string=”Результат обрахувань програми:";
string+=s;
File.WriteString(LPCSTR(string));
Завдяки функції File.WriteString(LPCSTR(string) відбувається запис до файлу.
Результати виконання програми зберігаються в текстовий файл, як показано на рис. 17.
Рисунок 17 – Діалогове вікно, що відображає вміст файлу
9. ВИВЕДЕННЯ РЕЗУЛЬТАТІВ ОБЧИСЛЕНЬ
9.1 Числове виведення результату
Числовий результат роботи програми виводиться у окремому вікні. Для цього був створений новий клас CTextWnd:
class CTextWnd:public CFrameWnd
public:
CTextWnd(CWnd *wnd);
Для створення нового вікна використовується метод Create:
CTextWnd::CTextWnd(CWnd *WndParent)
CRect rect(200,200,500,500);
Create (NULL,"Текстовий результат", WS_OVERLAPPEDWINDOW, rect, WndParent, NULL);
Власне виведення результату описане в функції OnResult ()(рисунок 18):
CClientDC DC(TextWnd);
DC.SetTextColor(RGB(13,66,6));
Виконуємо виведення результату за допомогою функції TextOut.
DC.TextOut(125,125,s,strlen(s));
Рисунок 18 – Діалогове вікно числового виведення результату
9.2 Графічне виведення результату
Для всіх пристроїв графічного виведення використовуються одні і ті ж самі функції і класи, а вибір конкретного пристрою система виконує самостійно на основі інформації про контекст пристрою. Особливістю бібліотеки MFC є те, що вона містить спеціальні класи контекстів пристроїв. Базовим класом для всіх контекстів пристроїв є клас CDC. Існує також ще декілька класів контекстів пристроїв, що мають більш вузьку спеціалізацію. Я використовував CClientDC, що являє собою клас контексту пристрою для забезпечення доступу до клієнтської (робочої) області вікна. При створенні об’єкта цього класу в конструкторі викликається API-функція GetDC(), а при його знищенні в деструкторі – API-функція RealeaseDC()[7].
Для виведення результатів роботи програми у графічному вигляді було використано можливості векторної графіки.