1. Въведение в Windows



страница1/4
Дата21.07.2017
Размер0.77 Mb.
#26214
  1   2   3   4
1. Въведение в Windows.

BIOS драйвери - системни ср-ва в DOS:

-управление на файл;

-управление на памет;

-управление на изч. процес;

-управление на драйвери;

-обработка на грешки;

-вход/изход.

Системните ср-ва се използват само ако програмата ги вика. Също се използва функционалност от драйвери и BIOS комуникацията може да се осъществи директно, или чрез посредничеството на драйвери, BIOS. Директното е чрез директно свързване с апаратната част.

Програмна среда на windows:

Апаратна част: Win компоненти

Памет GDI

Диск Kernel

User


Драйвери на Win (display, printer, kbd).

BIOS файлова с-ма:

Windows компонентите използват драйвери или директна комуникация с апаратната част. Тези компоненти са:

- GDI- у-ва за графичната среда;

- Кernel- у-ва за изчислителния процес и паметта;

- User- у-ва за потребителски интерфейс и диалозите. Всичко минава през Windows, който менажира задачите, заявките и т.н.

Разликата между Windows и DOS е че в Windows винаги се минава през Windows за да се получи достъп навсякъде.

Особенности на ОС:

1. Вход чрез опашки и съобщения- отказваме се от DOS. Идеята е директно да извикаме ф-я или основно изчисли-телния процес да се изпълнява после-дователно. В DOS програмата лесно се проследява, но става по-трудно четима.

2. В Windows се отказваме от директно извикване, последователното изпълнение на командите във файла.

Kbd таймер мишка

А.EXE


WINDOWS B.EXE

Ако имаме приложение А.ЕХЕ, то стрелките са от къде можем да получаваме съобщения - от самата себе си, от клавиатурата, от мишката, от софтуерни таймери и т.н. Съобщението е ср-во за насочване на изчислителния процес за изпълнение на определен програмен код, който е фрагмент от програмата. Приложвнието в Windows се състои от множество фрагменти, които се изпълняват ако са изпълнени определени събития (дошли са определени съобщения). Съобщението е 1 число, което има буквен еквивалент в Windows. Има дефинирани около 150 съобщения които могат да се обработят или не. Всяко съобщение е съпътствано от параметри (поне 2). Msgто идентифицира събитието, а параметрите дават допълнителна инф за msgто. Ако msgто е свързано с промяна размера на прозореца, то някъде ще се съдържа новата инф за размерите и след това ще се прерисува. Има независимост от устройство за изходен интерфейс. Изхода обикновено е на екран, но може да е на диск, интернет, принтер. Изхода трябва да е еднакъв т.е. каквото се вижда на екрана това да излезе на принтера (примерно). Въпросът е да не се налагат промени. Ако се смени устройствения контекст (DC) в рамките на който се прави изхода, просто ще се насочи в др.посока. Мощен клас за управление в MFC е CDC (Device Context). DC предоставя служебно създадена структура от Д, в която има набор от функции чрез които могат да се настройват у-ва. Когато се направи Device Context, а то трябва да се направи преди изхода, тогава изхода се извежда към него.

Многозадачност.

В DOS няма многозадачност. Първите версии на Windows (3.0, 3.11, 95) не са многозадачни. 98 е преходен Windows. Windows NT и 2000 са многозадачни.

Характеристики на многозадачна ОС:

-Възможност за чист паралелизъм (ако хардуера го позволява) или превключване без намеса;

-Изолирани адресни пространства;

-Защити;


-Права на достъп;

-Приоритети;

-Преходи в състоянията ня процесите (отложен, блокиран и т.н.);

Правило: изчислителният процес се управлява от поток приложения и всеки процес има собствено приложение => превключване на задачи става само ако се изчерпат msgтата в опашката на 1вото, а се появят в опашката на другото msg.

Усъвършенстване управлението и извикването на файлове.

Има много механизми, които позволяват качване и сваляне на фрагменти от програмата, което позволява разширение на паметта (виртуалната памет, swap и т.н., асоциране на файл с ОП).



4. Класическа структура на Windows приложение.

