Смекни!
smekni.com

Розробка системних обєктно-орієнтованих програм мовою С в середовищі Windows (стр. 3 из 5)

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].

Для виведення результатів роботи програми у графічному вигляді було використано можливості векторної графіки.