Professional Documents
Culture Documents
Bai Giang Lap Trinh Windows
Bai Giang Lap Trinh Windows
BI GING
LP TRNH WINDOWS
TN HC PHN : Lp trnh Windows M HC PHN : 17214 TRNH O TO : I HC CHNH QUY DNG CHO SV NGNH : CNG NGH THNG TIN
HI PHNG - 2010
Sinh vin phi hc xong cc hc phn sau mi c ng k hc phn ny: L p trinh hng i t ng, C u truc d li u Mc tiu ca hc phn: Cung cp cc kin thc c bn v l p trinh trc quan trn h i u hanh Windows hnh phn cua h iu - Cung c p cac ki n thc v truy c p va can thi p vao cac t hnh Windows Ni dung ch yu Cc kin thc v thao tc vi file v th muc , c s d li u registry , cc lung , ti n trnh, dich vu, cc th vin lin kt ng v lp trnh sockets trn Windows. Ni dung chi tit ca hc phn: TN CHNG MC Chng I. Cc khi nim c bn 1.1. Gii thiu v mi trng l p trinh trn Windows 1.1.1. C s v h i u hanh Windows 1.1.2. Cc phin bn cua h i u hanh Windows 1.1.3. Vai tro cua Windows trn thi trng ph n m m 1.2. Th vi n Win32 v Win64 1.2.1. Win32 API 1.2.2. Win64 API 1.3. Gii thi u v b cng cu Visual Studio 2005 Chng II. H th ng file va th mc 2.1. Truy c p va s du ng h th ng file trn mi trng Windows 2.1.1. H th ng file va th mu c cua Windows 2.1.2. Cc thao tc vi file v th muc trn Windows 2.1.3. Cc vn lin quan ti Unicode 2.2. Cc v du v thao tac vi file 2.2.1. Tao file v x l cc li lin quan PHN PHI S TIT TS LT TH/Xemina 3 0 1 BT 0 KT 0
4 2
4 2
4 1
6 1
4 2
6 2
1 1
2 1
4 1
6 2
ii
0,5 4 1 1 2
4 0,5 1 2,5
Tham d cc bui thuyt trnh cua gio vin, t hc, t lm bi tp do gio vin giao, tham d cc bi kim tra inh k v cui k. Ti liu hc tp : L Hu a t. Lp trinh Windows. NXB Giao du c. Charles Petzold. Programming Windows, fifth edition. Microsoft Press. 1998.
- Johnson M. Hart. Windows System Programming Third Edition. Addison Wesley Professional. 2004. Hnh thc v tiu chun nh gi sinh vin: Hnh thc thi cui k : Thi vn p. Sinh vin phi m bo cc iu kin theo Quy ch cua Nh trng v cua B
iii
ii
iii
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { MessageBox(NULL, "Goodbye, cruel world!", "Note", MB_OK); return 0; } Nu nh chng trnh khng lm vic bc u tin m ban cn lm l c tt c cc li (error) m chng trnh bo ln v nu nh ban khng hiu ngha cua chung hy tra trong bt c mt quyn sch day lp trnh hoc cc sch hng dn i km vi trnh bin dich m ban ang s dung. Hy chc chn l ban co y u cc file m trnh bin dich yu cu. Tht khng may l ti khng th giup nhiu trong trng hp ny v cc li phu thuc vo trnh bin dich v ngi s dung (trong vic gy li cng nh sa li). Ban co th nhn c mt vi cnh bo t trnh bin dich v vic chng trnh khng s dung cc tham s c cung cp cung vi hm WinMain(). Nhng khng sao iu quan trng l ban dich chng trnh thnh cng v co mt chng trnh Win32 thc s. Chung ta s phn tch cc oan m chng trnh k cng hn. int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) WinMain() l hm chnh cua mt chng trnh trn mi trng Windows ging nh hm main trn mi trng DOS v UNIX. o l ni cc oan m chng trnh s c thc thi. Cc tham s cua hm main gm co: HINSTANCE hInstance
// Step 4: the Window Procedure LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { switch(msg) { case WM_CLOSE: DestroyWindow(hwnd); break; case WM_DESTROY: PostQuitMessage(0); break; default: // windows x l cc thng ip con lai return DefWindowProc(hwnd, msg, wParam, lParam); } return 0; }
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { WNDCLASSEX wc; HWND hwnd; MSG Msg;
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); /* mu nn */ /*wc.hbrBackground = GetStockObject(WHITE_BRUSH); mu nn trng */ wc.lpszMenuName = NULL; /* khng co h thng thc n */ wc.lpszClassName = g_szClassName; /* tn lp ca s */ wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION); /* ng k lp ca s */ if(!RegisterClassEx(&wc)) { MessageBox(NULL, "Window Registration Failed!", "Error!", MB_ICONEXCLAMATION | MB_OK); return 0; }
// Step 2: Creating the Window // Tao ra mt th nghim cua lp ca s cho ng dung hwnd = CreateWindowEx( WS_EX_CLIENTEDGE, g_szClassName, "The title of my window", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 240, 120, NULL, NULL, hInstance, NULL);
// Step 3: The Message Loop // Step 3: Tao vong lp x l thng ip while(GetMessage(&Msg, NULL, 0, 0) > 0) { TranslateMessage(&Msg); DispatchMessage(&Msg); } return Msg.wParam; }
Hnh 1 Ca s cua chng trnh khi chay y co le la m t chng trinh windows n gian nh t ma ba n co th vi t va chc nng cua chng trnh n gin l tao ra mt ca s cng rt n gin . Ban nn g chng trnh v bin dich cha y th va hay am bao la khng co li gi xay ra . Bc 1: ng ky (Registering) lp ca s (Window). M t lp ca s (Window Class) cha cac thng tin v ki u ca s , bao g m thu tu c Window cua no (thu tuc ny kim sot ca s khi no c ta o ra va ap ng la i cac s ki n ngi dung tac ng ln ca s ), cc icon ln v nho cua ca s, v mu nn cua ca s. Theo cch ny ban co th ng k mt lp v sau o tao ra bao nhiu ca s tuy thich ma khng c n chi ro t t ca cac thu c tinh o thm m t l n nao na . H u h t cac thu c tinh ma ba n thi t l p trong lp ca s (window) co th thay i c theo mt cch rt c bn (th m c) n u nh ba n thch. V cn chu l lp ca s ny khng lin quan g ti khi nim cc lp trong C++. const char g_szClassName[] = "myWindowClass"; Bi n trn lu tn cua lp ca s cua chung ta , chung ta s s dung no ng k lp ca s cua chung ta vi h th ng.
wc.lpfnWndProc = WndProc; wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance wc.hIcon wc.hCursor = hInstance; = LoadIcon(NULL, IDI_APPLICATION); = LoadCursor(NULL, IDC_ARROW);
if(!RegisterClassEx(&wc)) { MessageBox(NULL, "Window Registration Failed!", "Error!", MB_ICONEXCLAMATION | MB_OK); return 0; } o la oa n ma chng trinh chung ta s du ng trong ham WinMain() ng ky lp ca s cua chung ta . Chung ta s in y u cc thnh vin cua cu truc WNDCLASSEX v gi ti ham RegisterClassEx(). Cc thnh vin cua cu truc nh hng n lp ca s gm co: cbSize: kch thc cua cu truc style: Class Style (CS_*), khng nhm ln vi Window Style (WS_*). Thng thng thu c tinh nay c gan b ng 0. lpfnWndProc: con tro tro ti thu tu c quan ly ca s cho lp ca s nay . cbClsExtra: L ng d li u thm c c p phat trong b nh cho mi ca s thu c loa i ny. Thng thng cung c gan b ng 0. hInstance: Qun l mt th nghim (instance) cua ng dung (tham s u tin cua ham WinMain()). hIcon: Icon ln (th ng la 32x32) hi n thi khi chung ta nhn t hp phm Alt+TAB.
10
11
12
13
14
case WM_CLOSE: DestroyWindow(hwnd); break; case WM_DESTROY: PostQuitMessage(0); break; default: return DefWindowProc(hwnd, msg, wParam, lParam); } return 0; } Th t x ly cac thng i p la quan tro ng va c n nh la i vi cac thng i p khac (ngoi WM_DESTROY va WM_QUIT) c n co thm cu l nh break sau khi x ly xong thng i p. Trc tin ti se trinh bay oa n ma l nh ma chung ta se thm vao (hi n thi tn cua chng trinh cua chung ta ) v sau o ti s tch hp oan m o vo chng trnh cua chung ta. Trong cac ph n sau cua chng trinh t i se chi cho cac ba n oa n ma va cac ba n t tich h p oa n ma o vao cac chng trinh . i u nay va t t cho ti : ti se khng phai go i go la i cc oan m lnh v va tt cho cc ban : cc ban co c hi thc hn h nhng hi u bi t cua mnh nng cao k nng thc hnh . Con nu nh ban khng chc chn hy tra trong m ngu n chng trinh i kem vi tai li u nay . GetModuleFileName(hInstance, szFileName, MAX_PATH); MessageBox(hwnd, szFileName, MB_ICONINFORMATION); "This program is:", MB_OK |
Hm WndProc() cua chung ta by gi s nh sau: LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { switch(msg) { case WM_LBUTTONDOWN: // BEGIN NEW CODE { char szFileName[MAX_PATH]; HINSTANCE hInstance = GetModuleHandle(NULL);
15
16
#define WM_LBUTTONDOWN
0x0201
vn vn . Cc thng ip c s dung tru y n thng h u nh mo i th trn h i u hnh windows t nht l tai cc cp c bn . N u ba n mu n m t ca s ho c m t i u khi n (l mt dang ca s c bit ) thc hi n m t cng vi c nao o , ban s phi gi cho no m t thng i p. N u m t ca s khac mu n ba n lam i u gi o no se gi ti cho ba n m t thng i p. N u m t s ki n xay ra ch ng ha n nh ngi dung go ban phim , di chuy n chu t , nh n chu t ln m t button , th cc thn g i p se c h th ng (h i u hanh windows ) gi n cho cac ca s chiu tac ng cua s ki n o . N u ba n la m t trong cac ca s nh th , ban s ti p nh n va x ly thng i p, co cc hnh vi thch hp. Mi m t thng i p co th co nhi u nh t la hai tham s , wParam va lParam . Nguyn bn wParam l 16 bit va lParam la 32 bit, nhng trn cac h th ng Win 32 chung u l 32 bit. Khng phai t t cac thng i p u s du ng hai tham s nay , v mi thng i p s du ng chung theo cac cach khac nhau . Ch ng ha n thng i p WM _CLOSE khng s du ng ca hai tham s trn, v ban co th bo qua chung . Thng i p WM_COMMAND s du ng ca hai tham s trn , wParam cha hai gia tri , HIWORD(wParam) l thng ip bo hiu (n u thich h p ) v LOWORD(wParam) l inh danh iu khin hoc menu gi thng ip . lParam la HWND (window handle ) cua iu khin gi thng ip hoc NULL nu nh cc thng ip khng phi c gi i t m t i u khi n nao o. HIWORD() v LOWORD l cc macro c inh ngha bi windows ly ra 2 byte cao (High Word) cua mt gi tri 4 byte = 32 bit (0xFFFF0000) v hai byte thp (0x0000FFFF) tng ng. Trn cac h th ng Win 32 m t WORD la m t gia tri 16 bit con DWORD (Double WORD) l mt gi tri 32 bit. gi m t thng i p ba n co th s du ng ham PostMessage () ho c SendMessage (). PostMessage() t (put) thng i p vao hang i thng i p va tra v ngay l p tc. i u o co ngha l mi khi chung ta gi ti hm PostMessage () no s gi thng ip i ngay nhng vic thng i p o co thc hi n ngay hay khng ho c th m chi co thc hi n hay khng thi con cha ch c ch n . Hm SendMessage() gi thng i p trc ti p ti cho ca s nh n thng i p v s khng kt thuc cho ti khi thng ip o c x l xong. N u chung ta mu n ong m t ca s chung ta co th gi ti ca s o m t thng i p WM_CLOSE ch ng ha n nh PostMessage(hwnd, WM_CLOSE, 0, 0); i u nay co tac ng tng t nh vi c chung ta nh n chu t ln bi u t ng trn goc trn bn phai cua ca s . Chu rng wParam v
17
18
fWndProc(Msg.hwnd, Msg.message, Msg.wParam, Msg.lParam); } Ti a th cach o vi oa n ma chng trinh trc cua chung ta va no hoa t ng t t , tuy nhin co r t nhi u v n ch ng ha n nh cac chuy n i Unicode /ANSI, cc li gi ti cc iu khin thi gian vn vn m hm ny khng phu hp , v kh nng rt cao l no s break vi h u h t cac chng trinh tr cac chng trinh n gian . V th khng nn th dung hm ny, tr khi ba n chi mu n th no. Chu l chung ta s dung hm Get WindowLong() ly thu tuc x l ca s cua ca s . Tai sao chung ta khng n gin l gi ti hm WndProc () m t cach trc ti p ? Vong lp cc thng ip cua chung ta chiu trch nhim p ng cho tt c cc ca s tron g chng trnh cua chung ta , i u nay bao g m ca cac th ch ng ha n nh cac nut (button) v cc hp danh sach vi cac ham x ly thng i p cua chung , v th chung ta cn m bo l chung ta gi n ung hm x l ca s cua cac thanh ph n o (y thc s la m t vi du cua khai ni m a th trong l p trinh hng i t ng ). V cc ca s co th s dung chung mt hm x l thng i p nn tham s u tin (handle cua ca s ) c dung chi cho ham x ly thng i p bi t ca s nao la danh cho thng i p nao . Nh ba n co th th y ng du ng cua ba n danh ph n ln thi gian cua no cho vong l p x l thng ip , ni ma ba n co th hn hoan gi cac thng i p ti cac ca s se x ly chung . Nhng ba n c n lam gi khi mu n thoat khoi chng trinh ? V chung ta s dung mt vong lp while(), n u nh ham GetMessage () tr v FALSE , vong lp s thot v chung ta s ti cui hm WinMain() v thot khoi chng trnh . o chinh xac la nhng gi ma ham PostQuitMessage() a lam . No t mt thng ip WM _QUIT vao hang i thnmg i p va thay vi tra v m t gia tri dng, hm GetMesage() i n y u cac thng tin cho c u truc Msg v tr v 0. Tai thi im ny thnh vin wParam cua cu truc Msg cha gi tri m ban truy n cho ham PostQuitMessage () v ban cng co th bo qua no , ho c tra v qua ham WinMain(), gi tri o s c dung nh l m thot chng trnh khi tin trnh kt thuc.
19
20
Lp nay s du ng cac lu ng cua C ++ cho php cc lung d liu c nap t hoc lu la i thanh cac file m t cach hi u qua . Lp CArchive khng th t n ta i n u khng co m t i t ng CFile g n vi no. Lp CArchive co th cha d li u trong r t nhi u ki u file khac nhau , t t ca chung u l h u du cua lp CFile . Theo m c inh App Wizard se bao goi t t ca cac chc nng ta o v m cc i tng CFile thng thng s dung vi CArchive . N u chung ta mu n ho c
21
22
}; Macro th hai IMPLEMENTATION _SERIAL c t trong ph n cai t cua lp do chung ta ta o ra . Macro nay c n phai t bn ngoai b t c cac ham thanh vin nao cua lp vi no s thm m cua cc hm cn thit cho lp tng ng vi khai bo cua macro DECLARE_SERIAL. Macro nay nh n 3 tham s . Tham s th nh t l tn lp , gi ng nh macro th nh t . Tham s th hai la tn cua lp c s (l p cha). Tham s th ba la m t s version co th c s du ng xac inh m t file co la ung version thc hi n thao tac o c vi ng du ng cua chung ta hay khng . S version nay phai la m t s dng nn c tng ln mi l n phng thc serializeation cua lp c thay i thay b t c cach thc nao lam thay i d li u c ghi ho c o c t file. V du v khai bo cua macro th hai ny nh sau: // MyClass.cpp: implementation of the CMyClass class.
#ifdef _DEBUG #undef THIS_FILE static char THIS_FILE[]=__FILE__; #define new DEBUG_NEW #endif
23
CMyClass::~CMyClass() { } 2.1.4 Ci t ham Serialize Cung vi hai macro chung ta cn ci t hm Serialize trong lp cua chung ta . Hm ny nn c khai bao la ham ki u void vi m t tham s (CArchive &ar), ki u public va la ham virtual. Khi cai t ham nay ch ung ta thng s dung cch tip cn ging nh cch tng t c dung trong lp document trn , co ngha l cn phi kim tra o l thao tc ghi hay c trc khi thc hi n thao tac. 2.2 Ci t mt lp Serializable Khi chu ng ta b t u thi t k m t ng du ng mi , m t trong nhng i u u tin ma chung ta cn thit k l cch thc cha d liu trong lp document , d li u ma chng trinh s tao ra v thao tc vi . N u chung ta ta o ra m t ng du ng da ng data -oriented cha m t t p d li u t ngi dung ch ng ha n nh m t ng du ng c s d li u ch ng ha n lam th nao cha cac d li u o trong b nh cua chng trinh . Cch t chc d liu nh th no n u chung ta lm vic vi mt ng dung soan tho vn bn hoc ng dung x l bng tnh ? Khi chung ta a xac inh c cach thi t k cac c u truc d li u ma chng trinh se dung chung ta co th quyt inh c cch t t nh t thc hi n chc nng serialize cho chng trinh va cac lp trong chng trinh . N u chung ta quy t inh lu trc ti p t t ca d li u cua chng trinh trong lp document thi t t ca nhng gi chung ta c n la ghi d li u va o c d li u vi i t ng CArchive trong ham Serialize cua lp document . N u chung ta ta o ra lp ring lu cac d li u cua chng trinh (nh chung ta a lam bai thc hanh s 10) chung ta cn phi thm chc nng se rializable cho cac lp nay chung co th t ghi va o c t file. Trong ng du ng ma chung ta se xy dng bai thc hanh nay chung ta se vi t m t chng trinh c s d li u da ng n gian , flat-file minh ho a cach thc k t h p cac ki u d li u khac nhau trong m t lu ng d li u trong ng du ng serialization . ng dung cua chung ta s hin thi mt s cc trng d liu co kiu khc nhau , ghi va o c d li u t m t lu ng d li u duy nh t vi i t ng CArchive. 2.2.1 Thi t k giao din chng trinh Chung ta co th tao ra cc lp cua ring mnh , cc lp ny co th serialized , co th s dung vi cc ng dung SDI hoc MDI. Noi ngn gn bt c ng dung no lm vic vi bt c ki u d li u nao, du o l mt c s d liu hoc mt ti liu u co th serialized. Chung ta tin hnh cc bc sau: 1. 2. Tao mt project dang SDI co tn l Serialize Trong ph n Document Template String g phn File Extension l fdb
24
5. Nh n Finish , chung ta s nhn c thng bo l chng trnh s khng co chc nng in n, nh n Yes ti p tu c Sau khi ta o m t ng du ng SDI ho c MDI trong o lp view k tha t lp CFormView chung ta cn thit k form view cua chng trnh trnh , qu trnh ny cng ging nh thit k cc hp thoai trong cac ng du ng da ng Dialog based nhng chung ta khng c n co cac nut thot khoi chng trnh hoc huy bo qu trnh thc hin nh trn cc hp thoai thng thng . Vi m t ng du ng SDI ho c MDI chc nng ghi va thoat c a s c t trn cac h th ng menu chng trinh ho c trn cac thanh cng cu . Chu : N u chung ta lam vi c vi cac ng du ng da ng Dialog based App Wizard se khng cung c p cac oa n ma serialization cho ng du ng chung ta c n p hi t thc hin iu ny nu mun. Thi t k form cua chng trinh g m cac i u khi n nh bang sau: Object Static Text Edit Box Static Text Edit Box Static Text Property Setting ID ID ID ID ID IDC_STATIC IDC_ENAME IDC_STATIC IDC_EAGE IDC_STATIC IDC_RSINGLE Checked IDC_RMARRIED IDC_RDIVORCED IDC_RWIDOW IDC_CBEMPLOYED IDC_BFIRST Caption &Name:
Caption &Age
Caption Marital Status: Radio Button ID Group Radio Button ID Radio Button ID Radio Button ID Check Box Button ID ID Caption &Single
Caption &Married Caption &Divorced Caption &Widowed Caption &Employed Caption &First
25
Caption &Previous Caption Nex&t Caption &Last Caption Record 0 of 0 Giao di n chng trinh sau khi thi t k trong nh sau:
Khi chung ta phat tri n cac ng du ng ho c ca s ki u dialog -based chung ta s gn cc bi n cho cac i u khi n trn ca s cua lp h p thoa i . Tuy nhin i vi m t ng du ng da ng SDI ho c MDI chung ta se g n cho lp nao ? V hm UpdateData l mt hm cua lp CWnd v lp view l mt hu du cua lp CWnd , m c du lp document thi khng phai , nn lp view se la ni logic nh t t cac bi n g n vi cac i u khi n trn ca s chng trinh. gan cac bi n cho cac i u khi n cua chng trinh chung ta m Class Wizard v gn cc bin cho cc iu khin v ch inh lp cha chung l lp view cu th ng dung ny l CSerializeView. Cc bin c gn cho cc iu khin nh sau: Object IDC_EAGE IDC_ENAME IDC_RSINGLE Name m_iAge m_sName Category Type Value Value Value BOOL int CString int
IDC_CBEMPLOYED m_bEmployed
m_iMaritalStatus Value
26
27
// Are we writing?
28
CO bArray
M t vi c khac chung ta c n lam la include file header cua lp CPerson vao file cai t cua lp document (vi tr trc cc file header cua lp document v view) nh sau: #include "stdafx.h" #include "Serialize.h" #include "Person.h"
29
30
CPerson* CSerializeDoc::GetCurRecord(void) { // Are we editing a valid record number? if (m_iCurPosition >= 0) // Yes, return the current record return (CPerson*)m_oaPeople[m_iCurPosition]; else // No, return NULL return NULL; } Cc chc nng tip theo cn c ci t l cc hm cho php thc hin cc thao tc ly cc bn ghi cua mng mt cch tng i ( u, cu i, trc, sau): CPerson* CSerializeDoc::GetFirstRecord(void) { // Are there any records in the array? if (m_oaPeople.GetSize() > 0) {
31
CPerson* CSerializeDoc::GetNextRecord(void) { // After incrementing the position marker, are we // past the end of the array? if (++m_iCurPosition < m_oaPeople.GetSize()) // No, return the record at the new current position return (CPerson*)m_oaPeople[m_iCurPosition]; else // Yes, add a new record return AddNewRecord(); } CPerson* CSerializeDoc::GetPrevRecord(void) { // Are there any records in the array? if (m_oaPeople.GetSize() > 0) { // Once we decrement the current position, // are we below position 0? if (--m_iCurPosition < 0) // If so, set the record to position 0 m_iCurPosition = 0; // Return the record at the new current position return (CPerson*)m_oaPeople[m_iCurPosition]; }else // No records, return NULL
32
CPerson* CSerializeDoc::GetLastRecord(void) { // Are there any records in the array? if (m_oaPeople.GetSize() > 0) { // Move to the last position in the array m_iCurPosition = (m_oaPeople.GetSize() - 1); // Return the record in this position return (CPerson*)m_oaPeople[m_iCurPosition]; }else // No records, return NULL return NULL; } Ti p n la ham Serialize cho mang cac i t ng cua lp document (CSerializeDoc): void CSerializeDoc::Serialize(CArchive& ar) { // Pass the serialization on to the object array m_oaPeople.Serialize(ar); } Hm lm cng tc mi trng, dn dep tt c mi th trc khi bt u mt ti liu mi (hm ny c gi ti khi chng trinh k t thuc ho c trc khi m t tai li u mi c m ): void CSerializeDoc::DeleteContents() { // TODO: Add your specialized code here and/or call the base class // Get the number of lines in the object array int liCount = m_oaPeople.GetSize(); int liPos;
33
// TODO: add reinitialization code here // (SDI documents will reuse this document) // If unable to add a new record, return FALSE if (!AddNewRecord()) return FALSE;
// Get a pointer to the view POSITION pos = GetFirstViewPosition(); CSerializeView* pView = (CSerializeView*)GetNextView(pos); // Tell the view that it's got a new data set if (pView) pView->NewDataSet(); return TRUE; } Khi m t tai li u mi b t u chng trinh se a ra m t form rng sn sang nh p thng tin mi , v bn ghi ny co th sn sng nhn thng tin chung ta thm vao m t ban ghi trong mang cac i t ng va khi m t ban ghi mi c thm vao mang chung ta c n thay i vi c hi n thi chi ra r ng ban ghi mi o t n ta i ng c la i cac hi n thi se ti p tu c vi ba n
34
// TODO: Add your specialized creation code here // Get a pointer to the view POSITION pos = GetFirstViewPosition(); CSerializeView* pView = (CSerializeView*)GetNextView(pos); // Tell the view that it's got a new data set if (pView) pView->NewDataSet();
return TRUE; } o la t t ca cac cng vi c chu n bi , t chc va x ly d li u cua lp document, ti p n chung ta s lm vic vi lp view tng tc vi ngi dung. i u u tin c n chu y la cac include trong cac file ma ngu n c n theo ung th t (gi ng bai thc hanh s 10): lp CPerson t rc, sau o ti lp document va cu i cung la lp view va cac chi thi include nay chi thc hi n trong cac file cai t lp (khc vi C/C++ thng thng) #include "stdafx.h" #include "Serialize.h"
#include "Person.h" #include "SerializeDoc.h" #include "SerializeView.h" V s lng cc thao tc i vi cc bn ghi l kh nhiu nn cng ging nh bi thc hnh 10 (s du ng 1 bi n lu i m hi n ta i cua con tro chu t ) trong bai thc hanh nay cho ti n chung ta thm m t bi n thanh vin ki u CPerson * co tn l m_pCurPerson cho lp View.
35
36
void CSerializeView::OnBnClickedBlast() { // TODO: Add your control notification handler code here // Get a pointer to the current document CSerializeDoc * pDoc = GetDocument(); if (pDoc) { // Get the last record from the document m_pCurPerson = pDoc->GetLastRecord(); if (m_pCurPerson) { // Display the current record PopulateView(); } } } void CSerializeView::OnBnClickedBprev() { // TODO: Add your control notification handler code here // Get a pointer to the current document CSerializeDoc * pDoc = GetDocument(); if (pDoc) {
37
void CSerializeView::OnBnClickedBnext() { // TODO: Add your control notification handler code here // Get a pointer to the current document CSerializeDoc * pDoc = GetDocument(); if (pDoc) { // Get the last record from the document m_pCurPerson = pDoc->GetNextRecord(); if (m_pCurPerson) { // Display the current record PopulateView(); } } } Ti p n chung ta c n m t ham reset la i lp view mi khi m t ban ghi mi c b t u ho c c m ngi khng ti p tu c nhin th y t p ban ghi cu . Chung ta co th gi ti hm x ly s ki n cua nut First bu c lp view a ra ban ghi u tin trong t p ban ghi . lam i u nay chung ta thm m t ham void (pubic) tn la NewDataSet nh sau: void CSerializeView::NewDataSet(void) { OnBnClickedBfirst(); }
38
void CSerializeView::OnEnChangeEage() {
39
40
V du, bt c mt phn cng my tnh no thay i u lm chc nng Plug and Play (Cm v chay) khi tao ngay v lm thay i lun cu hnh trong Registry. Registry lu tr tt c cc thit lp v cu truc b nh, phn cng, thit bi ngoai vi, v cc thnh phn lin quan n mang. Ban s tm thy o nhiu hn nhng thit lp cn thit trong cc tp khi tao ban u T Win98 v sau, Windows co s dung Registry Checker t qut Registry, nu khng thy g, no t lu backup mt ln trong ngy, nu tm thy li s sa... co th sa bng cch thay th bn Registry backup gn nht con tt. Registry Checker ti u ho v nn file backup thnh cng mi ln khi ng my. No con lm mt loat cc vic linh tinh nh loai bo nhng khong trng khng dung trong Registry, ti u ho...
41
Cc tp Registry cua Windows. Registry hin tai bao gm 3 tp chnh: 1. Tp USER.DAT Dung lu tr nhng xc lp ngi s dung i vi cc phn mm. 2. Tp SYSTEM.DAT Dung lu tr nhng xc lp lin quan ti my tnh v phn cng. 3. Tp Policy.pol System policies c thit k chun bi cho vic ghi bt c thit lp c cha trong 2 thnh phn registry khc nhau. System policies co th cha d liu b sung c trng ti mang hay mi trng t hp nh c ci t bi network administrator. Bn thn System policies cng c cha trong tp Policy.pol. Khng nh SYSTEM.DAT v USER.DAT, Policy.pol khng phi l thnh phn bt buc cua phn ci t Windows. Cc khoa chnh trong mt CSDL Registry: + HKEY_LOCAL_MACHINE cha cc thng tin v cu hnh vt l cua h thng cung vi cc phn mm c ci t trn h thng. + HKEY_USERS: cha cc thng tin cu hnh cua ti khon ngi dung + HKEY_CURRENT_CONFIG: cha cc thng tin thit lp cua h thng hin tai chng han nh phn gii mn hnh hay font ch. + HKEY_CLASS_ROOT: cha cc thng tin nh xa t cc kiu file sang cc ng dung m chung. HKEY_CURRENT_USER: cha cc thng tin v cc ti khon trn h thng, chng han nh cc bin mi trng, cc my in v cc tuy chn ng dung khc. 1.2 Cc kiu d liu Li khuyn ca Microsoft v nhng cng c x ly registry
42
Ban co th s dung Registry Editor thay i Registry bng tay. Ti thng dung Norton Registry Editor v no con co thm chc nng khc, v du nh tm v thay th i vi cc thnh phn cua Registry. T cc phn mm Registry Editor trn, ta nhn thy registry c b tr thnh cc nhnh ln. Tai mi nhnh co cc kho SUBKEY. Tai cc SUBKEY d liu c lu cc dang: 1. String (Dang chui) 2. Numeric (Dang s) 3. Binary (Dang nhi phn) 4. Expanded String (Dang chui m rng) 5. MultiString (Dang chui tng hp) (Nu ban dung Registry Editor - REGEDIT. EXE th s gi tn khc l DWORD) 2. Qun ly CSDL Registry Khi lp trnh i vi Registry, ban phi thc hin ht sc thn trng, sao lu cc tp ny thng xuyn trnh li ng tic, phi mt cng ci lai th cng rt mt thi gian.S dung cc hm API i vi Registry cng xin ht sc thn trng. 2.1 Thay i khoa thay i gi tri cua mt khoa trong CSDL Registry chung ta s dung hm LONG RegSetValueEx(HKEY hKey, LPCTSTR lpValueName, DWORD reserved, DWORD dwType, CONST BYTE * lpData, CONST cbData). 2.2 Thm mi khoa lm vic vi cc khoa trong CSDL Registry u tin chung ta s quan tm ti cc hm thm khoa mi: LONG RegOpenKeyEx(HKEY hKey, LPCTSTR lpSubKey, DWORD ulOptions, REGSAM samDesired, PHKEY phkResult). Trong o tham s th nht l handle tro ti khoa ang m, tham s phkResult tro ti mt bin co kiu HKEY cho khoa co th m mi, lpSubKey l tn cua subkey m chung ta mun m, thng thng co th l mt ng dn chng han nh Microsoft\WindowsNT\CurrentVersion. Gi tri NULL cho bin ny co ngha l mt khoa bng gi tri hKey s c sinh ra. Bin ulOptions l bin d tr v co gi tri bng 0. Bin samDesired l mt na truy cp m t gi tri bo mt cho khoa mi, co th l kt hp cua cc gi tri hng s KEY_ALL_ACCESS, KEY_WRITE, KEY_QUERY_VALUE, KEY_ENUMERATE_SUBKEYS. Gi tri tr v cua hm thng l ERROR_SUCCESS. Cng co th dung hm LONG RegCreateKeyEx( HKEY hKey, LPCTSTR lpSubKey, DWORD Reserved, LPTSTR lpClass, DWORD dwOptions, REGSAM samDesired, PSECURITY_ATTRIBUTES lpSecurityAttributes, PHKEY phkResult, LPDWORD lpdwDisposition) tao khoa mi.
43
3.3 Thay i cac thi t l p vi ngi dung Cc bin mi trng cua mt ngi dung nm trong phn HKEY_CURRENT_USER\Environment, con cho c h thng nm trong phn HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Environment. Bi tp: Bi tp 1: Vit chng trnh thay i giao din Windows bng cch s dung can thip qua Registry. Bi tp 2: Vit chng trnh thay i cc bin mi trng cua Windows bng cch s dung can thip qua Registry.
44
45
2. Cc thao tc vi tin trnh 2.1. To tin trnh Hm c bn qun l cc tin trnh cua Windows l hm CreateProcess(), hm ny tao ra mt tin trnh vi mt lung n. Tham s m hm cn l tn file chng trnh s thc hin. Chung ta co th thy co nhiu cp ti khi nim tin trnh cha, tin trnh con nhng thc s th quan h ny khng c qun l bi Windows. Windows n thun ch tham chiu ti cc tin trnh tai ra mt tin trnh con m no l tin trnh cha. Hm CreateProcess() co 10 tham s: BOOL CreateProcess ( LPCTSTR lpApplicationName, LPTSTR lpCommandLine, LPSECURITY_ATTRIBUTES lpsaProcess, LPSECURITY_ATTRIBUTES lpsaThread, BOOL bInheritHandles, DWORD dwCreationFlags, LPVOID lpEnvironment,
46
OSVer.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
47
/* Execute the command line; wait for process to complete. */ CreateProcess (NULL, targv, NULL, NULL, TRUE, NORMAL_PRIORITY_CLASS, NULL, NULL, &StartUp, &ProcInfo);
/* Assure that we have all REQUIRED access to the process. */ DuplicateHandle (GetCurrentProcess (), ProcInfo.hProcess, GetCurrentProcess (), &hProc, PROCESS_QUERY_INFORMATION | SYNCHRONIZE, FALSE, 0); WaitForSingleObject (hProc, INFINITE); GetSystemTime (&ExitTimeSys);
if (IsNT) { /* W NT. Elapsed, Kernel, & User times. */ GetProcessTimes (hProc, &CreateTime.ft, &ExitTime.ft, &KernelTime, &UserTime); ElapsedTime.li = ExitTime.li - CreateTime.li; FileTimeToSystemTime (&ElapsedTime.ft, &ElTiSys); FileTimeToSystemTime (&KernelTime, &KeTiSys); FileTimeToSystemTime (&UserTime, &UsTiSys); _tprintf (_T ("Real Time: %02d:%02d:%02d:%03d\n"), ElTiSys.wHour, ElTiSys.wMinute, ElTiSys.wSecond, ElTiSys.wMilliseconds); _tprintf (_T ("User Time: %02d:%02d:%02d:%03d\n"), UsTiSys.wHour, UsTiSys.wMinute, UsTiSys.wSecond, UsTiSys.wMilliseconds); _tprintf (_T ("Sys Time: %02d:%02d:%02d:%03d\n"), KeTiSys.wHour, KeTiSys.wMinute, KeTiSys.wSecond, KeTiSys.wMilliseconds); } else {
48
49
/* Create a separate "grep" process for each file. */ for (iProc = 0; iProc < argc - 2; iProc++) { _stprintf (CommandLine, _T ("%s%s %s"), _T ("grep "), argv [1], argv [iProc + 2]); GetTempFileName (_T ("."), _T ("gtm"), 0, ProcFile [iProc].TempFile); /* For search results. */ hTempFile = /* This handle is inheritable */
50
/* Create a process to execute the command line. */ CreateProcess (NULL, CommandLine, NULL, NULL, TRUE, 0, NULL, NULL, &StartUpSearch, &ProcessInfo); /* Close unwanted handles. */ CloseHandle (hTempFile); CloseHandle (ProcessInfo.hThread); hProc [iProc] = ProcessInfo.hProcess; }
/* Processes are all running. Wait for them to complete. */ for (iProc = 0; iProc < argc - 2; iProc += MAXIMUM_WAIT_OBJECTS) WaitForMultipleObjects ( /* Allows a large # of processes */ min (MAXIMUM_WAIT_OBJECTS, argc - 2 - iProc), &hProc [iProc], TRUE, INFINITE); /* Result files sent to std output using "cat." */ for (iProc = 0; iProc < argc - 2; iProc++) { if (GetExitCodeProcess(hProc [iProc], &ExCode) && ExCode==0) { /* Pattern was detected -- List results. */ if (argc > 3) _tprintf (_T ("%s:\n"), argv [iProc + 2]); fflush (stdout); /* Multiple processes use stdout. */ _stprintf (CommandLine, _T ("%s%s"), _T ("cat "), ProcFile [iProc].TempFile); CreateProcess (NULL, CommandLine, NULL, NULL, TRUE, 0, NULL, NULL, &StartUp, &ProcessInfo); WaitForSingleObject (ProcessInfo.hProcess, INFINITE); CloseHandle (ProcessInfo.hProcess);
51
/* Thread argument */
} THREADARG, *PTHREADARG;
static int KeyCompare (LPCTSTR, LPCTSTR); static DWORD WINAPI ThSort (PTHREADARG pThArg); static DWORD nRec; /* Total number of records to be sorted. */ static HANDLE * ThreadHandle;
int _tmain (int argc, LPTSTR argv []) { HANDLE hFile; LPRECORD pRecords = NULL;
52
iNP = Options (argc, argv, _T ("n"), &NoPrint, NULL); iFF = iNP + 1; NPr = _ttoi (argv [iNP]); /* Number of threads. */ hFile = CreateFile (argv [iFF], GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL); FsLow = GetFileSize (hFile, NULL); nRec = FsLow / RECSIZE; /* Total number of records. */ nRecTh = nRec / NPr; /* Records per thread. */
/* Allocate thread args and handle array and space for the file. Read the complete file. */
ThArg = malloc (NPr * sizeof (THREADARG)); /* Thread args. */ ThreadHandle = malloc (NPr * sizeof (HANDLE)); pRecords = malloc (FsLow + sizeof (TCHAR)); ReadFile (hFile, pRecords, FsLow, &nRead, NULL); CloseHandle (hFile);
LowRecNo = 0; /* Create the sorting threads. */ for (iTh = 0; iTh < NPr; iTh++) { ThArg [iTh].iTh = iTh; ThArg [iTh].LowRec = pRecords + LowRecNo; ThArg [iTh].HighRec = pRecords + (LowRecNo + nRecTh); LowRecNo += nRecTh; ThreadHandle [iTh] = (HANDLE) _beginthreadex (NULL, 0, ThSort, &ThArg [iTh], CREATE_SUSPENDED, &ThId); }
53
StringEnd = (LPTSTR) pRecords + FsLow; *StringEnd = '\0'; if (!NoPrint) printf ("\n%s", (LPCTSTR) pRecords); free (pRecords); free (ThArg); free (ThreadHandle); return 0; } /* End of _tmain. */
static VOID MergeArrays (LPRECORD, LPRECORD); DWORD WINAPI ThSort (PTHREADARG pThArg) { DWORD GrpSize = 2, RecsInGrp, MyNumber, TwoToI = 1; LPRECORD First;
MyNumber = pThArg->iTh; First = pThArg->LowRec; RecsInGrp = pThArg->HighRec - First; qsort (First, RecsInGrp, RECSIZE, KeyCompare); while ((MyNumber % GrpSize) == 0 && RecsInGrp < nRec) { /* Merge with the adjacent sorted array. */ WaitForSingleObject ( ThreadHandle [MyNumber + TwoToI], INFINITE); MergeArrays (First, First + RecsInGrp); RecsInGrp *= 2; GrpSize *= 2; TwoToI *= 2; } _endthreadex (0);
54
static VOID MergeArrays (LPRECORD p1, LPRECORD p2) { DWORD iRec = 0, nRecs, i1 = 0, i2 = 0; LPRECORD pDest, p1Hold, pDestHold;
nRecs = p2 - p1; pDest = pDestHold = malloc (2 * nRecs * RECSIZE); p1Hold = p1; while (i1 < nRecs && i2 < nRecs) { if (KeyCompare ((LPCTSTR) p1, (LPCTSTR) p2) <= 0) { memcpy (pDest, p1, RECSIZE); i1++; p1++; pDest++; }
if (i1 >= nRecs) memcpy (pDest, p2, RECSIZE * (nRecs - i2)); else memcpy (pDest, p1, RECSIZE * (nRecs - i1));
memcpy (p1Hold, pDestHold, 2 * nRecs * RECSIZE); free (pDestHold); return; } Bi tp: Bi tp 1: Vit chng trnh hin thi tt c cc thng tin v tin trnh v lung cua mt tin trnh ang chay.
55
2. Cc thnh phn ca mt dich v 2.1 Hm main() Hm ny c gi bi SCM, co nhim vu l khai bo dich vu vi SCM v bt u thc hin cng vic cua mt dich vu. 2.2 Hm ServiceMain() Hm ServiceMain() l mt dang tng t nh hm main() vi cc tham s tng t, no thc hin cc tc vu chnh cua mt dich vu. 2.3 Ki m soat dich vu qua cac Handler kim sot dich vu, chung ta s dung cc hm sau: DWORD WINAPI HandlerEx ( DWORD dwControl, DWORD dwEventType,
56
VOID LogEvent (LPCTSTR, DWORD, BOOL); void WINAPI ServiceMain (DWORD argc, LPTSTR argv []); VOID WINAPI ServerCtrlHandlerEx(DWORD, DWORD, LPVOID, LPVOID); void UpdateStatus (int, int); /* Calls SetServiceStatus. */ int ServiceSpecific (int, LPTSTR *); /* Former main program. */ volatile static BOOL ShutDown = FALSE, PauseFlag = FALSE; static SERVICE_STATUS hServStatus; static SERVICE_STATUS_HANDLE hSStat; /* Handle to set status. */
/* Main routine that starts the service control dispatcher. */ VOID _tmain (int argc, LPTSTR argv []) { SERVICE_TABLE_ENTRY DispatchTable [] = { { ServiceName, ServiceMain }, { NULL, NULL } };
/* ServiceMain entry point, called when the service is created. */ void WINAPI ServiceMain (DWORD argc, LPTSTR argv [])
57
/* Set all server status data members. */ hServStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS; hServStatus.dwCurrentState = SERVICE_START_PENDING; hServStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN SERVICE_ACCEPT_PAUSE_CONTINUE; hServStatus.dwWin32ExitCode = ERROR_SERVICE_SPECIF0C_ERROR; hServStatus.dwServiceSpecificExitCode = 0; hServStatus.dwCheckPoint = 0; hServStatus.dwWaitHint = 2 * CS_TIMEOUT; |
/* Start service-specific work; generic work is complete. */ if (ServiceSpecific (argc, argv) != 0) { hServStatus.dwCurrentState = SERVICE_STOPPED; hServStatus.dwServiceSpecificExitCode = 1; /* Server initialization failed. */ SetServiceStatus (hSStat, &hServStatus); return; } /* We will only return here when the ServiceSpecific function completes, indicating system shutdown. */ UpdateStatus (SERVICE_STOPPED, 0); return; }
58
/* Control handler function, invoked by the SCM to run */ /* in the same thread as the main program. */ /* The last three parameters are not used, and the pre-NT5 */ /* handlers would also work in this example. */ VOID WINAPI ServerCtrlHandlerEx (DWORD Control, DWORD EventType, LPVOID lpEventData, LPVOID lpContext) { swsitch (Control) { case SERVICE_CONTROL_SHUTDOWN: case SERVICE_CONTROL_STOP: ShutDown = TRUE; /* Set the global shutdown flag. */ UpdateStatus (SERVICE_STOP_PENDING, -1); break; case SERVICE_CONTROL_PAUSE: PauseFlag = TRUE; /* Interrogated periodically. */ break; case SERVICE_CONTROL_CONTINUE: PauseFlag = FALSE; break; case SERVICE_CONTROL_INTERROGATE: break; default: if (Control > 127 && Control < 256) /* User defined. */
59
/* This is the service-specific function, or "main," and is called from the more generic ServiceMain. In general, you can take any server, such as ServerNP.c, and rename "main" as "ServiceSpecific"; putting code right here. But some changes are required to update status. */
int ServiceSpecific (int argc, LPTSTR argv []) { UpdateStatus (-1, -1); /* Increment the checkpoint. */ /* ... Initialize system ... */ /* Be sure to update the checkpoint periodically. */
return 0; } 4. Qun ly cc dich v ca Windows 4.1 Cc phng php kim sot cc dich v ca Windows qun l cc dich vu cua Windows ta co hai cch: mt l dung cng cu SCM, hai l g trc tip cc lnh trn dong lnh. 4.2 Vi d : i u khi n cac dich vu cua Windows #include "EvryThng.h"
int _tmain (int argc, LPTSTR argv []) { BOOL Exit = FALSE; TCHAR Command [MAX_COMMAND_LINE + 10], *pc;
60
/* Prepare the local "argv" array as pointers to strings. */ for (i = 0; i < MAX_ARG; i++) pArgs [i] = argstr [i];
/* Open the SC Control Manager on the local machine. */ hScm = OpenSCManager (NULL, NULL, SC_MANAGER_ALL_ACCESS);
/* Main command processing loop. */ _tprintf (_T ("\nWindows Service Management")); while (!Exit) { _tprintf (_T ("\nSM$")); _fgetts (Command, MAX_COMMAND_LINE, stdin); ... Similar to JobShell ... if (_tcscmp (argstr [0], _T ("create")) == 0) { Create (LocArgc, pArgs, Command); } ... Similarly for all commands ... } CloseServiceHandle (hScm); return 0; }
int Create (int argc, LPTSTR argv [], LPTSTR Command) { /* Create a new service as a "demand start" service: argv [1]: service Name argv [2]: display Name argv [3]: binary executable */ SC_HANDLE hSc; TCHAR CurrentDir [MAX_PATH + 1], Executable [MAX_PATH + 1];
61
int Delete (int argc, LPTSTR argv [], LPTSTR Command) { SC_HANDLE hSc; hSc = OpenService (hScm, argv [1], DELETE); DeleteService (hSc); CloseServiceHandle (hSc); return 0; }
/* Start a named service -- argv [1]: service name to start. */ int Start (int argc, LPTSTR argv [], LPTSTR Command) { SC_HANDLE hSc; TCHAR WorkingDir [MAX_PATH + 1]; LPTSTR pWorkingDir = WorkingDir; LPTSTR argvStart [] = {argv [1], WorkingDir};
GetCurrentDirectory (MAX_PATH + 1, WorkingDir); hSc = OpenService(hScm, argv [1], SERVICE_ALL_ACCESS); /* Start the service with one arg, the working directory. */ /* Note: The service name agrees, by default, with the name */ /* /* associated with the handle, hSc, by OpenService. */ But, the ServiceMain function does not verify this. */
62
/* Control a named service. argv [1]: service name to control. argv [2]: Control command: stop, pause, resume, interrogate. */ static LPCTSTR Commands [] = {"stop," "pause," "resume," "interrogate," "user"}; static DWORD Controls [] = { SERVICE_CONTROL_STOP, SERVICE_CONTROL_PAUSE, SERVICE_CONTROL_CONTINUE, 128}; SERVICE_CONTROL_INTERROGATE,
int Control (int argc, LPTSTR argv [], LPTSTR Command) { SC_HANDLE hSc; SERVICE_STATUS ServiceStatus; DWORD dwControl, i; BOOL Found = FALSE;
for (i= 0; i < sizeof (Controls)/sizeof (DWORD) && !Found; i++) Found = (_tcscmp (Commands [i], argv [2]) == 0); if (!Found) { _tprintf (_T ("\nIllegal Control Command %s"), argv [1]); return 1; } dwControl = Controls [i - 1]; hSc = OpenService(hScm, argv [1], SERVICE_INTERROGATE | SERVICE_PAUSE_CONTINUE | SERVICE_STOP | SERVICE_USER_DEFINED_CONTROL | SERVICE_QUERY_STATUS); ControlService (hSc, dwControl, &ServiceStatus);
63
64
65
66
typedef struct SERVER_ARG_TAG { /* Server thread arguments. */ volatile DWORD number; volatile SOCKET sock; volatile DWORD status; /* Explained in main thread comments. */ volatile HANDLE srv_thd; HINSTANCE dlhandle; /* Shared library handle. */ } SERVER_ARG; volatile static ShutFlag = FALSE; static SOCKET SrvSock, ConnectSock;
int _tmain (DWORD argc, LPCTSTR argv []) { /* Server listening and connected sockets. */ BOOL Done = FALSE; DWORD ith, tstatus, ThId; SERVER_ARG srv_arg [MAX_CLIENTS]; HANDLE hAcceptTh = NULL; HINSTANCE hDll = NULL;
/* Initialize the WSA library, Ver 2.0, although 1.1 will work. */ WSAStartup (MAKEWORD (2, 0), &WSStartData);
/* Open command library DLL if specified on command line. */ if (argc > 1) hDll = LoadLibrary (argv [1]); /* Initialize thread arg array. */ for (ith = 0; ith < MAX_CLIENTS; ith++) { srv_arg [ith].number = ith; srv_arg [ith].status = 0; srv_arg [ith].sock = 0; srv_arg [ith].dlhandle = hDll; srv_arg [ith].srv_thd = NULL;
67
/* Main thread becomes listening/connecting/monitoring thread. */ /* Find an empty slot in the server thread arg array. */ /* status values: 0 -- slot is free; 1 -- thread stopped; 2 -- thread running; 3 -- stop entire system. */ while (!ShutFlag) { for (ith = 0; ith < MAX_CLIENTS && !ShutFlag; ) { if (srv_arg [ith].status==1 || srv_arg [ith].status==3) { /* Thread stopped, normally or by shutdown request. */ WaitForSingleObject (srv_arg[ith].srv_thd INFINITE); CloseHandle (srv_arg[ith].srv_thd); if (srv_arg [ith].status == 3) ShutFlag = TRUE; else srv_arg [ith].status = 0; /* Free thread slot. */ } if (srv_arg [ith].status == 0 || ShutFlag) break; ith = (ith + 1) % MAX_CLIENTS; if (ith == 0) Sleep (1000); /* Break the polling loop. */ /* Alternative: use an event to signal a free slot. */ } /* Wait for a connection on this socket. */ /* Separate thread so we can poll the ShutFlag flag. */ hAcceptTh = (HANDLE)_beginthreadex (NULL, 0, AcceptTh, &srv_arg [ith], 0, &ThId);
68
_tprintf (_T ("Server shutdown. Wait for all srvr threads\n")); /* Terminate the accept thread if it is still running. * See the Web site for more detail on this shutdown logic. */ if (hDll != NULL) FreeLibrary (hDll); if (hAcceptTh != NULL) TerminateThread (hAcceptTh, 0); /* Wait for any active server threads to terminate. */ for (ith = 0; ith < MAX_CLIENTS; ith++) if (srv_arg [ith].status != 0) { WaitForSingleObject (srv_arg[ith].srv_thd, INFINITE); CloseHandle (srv_arg[ith].srv_thd); } shutdown (SrvSock, 2); closesocket (SrvSock); WSACleanup (); return 0; }
static DWORD WINAPI AcceptTh (SERVER_ARG * pThArg) { /* Accepting thread that allows the main thread to poll the */ /* shutdown flag. This thread also creates the server thread. */ LONG AddrLen, ThId;
69
GetStartupInfo (&StartInfoCh); ConnectSock = pThArg->sock; /* Create a temp file name. */ sprintf (TempFile, "%s%d%s", "ServerTemp", pThArg->number, ".tmp");
while (!Done && !ShutFlag) { /* Main command loop. */ Disconnect = ReceiveRequestMessage (&Request, ConnectSock); Done = Disconnect || (strcmp (Request.Record, "$Quit") == 0) || (strcmp (Request.Record, "$ShutDownServer") == 0); if (Done) continue; /* Stop this thread on "$Quit" or "$ShutDownServer". */ hTmpFile = CreateFile (TempFile, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, &TempSA, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
70
i = strcspn (Request.Record, ws); /* Length of token. */ memcpy (sys_command, Request.Record, i); sys_command [i] = '\0';
dl_addr = NULL; /* Will be set if GetProcAddress succeeds. */ if (pThArg->dlhandle != NULL) { /* Try server "in process." */ dl_addr = (int (*)(char *, char *)) GetProcAddress (pThArg->dlhandle, sys_command); if (dl_addr != NULL) __try { /* Protect server process from exceptions in DLL. */ (*dl_addr) (Request.Record, TempFile); } __except (EXCEPTION_EXECUTE_HANDLER { ReportError (_T ("Exception in DLL"), 0, FALSE); } } } if (dl_addr == NULL) { /* No in-process support. */ /* Create a process to carry out the command. */ /* ... Same as in serverNP ... */ } /* ... Same as in serverNP ... */
_tprintf (_T ("Shutting down server# %d\n"), pThArg->number); shutdown (ConnectSock, 2); closesocket (ConnectSock);
71
int _tmain (DWORD argc, LPTSTR argv []) { SOCKET ClientSock = INVALID_SOCKET; REQUEST Request; /* See ClntSrvr.h. */ RESPONSE Response; /* See ClntSrvr.h. */ WSADATA WSStartData; /* Socket library data structure. */ BOOL Quit = FALSE; DWORD ConVal, j; TCHAR PromptMsg [] = _T ("\nEnter Command> "); TCHAR Req [MAX_RQRS_LEN]; TCHAR QuitMsg [] = _T ("$Quit"); /* Request: shut down client. */ TCHAR ShutMsg [] = _T ("$ShutDownServer"); /* Stop all threads. */ CHAR DefaultIPAddr [] = "127.0.0.1"; /* Local system. */
72
/* Connect to the server. */ /* Follow the standard client socket/connect sequence. */ ClientSock = socket (AF_INET, SOCK_STREAM, 0); memset (&ClientSAddr, 0, sizeof (ClientSAddr)); ClientSAddr.sin_family = AF_INET; if (argc >= 2) ClientSAddr.sin_addr.s_addr = inet_addr (argv [1]); else ClientSAddr.sin_addr.s_addr = inet_addr (DefaultIPAddr); ClientSAddr.sin_port = htons (SERVER_PORT); /* Defined as 1070. */ connect (ClientSock, (struct sockaddr *) &ClientSAddr, sizeof (ClientSAddr)); /* Main loop to prompt user, send request, receive response. */ while (!Quit) { _tprintf (_T ("%s"), PromptMsg); /* Generic input, but command to server must be ASCII. */ _fgetts (Req, MAX_RQRS_LEN-1, stdin); for (j = 0; j <= _tcslen (Req); j++) Request.Record [j] = Req [j]; /* Get rid of the new line at the end. */ Request.Record [strlen (Request.Record) - 1] = '\0'; if (strcmp (Request.Record, QuitMsg) == 0 || strcmp (Request.Record, ShutMsg) == 0) Quit = TRUE; SendRequestMessage (&Request, ClientSock); ReceiveResponseMessage (&Response, ClientSock); }
shutdown (ClientSock, 2); /* Disallow sends and receives. */ closesocket (ClientSock); WSACleanup ();
73
74
75
76
----------------------*/
#ifdef __cplusplus #define EXPORT extern "C" __declspec (dllexport) #else #define EXPORT __declspec (dllexport) #endif
EXPORT BOOL CALLBACK EdrCenterTextA (HDC, PRECT, PCSTR) ; EXPORT BOOL CALLBACK EdrCenterTextW (HDC, PRECT, PCWSTR) ;
#ifdef UNICODE #define EdrCenterText EdrCenterTextW #else #define EdrCenterText EdrCenterTextA #endif
77
int WINAPI DllMain (HINSTANCE hInstance, DWORD fdwReason, PVOID pvReserved) { return TRUE ; }
EXPORT BOOL CALLBACK EdrCenterTextA (HDC hdc, PRECT prc, PCSTR pString) { int iLength ; SIZE size ;
iLength = lstrlenA (pString) ; GetTextExtentPoint32A (hdc, pString, iLength, &size) ; return TextOutA (hdc, (prc->right - prc->left - size.cx) / 2, (prc->bottom - prc->top - size.cy) / 2, pString, iLength) ; }
EXPORT BOOL CALLBACK EdrCenterTextW (HDC hdc, PRECT prc, PCWSTR pString) { int iLength ; SIZE size ;
78
WNDCLASS
wndclass.style
= CS_HREDRAW | CS_VREDRAW ;
wndclass.lpfnWndProc = WndProc ; wndclass.cbClsExtra = 0 ; wndclass.cbWndExtra = 0 ; wndclass.hInstance wndclass.hIcon wndclass.hCursor = hInstance ; = LoadIcon (NULL, IDI_APPLICATION) ; = LoadCursor (NULL, IDC_ARROW) ;
if (!RegisterClass (&wndclass)) { MessageBox (NULL, TEXT ("This program requires Windows NT!"), szAppName, MB_ICONERROR) ;
79
hwnd = CreateWindow (szAppName, TEXT ("DLL Demonstration Program"), WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, NULL) ;
while (GetMessage (&msg, NULL, 0, 0)) { TranslateMessage (&msg) ; DispatchMessage (&msg) ; } return msg.wParam ; } LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { HDC hdc ;
switch (message) { case WM_PAINT: hdc = BeginPaint (hwnd, &ps) ; GetClientRect (hwnd, &rect) ; EdrCenterText (hdc, &rect, TEXT ("This string was displayed by a DLL")) ;
80
case WM_DESTROY: PostQuitMessage (0) ; return 0 ; } return DefWindowProc (hwnd, message, wParam, lParam) ; } 6. t ch dich l Project th hai phu thu c (dependencies) vo Project th nh t va th mu c Output cung ta m cua hai Project la ../Release. 7. Dich v chay chng trnh. y chung ta co hai phin bn cua mt hm trong th vin lin kt ng c s dung, i u nay cho php dung cc hm co h tr Unicode trong trng hp h thng co h tr v ngc lai s dung mt hm khng co Unicode , thng tn cua ham se co thm ch W n u co h tr Unicode v A nu khng. ng thi chung ta cng t h y trong ma cua th vi n co m t ham DllMain , hm ny co vai tro tng t nh ham WinMain trong m t chng trinh . Tc dung cua hm DllMain l khi ta o va thu h i b nh va nhng th lin quan khac , chung ta s bn ti vn ny cui chng, hi n ta i chi c n return TRUE la n . i u bi n con la i co le la inh danh EXPORT . Cc hm trong mt th vin lin kt ng c s du ng bi cac ng du ng khac phai c xu t kh u . i u nay khng lin quan ti cc vn thng mai thng thng m ch l mt ch thi m bo trnh bin dich s thm tn hm vo th vin import simpledll .lib trinh lin k t co th a cac thng tin phu h p vao chng trinh (file *.exe) co th nap cc th vin dll khi chng trnh chay . inh danh EXPORT con bao g m chi inh lp cha __declspec(dllexport) v mt ch thi tin x l if extern C phong trng h p file header c bin dich theo ki u C++. i u nay ngn ch n trinh bin dich khoi cac li trung tn cua cac ham C ++ v cho php cc th vin lin kt ng co th c s du ng bi ca cac chng trinh C va C++. i m vao va i m thoat cua th vin (Entry and Exit Point) Hm DllMain c gi n khi th vin lin kt ng ln u tin c nap vo b nh thc hin v khi no kt thuc nhim vu (bi loai khoi b nh ). Tham s u tin cua ham DllMain la handle ti instance cua th vi n. N u nh th vi n co s du ng cac tai nguyn oi hoi mt handle instance (ch ng ha n nh cac h p thoa i ), chung ta nn lu lai hInstance vo m t bi n toan cu c . Tham s cu i cung cua ham DllMain c d tr danh cho h t h ng s dung. Tham s fdwReason co th la m t trong 4 gi tri ch ra tai sao Windows lai gi ti hm DllMain. Trong cac mu c ti p theo chung ta nn nh r ng m t chng trinh n co th c
81
82
83
84
85
86
Bi t r ng cac ID cua cc control cua Dialog trn nh sau : cc ID cua cc Edit Text tng ng vi cac Static Text Canh a , Canh b , Canh c l n l t la : ID_CANHA, ID_CANHB, ID_CANHC, ID cua Static 1 l ID_KQKT, ID cua Static 2 l ID_DTCV, ID cua cac Button Kiem tra va Thoat la ID _KIEMTRA, ID_THOAT. Hy vit hm x l cho Dialog trn sau cho khi nh n vao nut Kiem tra thi chng trinh se ki m tra xem ba s nguyn c nh p va 3 Edit text tng ng co la 3 canh cua 1 tam giac hay khng , k t qua ki m tra c thng bao qua Static 1. Trong trng h p la 3 canh cua 1 tam giac hay tinh va hi n thi chu vi , di n tich cua tam gic qua Static 2 v khi ngi dung nhn vo nut Thoat s kt thuc Dialog. Bi s 2 a) Hy trnh by (a ra ) dang n gin nht cua mt hm x l thng ip ca s chnh trinh (hm Window Proc). b) Gi s chng trnh ch co mt muc menu Help , trong o co 2 muc menu con l Contents va About , hy vit hm x l thn g i p ca s chng trinh sao cho khi ngi dung cho n cac mu c trong menu Help chng trinh se hi n thi cac thng bao (hm Message Box) tng ng va khi ngi dung nh n chu t trai vao 1 vi tr trn mn hnh, hy in ra mt thng bao v to a chu t ta i vi tri o (hm TextOut). s 2: Bi s 1 Vi t ham x ly h p thoa i sau:
87
Cc iu khin XA , YA, XB, YB, XC, YC la to a 3 inh trn m t ph ng to a (nguyn). Khi nh n nut Tinh chu vi hay tnh chu vi cua tam gic tao thnh bi 3 inh A, B, C va hi n thi ln IDC _KQ. Nh n Thoat thoat khoi h p thoa i va nh n Tinh dien tich se tnh din tch v hin thi nh trong phn tnh chu vi Bi s 2 a) Hy trnh by (a ra) dang n gin nht cua mt hm x l thng ip ca s ch o m t h p thoa i. b) Hy vit hm WndProc cho mt chng trnh co h thng menu gm 1 muc File , trong o co cac mu c con vi cac chc nng sau : Menu1, Menu2, khi ngi dung nhn vo cc muc ny ch cn a ra thng bo n gin , muc Exit thot khoi chng trnh. s 3: Bi s 1 Vi t ham x ly h p thoa i sau:
Cc iu khin XA , YA, XB, YB, XC, YC la to a 3 inh trn m t ph ng ta (nguyn). Khi nh n nut Tinh chu vi hay tinh chu vi cua tam giac ta o thanh bi 3 inh A, B, C va hi n thi ln IDC _KQ. Nh n Thoat thoat khoi h p thoa i va nh n Tinh dien tich se tnh din tch v hin thi nh trong ph n tinh chu vi
88
89