Структура и методика:

Примерна програма на DOS:

#include

main()

{printf(“Hello\n”);}



Недостатъци:

1)Подразбира се изх. само на екран (не на принтер напр.);

2)Мястото на изведения текст не е фиксирано;

3)Няма ср-ва, които да гарантират еднотипното изпълнение при многократно стартиране;

4)След края на програмата на екрана остава нещо;

5)Не се поддържа мишка;

Освен това Windows приложението създава много приятни за потребителя неща:

Приложение в Windows:

1)Част от кода е стандартизиран и auto може да се генерира;

2)В средата Windows има много подкрепи. Например ако се прави текстов редактор може да се постави 1 контрола

Пример на VC++:

switch(message)

{case WM_PAINT:

hdc=BeginPaint (hwnd, &ps);

GetClientRect (hwnd, &rect);

DrawText (hdc, “Hello” , -1, &rect, DT_SINGLELINE | DT_CENTER | DT_VCENTER);

EndPaint(hwnd, &ps);

return 0;

case WM_DESTROY:

PostQuitMessage(0);

return 0; }

return DefWindowProc(hwnd, message, wParam, lParam);

В примера се обхващат и обработват само 2 съобщ. – WM_PAINT и WM_DESTROY. Има много др. съобщ., к. са генерирани. Тези, к. не са прихванати се обработват по подразбиране

1 - отключване на заглавни файлове;

2 – сигнатурата на WndProc;

3 - WinMain стартова точка/подават й се параметри. Съществуват стандарти за именоване;

4 – lpsz CmdParam параметри на командния ред;

5 – дефинират се данни Handle към прозореца;

тип Msg

typedefstruc tag Msg



{ HWND hwnd; WORD message;

WORD W Param, LONG l Param, DWORD time

В главната програма – 1ви прозорец се изпълнява само ако сме в 1во стартиране на програмата. В многозадачна среда този правоъгълник отпада.

wndclass.style = CS_HREDRAW | CS_VREDRAW ;

инициализираме полета на каса

Style – представката е Class Show. Стилът е комбинация от флагове, к. описват поведението, в случая указваме необходимост от прерисувания, винаги когато се променят хор. или вертик. Размери

hdc = BeginPaint(hwnd, &ps);

GetClientRect(hwnd, &rect);

се изпълнява(породено е от WM_PAINT, к. се поражда при промяна р-рите на прозореца)

RegisterClass(&wndclass);

регистрираме клас

hwnd = CreateWindow (szAppName, “Name of the programm” - създаване на прозорец(не визуализираме)

WS_OVERLAPPEDWINDOW, CW_USEDEFAULT,

CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, NULL); - показват размерите в началния момент. Те са по подразбиране=>целия екран

1ви-NULL-родителски прозорец;

2ри-NULL-място hwnd към меню;

3ти стилове:

ShowWindow(hwnd, nCmdShow);UpdateWindow(hwnd); - генерира Windows MessageSize(но е по подразбиране), т. е. ако бяхме нагласили код за size щеше да се изпълни.

UpdateWindow – инициализира прерисуването. Това става като отлага WindowMessagePaint

while(GetMessage(&msg, NULL, 0, 0)) – цикъл за извличане на съобщение

GetMessage - тегли поредното съобщение, от опашката евентуално го транслира и насочва. Приключва когато срещне нулево съобщение. Не може да има прекъсване в тегленето. До тук се използват стандартни ф-ии.

long FAR PASCAL WndProc(HWND, whnd, WORD message, WORD wParam, LONG lParam)

- WndProc- в нея са копирани case овете на обработваните съобщения за даден прозорец, представени от своя handle.

Приложението трябва да има две обособени части:

{HDC hdc;PAINTSTRUCT ps;RECT rect;

деф. някакви променливи от стандартен тип

Paint struct – представлява тази част от клиентската област, к. трябва да се прерисува. Всички необработени съобщения генерирани извън WM_DESTROY се прихващат по подразбиране, то е последното съобщение от веригата. Полезното съобщение е в WM_PAINT. След като ще рисуваме ! да си приготвим DC. Тoй се изразява в Paint &ps позволява там да се попълни размера на клиентската част:

DrawText(hdc, “Hello”,-1, &rect, DT_SINGLELINE | DT_CENTER | DT_VCENTER); - “-1” низа е в С и завършва с 0. Комбинацията от флагове показва опции при рисуването, EndPoint предшества прерисуването за структурата, к. сме указали

WM_PAINT

1. начално съставяне на прозорец

2. при промяна размерите на прозореца

3. при свиване на прозорец и обратно

4. при прерисуване наложено вследствие припокриване на прозореца

*Ако в опашката се оталожат повече от един WM_PAINT , обединяват се в един с с окрупнена област на прерисуване

*Invalidate –слага WM_PAINT в опашката

Validate – проверява има ли инвалидизирана област и я прерисува

-1- WinMain- състои се от три части

RegisterClass(регистрира класа),

CreateWindow(създава прозорец),

UpdateWindow(визуализира/ъпдейтва прозореца);

-2- WinProc – функция която съдържа множество swich-ове. Всяко едно приложение се състои тематично от три компонента – вход, данни и ресурси. Винаги кода е един, данните са собствени. Ресурсите са: менюта, икони, bitmap, др.

За създаване на Windows приложение е необходимо:

-1- редактор, вкойто се пише кода;

-2- компилатор, съдържащ нужните библиотеки;

-3- свързващ редактор за .obj файлове. Тези ресурси се прибавят към изходното .exe.

Особености на Windows програма. След регистрирането на класа, който съдържа параметри, програмата се развива съобразно тези параметри. Създва се прозорец (с WinProc). Към нея се подава набор съобщения. Всяко събитие трябва да се отрази с някакво съобщение (натискане на бутон, преместване на прозорец, и др.). Всяко съобщение съдържа информация кога се поражда, какви съпътстващи съобщения гопридружават. Независимо дали ни интересуват, съобщенията в опашката се извличат. Това което може да се направи за неинтересуваите ни съобщения, е в WinProc да не се предвиди опция swich за тях. (да се игнорират). Съобщенията се предхождат от WM(windows message) Съдържат два вида съпътстващи параметри: 1) wParam – word parameter – указва в какъв вид е прозореца (нормален, във вид на икона, скрит и др.) и lParam – long parameter – указва в какъв вид са новите параметри на прозореца. Някой съобщения пораждат други съобщения – получава се верига.

(например.: при натискане на бутона Close на приложение се генерират:

WM_SYSCOMMAND; WM_CLOSE,

WM_Destroy Windows;

WM_QUIT).

Тази верига се състои отмеждинни систояния, които не ни обременяват. Те дават възможност да се намесим в хода на програмата.

Windows може да генерира и съобщения от вида:

PostMessage – поставя съобщението в края на опашката; SendMessage – съобщението прескача и отива в началото на опашката – нарушава се естествения ред. Съобщенията се обработват в определен ред – следващото съобщение се изпълнява, само ако предходното е завършило. Всички функции в Windows са far Pascal.



Някой правила при програмиране в Windows:

-1- не може да се използват функции за директна комуикация с устройство;

-2- директно не се работи с паметта.

-3- не е желателно да се обменят данни директно с процесора (промяна на флаг);

-4- да се избягва работата с функциите alloc, malloc;

-5- да не се ползват стандартите функции за работа с файлове (windows има подобни).



6. Обща класиф-я на класовете в MFC среда.

1.Общи класове - това са групите класове за управление и промяна на файлове, низове, изключителни ситуации и често използвани класове.

2. Класове, които управляват видимости (меню, графични обекти, контекстни у-ва, прозорци, диалози).

3. Класове, които структурират приложение:

- класове, св. с двуслойната архитектура и техните подразделения;

-класове, св с упр-е на нишката;

-класове, св. с упр-е на блокировките;

4. Класове колекции – служат като контейнери за съхраняване и възстановяване на други обекти.

5. OLE класове.

6. Database класове – 7-8 класа свързани с обработката на структурирани данни- извличане, корекция, добавяне на записи, изкл.ситуации, SQL, изобразяване на записи.

7. Контролите- 20,30 класа.

8. Window Socket класове – тук се включват класовете за работа с клиент-сървър приложения, работа в мрежи

Структура на приложение с MFC подкрепа:

Hello.h


Class CMyApp:public SWinApp

{public: virtual BOOL InitInstance();};

class CMainWindow:public CFrameWnd

{public:CMainWindow();

protected: afx_msg void OnPaint();

DECLARE_MESSAGE_MAP()};

Hello.cpp

#include

#include “Hello.h”

CMyApp myApp; //обект на приложението- той е само един в MFC приложението и има глобална видимост

BOOL CMyApp::InitInstance() //създава обект от класа CMainWindow и копира неговия адрес в член-променливата m_pMainWnd

{m_pMainWnd=new CMainWindow;

m_pMainWnd->ShowWindow (m_nCmdShow)//показва прозорецът

m_pMainWnd-> UpdateWindow();

return TRUE;}

BEGIN_MESSAGE_MAP (CMainWindow, CFrameWnd)

ON_WM_PAINT()

END_MESSAGE_MAP()

CMainWindow::CMainWindow()

}Create (NULL,_T(“The Hello Application”));}

void CMainWindow::OnPaint()

{CPaintDC dc(this);

CRect rect;

GetClientRect(&rect);

dc.DrawText({T(“Hello”),-1,&rect, DT_SINGLELINE_CENTER);}
Към приложението:

Със ChelloApp the Application – започва програмата;

AfxWinMain е първата използвана функция. Тя е скрита и не я пишем. Тази функция вика първата функция от нашето приложение. ChelloWnd.

Всяко приложение се структурира в нов thread и няма previous instance. Тогава се стартира нов thread за приложението и се структурира нова опашка от която после се теглят съобщенията.

Следващото което се изпълнява е pMainWnd. InitIntrance създава обекти от ChelloWnd като първо изпълнява конструктора m_pMainWnd = new(HelloWnd). След коетосъздава прозореца и после го визуализира. Тук нямаме Proc функция която да насочи изчисленията. Тук това става чрез картата на съобщенията. Чрез картата на съобщенията, възникващите съобщения се насочват към обработващите ги функции. Картата на съобщенията автоматично свързва съобщението с метода. В случая: WM_PAINT с On_Paint().

CframeWnd е наследник на FrameWnd, който създава toolbar и т.н. и е от по-висока инстанция.

Create има около 10 параметъра аналози на параметрите в С++ (за Windows).

8 Методика на изгр. на работоспособно приложение във визуална среда.

Cdocument CView display printer аrchive data.

Едно изображение може да работи с множество документи, както и един документ – в много изображения.

Едно приложение във визуална среда има следните класове:

1. Документен клас (Cdocument) – в него систематизирана цялата обработка на данните.

2. Клас изображение (CView) – неговите методи са отговорни за изобразяване на данните, входа и изхода.

3. Клас Frame – това е най-голямото изображение. Това е мястото където се съдържа клиентската област на изображението

4. Клас на приложението – този клас обединява останалите и осъществява взаимодействието със средата (Windows).

С тези класове се генерират имена и файлове, к. изграждат приложението. ! да се добави код, за да стане функционална програма.

Търсим метод подходящ за CHelloView класа. Този метод ще е On Draw. Той е метод на базовия клас, вика се винаги, когато има необходимост от прерисуване

Hello World във визуална среда. Използваме метода OnDrаw:

void CHelloView::OnDraw(CDC* pDC){

CHelloDoc* pDoc = GetDocument(); //указател към документа

ASSERT_VALID(pDoc);

// добавен код

CRect rcClient;

GetClientRect( rcClient );

pDC->DrawText( "Hello World", -1, rcClient, DT_SINGLELINE|DT_CENTER |DT_VCENTER );

}

Взимаме клиентската област



GetClientRect; Попълваме я; извикваме я; компилираме и пускаме.

Курсор на мишка – изображение на мишката;

1.Създаване на курсор чрез WNDCLASS :

CString strWndClass = AfxRegisterWndClass(…,AfxGetApp() LoadStandartCursor( IDC_CROSS),……..);

//в констр. на CMainWindow…………

Create(strWndClass,…………);

// в CFrameWnd::Create() – при създаване на прозореца – рамка.

2. С API ф-ия ::SetCursor(m_hCursor);

3. Курсора да е на пясъчен часовник CWaitCursor.

pOldWnd – указател на прозорец който до сега е имал фокуса.

void CMainWindow::OnSetFocus( CWnd* pOldWnd){………}

Същото е и при OnKillFocus той ще има за параметър новия прозорец, той ще получи фокус. Това важи само за прозорци, които се намират в един и същи thread.

2. Каретка-това е тази чертичка или правоъгълниче, което показва къде ще се изпише буквата. Тя трябва да се управлява от нас.

CWnd има 7 ф-ии за работа с каретка:

CreateCaret създава я от битмап

GetCaretPos;

SetCaretPos;

ShowCaret;

HideCaret;

За разлика от изображението на мишката при каретката е локално, т. е. в рамките на прозореца;

3. Мишка-при движение на мишката WM_MOUSEMOVE . Съобщенията от мишкатасе отлагат в опашката на прозореца над която е тя, а не на фокусирания.

- При натиснат бутон: WM_LBUTTONDOWN; WM_LBUTTONUP;

WM_LBUTTONDBLCLK;

Как можем да определим кога курсор влиза и излиза от рамката на прозорец:

влизането : в опашка се отлага WM_MOUSEMOVE.В windows 98 се появи и интересна ф-ия ::TrackMouseEvent() (за да проверим можем ли да я използваме: #define _WIN32_WINNT 0x0400 ). С тази ф-ия можем да укажем приложението ( с параметър HWND) да получава съобщния WM_MOUSELEAVE и WM_MOUSEHOVER. С Track_Mouse Exent() - можем да се регистрираме не искаме да получава и информация когато мишката напусне нашият прозорец и когато мишката остава неподвижна за да направим това нещо правим #define WM_MOUSELEAVE и WM_MOUSEHOVER нямат привързване към функция т.е. трябва да предефинираме картата на съобщенията. Тези 2 съоб-я не са обвързани към ф-ии. Те са стандартни, но трябва да се редактира КС. Има и друго msg, к. се появява при движение на мишката, без да натискаме бутон. Благодарение на възможността да се капсулира потока на msgs дори ако мишката излезе от прозореца, може да се прихваща msg на мишката при излизане от прозореца. SetCapture показва, над к. прозорец е мишката.

Още едно съобщение свързано с движението на командата MOUSEWILL

Прихващане на мишка:

CWnd::SetCapture()

::ReleaseCapture()
12. Основи на вх/изх интерфейс.

1.Работа с текст.

За да се изведе текст то предварително трябва да са указани неговите характеристики. Това става чрез ползването на съответните полета в DC (Device Context). Една от характеристиките е mapping mode (режим на съответствие) също трябва да се установи. Съответствието между нашите представи и реалните се прави от mapping mode. Екрана има физ. х-ки, к. са различни, но се работи в лог. ст-сти, к. оказват координатите.

case WM_PAINT :

hdc =GetDC(hwnd);

hdc=BeginPaint(hwnd, &ps);….

графични обработки;

ReleaseDC(hwnd,hdc);

EndPaint(hwnd, &ps);

return 0;

Ето един пример извличащ размера на текущата потребителска област:

static short cxClient, cyClient;

....

case WM_SIZE: cxClient = LOWORD (lParam); cyClient = HIWORD(lParam);



За скролиране има стандартна ф-я, която ги създава и такава, която указва с едно кликване на колко позиции да се отмести.

2. Работа с текст при MFC поддръжка.

CDC поддържа ред текстови функции:

DrawText – текст в правоъгълна област.

TextOut – ред на указани координати.

ExtTextOut – ред със запълване на правоъгълника с фон и др.

GetTextExtent – изчислява ширината на низа в избрания шрифт.

GetTextMetrics – връща шрифтови размери.

SetTextAlign, SetTextColor, SetBgColor.

Шрифтът е GDI обект : В MFC той се представлява от Cfont. Най-често се създава с CreateFont() или така:

CFont font;

font.CreatePointFont(120, _T(“Times New Roman”)); // 12 пункта размер

След като създадете шрифт обекта следва да го изберете за употреба:

CPaintDC(this);

dc.SelectObjec( &font);

dc.SetBkMode(TRANSPARENT);

CString string = _T(“Hello”));

CRect rect (….);

dc.SetTextColor( RGB(192,192,192));

dc.DrawText( string, &rect, ….); Може да се създаде логически шрифт, чрез него се създават “тънки” настройки на шрифта (градуси на наклона и др.). Но с логически шр. не работят всички шр.. Bitmap шрифт не могат да са логически, а само векторните.



10 Входно/изходен И .

1.Клавиатура

При инсталация на Windows се променя клавиатурният драйвер за DOS. Изменя се принципа на реакция при натискане на клавиш. Поражда се съобщение, к. се отлага в опашката на фокусирания прозорец. Само фокусиран прозорец и опашката му поемат съобщението. Отпуснат клавиш – друго съобщ. Комбинацията на ALT+ др. клавиш отлага др. съобщ. Съпътстващите параметри дават богата инфо

case WM_KEYDOWN :

switch (wParam){

case VK_HOME: .....; //виртуален код на Home

break;

case VK_END : ...;



//виртуален код на END

break;


В case се прави анализ, за кой точно клавиш става дума:

case WM_KEYDOWN :

switch (wParam){

case VK_xxxx: SendMessage(hwnd, message,wParam,lParam);

break;

VK….хххх – ако искаме да реализираме функционална еквивалентност м/у натискане на клавиш и натискане на бутон на мишка. Програмата сама със себе си генерира в явен вид msg. Само по този начин може да се генерира кода при натискане на л. бутон



KEYDOWN е свързан с виртуални съобщения, но по лесно е да разглеждаме не вирт. код, а ASCII кода. Това прехвърляне става чрез translatemsg. Когато се извлече съобщ. KEYDOWN, транслира се в опашката, то изпълнява WM_CHAR

KEY_UP – при отпускане на клавиш

WM_KEYDOWN-виртуален код на а

WM_CHAR-ASCII код на а

WM_KEYUP-виртуален код на а

Когато се извлече WM_KEYDOWN от опашката…………………….. ще char. Тогава фрагментът обработващ клавиатура може да се промени по следният начин:

case WM_CHAR :

switch(wParam):

{case '\b': ........;

// backspace

break;

case 'n' : ........;



// буква n

break;


default: ..........

Клавиатура в 32 битова среда (допълнения):

Съобщенията се пренасочват към помощният фокус прозорец.

Промяна на фокус:WM_SETFOCUS, WM_KILLFOKUS и съответно: ON_WM_SETFOCUS, ON_WM_KILLFOKUS в картата на съобщенията.


11 Вх./изх. интерфейс.

Софтуерен таймер-периодично чрез отлагане на съобщения информира, че е изминал определен времеви интервал. При програми, които по някъкъв начин са свързани с време; в програми които периодично правят определени измервания на началната памет в компютъра; при много задания, работа, когато програмата освобождава ресурсите и да ги предоставим на други; при програми, които автоматично апериодично съхраняват данни при операции.

Ето един фрагмент от програма, дефиниращ 2 таймера:

#define TIMER_SEC 1

#define TIMER_MIN 2

.....


SetTimer(hwnd, TIMER_SEC, 1000, NULL);

SetTimer(hwnd,TIMER_MIN, 60000,NULL);

....

case WM_TIMER :



switch(wParam)

/ /съдържа идентификатор на таймер

{case TIMER_SEC :

// обработка веднаж в секунда;

break;

case TIMER_MIN :



// обработка веднаж в минута;

break;......

CALL-BACK функции

Това е функция предназначена да се вика през ОС на която може да се предават определени аргументи.Викането не става явно.Те позволяват:

- свързване с прозорец;

- да приемат за обработка съобщения;

- функционално модифицирана обикновено стандартна Арр функция;

- позволява както ние да подадем параметри, така и Windows като мине през него да допълни със стойности параметри.

Списъка на Call-back функцията е фиксиран. Ако решим таймер да свържем с обработка на собствени ф-ии има няколко начина, по к. да се постъпи.

Класически:

1. декларира се call-back ф-ята и се описва изпълнението им. Списъкът е фиксиран.

2. В export наред с proc ф-ята хххх ! да се появи името на TimerProc

3. ! да се свърже името на ф-ята ни, като call-back ф-я на някакво място

3 стъпки:

- декларация на далечен указател

- трябва да се постави адрес на ф-ята, но той е различен за всяко стартиране. Затова се използва MakeProcInstance, к. изработва адреса на TimerProc за конкретния Instancе. Данните са на непостоянно място. МакеProcInstance създава в паметта служебна структура(шлюз) през, к. преминават извикванията към ф-ята. В тази структура има код, в к. адреса на данновия сегмент се зарежда в един регистър. Всяка windows exe програма взема съдържанието на “ах”и го поставя като даннов сегмент.Ако не изработим по този начин адреса извикването на TimerProc ще се намери (кода), но данните - не . Когато Windows размества код и данни в паметта, той има грижата да ги премести в шлюза. Мястото на данни и код е променливо за това понятието на адреса губи смисъл, но за нас адреса е постоянен, защото ние го вземаме от шлюза.

- далечният указател се поставя във ф-ята след таймера

Пр.1


WORD FAR PASCAL TimerProc(HWND hwnd, WORD message,WORD wParam,LONG lParam)

{//отработване на съобщенията от таймера;

return 0;}

EXPORT xxxxx

TimerProc

FARPROC lpfnTimerProc;

// декларация на дълъг указател

......


lpfnTimerProc =

MakeProcInstance (TimerProc, hInstance);

.....

SetTimer(hwnd,1, Interval, lpfnTimerProc);



Таймери в 32 битови среди

CWnd:: SetTimer()

CWnd::KillTimer();

MFC макросът ON_WM_TIMER насочва WM_TIMER към CMainWindows::OnTimer(UINT nTimerID);

Обработката на таймер със съобщения става по 2 начина:

1. Чрез свързване към съобщението и той се връща до пр.1.

2. Чрез свързване с Call-back функция

Таймерското съобщение е ниско приоритетно, т.е ако getmessаge изтегли всички съобщения от опашката тогава ще провери дали е вдигнат флага от таймера. Тогава то се изтегля от getmеssаge а Dispatch message проверява има ли Call-back функция. Ако има подава на нея съобщение, а ако няма се свързва с PROC функцията, която е обща за всички.

1.Приложението с таймер би трябвало да изглежда така:

BEGIN_MESSAGE_MAP ( CMainwindow, CFrameWindow)

ON_WM_CREATE()

ON_WM_TIMER()

END_MESSAGE_MAP

int


CMainWindow::OnCreate(…………)

{…………if(!SetTimer(ID_TIMER_XX,100,NULL)) {..} return 0;}

void

CMainWindow::PnTimer(UINT nTimerID)



{

// например изрисува нещо през 100 мс

}

2.Ако искаме да свържем таймера с callback ф-ия:



SetTimer( ID_TIMER, 100, TimerProc); ……..

void CALLBACK TimerProc( HWND hWnd, UINT nMsg, UINT nTimerID, DWORD dwTime );

3. Определяне на времето

CTime е клас за време и дата

CTime time=CTime::GetCurrentTime();

int second = time.GetSecond();

int nMinute = time.GetMinute();

int nHour = time.GetHour()%12;

Всяка Call-back функция трябва да е или глобална или статична. Глобална – да не е метод на никакъв клас. За да е описана в клас трябва да е статична. Call-back функциите са статични, защото списъка с параметрите е фиксиран. Много от Call-back функциите имат предвиден някой от последните параметри и служи да предава от програмиста данни. С указател this ще се реализира достъп до нестатичните методи на класа, без него обръщение към тях няма.




Сподели с приятели:
  1   2   3   4




©obuch.info 2024
отнасят до администрацията

    Начална страница