Jump to content

SUBIECTE NOI
« 1 / 5 »
RSS
Deparazitare externa pisici fara ...

Seriale turcesti/coreene online H...

Merita un Termostat Smart pentru ...

Sfat achizitie MTB Devron Riddle
 Problema mare cu parintii= nervi ...

switch microtik

Permis categoria B la 17 ani

Sfaturi pentru pregatirea de eval...
 Crapaturi placa

cum imi accesez dosarul electroni...

Momentul Aprilie 1964

Sursa noua - zgomot ?
 A fost lansat Ubuntu 24.04 LTS

Pareri apartament in zona Berceni?

Free streaming SkyShowtime de la ...

Skoda Fabia 1.0 TSI (110 CP)- 19 ...
 

Visual C++ 2010 Express pentru tăți

- - - - -
  • Please log in to reply
24 replies to this topic

#1
dani.user

dani.user

    Guru Member

  • Grup: Senior Members
  • Posts: 30,238
  • Înscris: 24.02.2007
Intrucat foarte multi elevi/studenti de buna voie sau la indicatiile altora, doresc compilatoare de pe vremea raposatului, creez acest mic tutorial pentru cei ce doresc sa traiasca totusi in deceniul asta.

Acest tutorial presupune ca aveti habar ce e C, ce e C++ si, mai ales, ca ati citit Lucruri pe care orice programator ar trebui să le ştie
  • Se descarca & instaleaza Microsoft Visual C++ 2010 Express (am ales versiunea 2010 fiindca cea 2012 nu mai functioneaza sub Windows XP)
  • Se creaza un nou proiect
    Attached File  newproject.png   42.38K   174 downloads
    • Se alege un proiect de tip Win32 Console Application si ii se da un nume respectiv calea unde va fi stocat pe disc
    • Se debifeaza Create directory for solution. Solution este un grup de proiecte interconectate, nu este nevoie acum de asa ceva.
    • In continuare se alege tot Console application si se bifeaza Precompiled header. Precompiled header creaza un cache al fisierelor header des folosite dar rar actualizate (cum sunt cele ale biblioteciilor de sistem), marind astfel viteza de compilare.
      Attached File  newproject2.png   29.15K   197 downloads
      • Windows application - Creaza un executabil Windows fara consola vizibila
      • Console application - Creaza un executabil Windows avand consola vizibila
      • DLL - Creaza o librarie de functii ce pot fi folosite din mai multe aplicatii, alaturi de ele fiind necesar a se distribui si fisierul DLL
      • Static library - Creaza o librarie de functii ce va fi linked in fiecare executabil ce o cere
  • Se analizeaza ce s-a obtinut dupa creerea proiectului
    Attached File  ecran1.png   91.85K   193 downloads
    • Fisierul cpp include stdafx.h (Precompiled header), in acesta fiind indicat a se include headerele de sistem folosite
    • _TCHAR WTF??
      • Precum ati observat, multe aplicatii Windows permit folosirea/afiseaza diacritice.
      • Solutia Microsoft pentru aceasta problema a fost introducerea unui typedef TCHAR sau _TCHAR care, in functie de setarile proiectului (#ifdef  _UNICODE), va deveni char (daca unicode nu e activat) sau wchar_t (daca Unicode e activat)
      • wchar_t stocheaza informatia pe 16-biti, dublu fata de char
      • Daca se tine mouse-ul peste _TCHAR, IDE-ul afisa typedef wchar_t _TCHAR
  • C sau C++?
    • Default, un proiect nou realizat in Visual C++ e de tip C++
    • Se poate specifica insa ca proiectul se doreste a fi unul de C, din proprietatiile proiectului
      Attached File  properties1.png   38.28K   192 downloads
  • Se includ headerele necesare
    • Se poate observa ca in stdafx.h sunt incluse deja cateva headere
      Attached File  ecran2.png   91.93K   193 downloads
    • Daca dorim iostream, des utilizat in C++, includem headerul acolo #include <iostream>
    • Nu, nu e iostream.h, standardul zice ca e iostream
  • Incepem sa scriem cod
    • De ce e cout subliniat cu rosu??
      Attached File  ecran3.png   94.7K   201 downloads
      • Fiindca standardul zice ca: elemente din biblioteca standard se gasesc in namespace-ul std
      • Cea mai simpla solutie pentru a rezolva aceasta "problema" este using namespace std;
        Attached File  ecran4.png   107.86K   163 downloads
    • Si printf si cout??
      • Care-i problema? Nu te opreste nimeni sa folosesti functii din libraria standard C in C++
  • Debug & Release sau de ce lu' vecinu ii da eroare programul cand il deschide?
    • In mod normal, fiecare proiect nou create vine in 2 "nunate": Debug si Release.
    • Varianta Debug e gandita pentru a fi cat mai usor sa gasesti & repari buguri ale aplicatiei
    • Varianta Release e gandita pentru a avea cod cat mai rapid si cat mai lipsit de informatii "inutile"
    • Atunci cand se deschide, de exemplu, stdio.h sunt pomenite o gramada de functii, dar nu e nicaieri codul acestora. Asta deoarece codul se afla in biblioteca standard. Ii zice standard fiindca e gandita in asa fel incat pe orice platforma (ce se vrea a respecta standardul) lucrezi, sa ai la dispozitie printf(), memcpy() ...
    • Pe vremuri, libraria standard era cuprinsa in msvcrt.dll (se gaseste automat in toate versiunile Windows moderne). Microsoft au decis insa, ca pe masura ce scot noi compilatoare/versiuni ale bibliotecii sa nu inlocuiasca versiunea veche, ce sa creeze altele noi. Astfel au aparut msvcr70.dll (2003), msvcr80.dll (2005), msvcr90.dll (2008), msvcr100.dll (2010) etc.
    • Fiecare din acestea vin insa din nou in 2 "sortimente" varianta ce contine debug symbols (utile la debug), msvcr100d.dll, si varianta obisnuita
    • Atunci cand se compileaza varianta Debug, programul va fi legat de varianta Debug a librariei standard
      Attached File  ecran4.png   107.86K   163 downloads
    • In imaginea de mai sus, se observa in ecranul de Output ca au fost incarcate simbolurile de Debug pentru, printre altele, msvcr100d.dll

      Quote

      Loaded 'C:\WINDOWS\system32\msvcr100d.dll', Symbols loaded.
    • Se mai observa insa si ca, pentru DLL-uri de sistem, aceste simboluri nu au fost incarcate, neavand instalata o versiune Windows ce sa le contina

      Quote

      Loaded 'C:\WINDOWS\system32\kernel32.dll', Cannot find or open the PDB file
    • Atunci cand aplicatia se doreste a fi rulata pe alt sistem, trebuie instalate inainte aceste librarii standard, oferite sub numele de Microsoft Visual C++ 2010 (in acest caz) Redistributable Package
    • De asemenea, cand se da o aplicatie altcuiva, se va da versiunea Release
  • Debugging
    • Acest subiect nu este unul usor, insa doresc sa mentionez cel mai simplu mod de a face debug cu ajutorul Visual C++: breakpoints.
    • Printr-un click in stanga editorului de cod, se activeaza un breakpoint (marcat cu o bulina rosie), cauzand suspendarea executiei programului cand ajunge in acel punct. In acel moment, prin hover peste orice variabila din scope, se poate citi valoarea curenta a acestia.
      Attached File  ecran7.png   103.8K   174 downloads
    • In ecranele de jos se pot observa o sumedenie de alte informatii foarte utile in cazul realizarii unui Debug.
  • Utilizarea diacriticelor
    • Menţionam mai devreme de posibilitatea utilizării diacriticelor. Atunci cand se foloseste wchar_t in loc de char apar cateva probleme.
      • Functiile ce se asteapta sa primeasca un sir de caractere sub forma char* stiu ca sirul a ajuns la sfarsit cand intalnesc primul caracter nul (\0)
      • In cazul unui sir wchar_t*, caracterele obisnuite din alfabetul latin vor necesita tot un singur byte, celalalt fiind \0; derutand astfel functiile ce se asteapta sa primeasca un sir sub forma char*
      • Prin urmare exista un alt set de functii in libraria standard C ce se ocupa de lucrul cu siruri de caractere wide, numele lor incepand cu wcs in loc de str. In cazul C++ se foloseste wcout in locul lui cout
        Attached File  ecran5.png   117.59K   131 downloads
        Resultatul este
        Lungime sir1: 4, sir2: 6
        Lungime eronata sir2: 1
        
        
    • Asa cum au procedat cu TCHAR, cei de la Microsoft au creat macro-uri si pentru L si pentru functiile de lucru cu sirurile de caractere. Astfel, daca proiectul este unicode, se vor apela functiile pentru lucrul cu siruri wide, in caz contrar, cele pentru lucrul cu siruri obisnuite
      Attached File  ecran6.png   115.55K   119 downloads
      Afişez şirul: "abcd ăîşţâ" de lungime 10
      
    • Nota: in mod normal, consola nu va afisa diacritice, daca se doreste acest lucru trebuind precizat, caz in care nu se vor mai putea afisa decat siruri de caractere wide
      _setmode(_fileno(stdout), _O_U16TEXT);
      
  • Mentionam de biblioteci standard
    • Acestea ofera multe facilitati, insa nu intotdeauna tot ce am avea nevoie.
    • Se observa ca in respectiva lista nu se pomeneste nimic de interfete grafice, lucrul in retea, etc. Pentru acestea lucrurile nu mai sunt asa standard, respectiv usor portabile de la un sistem de operare la altul, trebuind sa apelam la biblioteciile dezvoltate si incluse, in acest caz, in Windows.
    • Cu mici exceptii, toate DLL-urile ce le vedeti in Windows, contin, privite la modul mai simplu, functii ce pot fi utile in diverse aplicatii.
    • Visual C++ 2010 instaleaza si SDK-ul pentru Windows, adica setul de headere ce descriu aceste functii alaturi de diverse constante si alte informatii necesare, precum si librariile de import pentru a incarca automat in memorie adresele respectivelor functii.
    • Ce ofera Windows dezvoltatorilor este cunoscut sub denumirea WinAPI si se gaseste in detaliu explicat pe MSDN.
    • Primul pas pentru a incepe sa se faca uz de WinAPI este
      #include <Windows.h>
      
    • Mare parte din WinAPI este procedural, pentru a putea fi accesat din cat mai multe limbaje/tehnologii.
    • Restul este orientat pe obiect, utilizand o tehnologie mai aparte pe nume COM, fiind deasemenea independenta de limbaj

Va urma

#2
Krisler12

Krisler12

    Senior Member

  • Grup: Senior Members
  • Posts: 2,761
  • Înscris: 21.04.2009
Vreau sa vad daca are elemente GUI (butoane, listboxuri etc.) daca vrei sa faci un proiect GUI fiindca eu stiam ca varianta Expres (Free) nu ofera acest lucru.

#3
neagu_laurentiu

neagu_laurentiu

    Guru Member

  • Grup: Senior Members
  • Posts: 40,604
  • Înscris: 30.07.2003

 Krisler12, on 23 februarie 2013 - 13:42, said:

eu stiam ca varianta Expres (Free) nu ofera acest lucru
Ba ofera.

#4
dani.user

dani.user

    Guru Member

  • Grup: Senior Members
  • Posts: 30,238
  • Înscris: 24.02.2007

Quote

Ok, dar suntem in 2013, nu vreau sa scriu tot aplicatii care aduna numere in DOS, vreau sa invat Java/C# sa fac aplicatii adevarate...

Nimic mai fals. Aceste aplicatii interactioneaza cu utilizatorul prin intermediul consolei, insa sunt aplicatii Windows. Si ce mod mai simplu de a demonstra asta, decat prin cateva exemple.
Ia incercati, puteti realiza asta sub MS-DOS?

  • MessageBox - Afisarea unui mesaj de atentionare sau a unei intrebari simple
    #include "stdafx.h"
    
    using namespace std;
    
    int _tmain(int argc, _TCHAR* argv[])
    {
    	if (MessageBox(HWND_DESKTOP, 
    		_T("Salut\r\nDoreşti să continui?"), 
    		_T("Titlu"),
    		MB_YESNO | MB_ICONQUESTION) == IDYES)
    	{
    		MessageBox(HWND_DESKTOP,
    			_T("OK"),
    			_T("Titlu 2"),
    			MB_ICONEXCLAMATION);
    	}
    	return 0;
    }
    
    
  • Multithreading
    Spre deosebire de MS-DOS, sub Windows ruleaza mai multe procese simultan, iar in cadrul fiecarui proces se pot intampla mai multe in acelasi timp, pot rula mai multe thread-uri.
    #include "stdafx.h"
    
    using namespace std;
    
    DWORD WINAPI functieThreadSecundar(LPVOID parametru)
    {
    	int* x = static_cast<int*>(parametru);
    	for (int i = 0; i < *x; i++)
    	{
    		_tprintf(_T("\t\tThread secundar: %d\r\n"), i);
    		Sleep(250); //pauza 250ms
    	}
    	return 0;
    }
    
    int _tmain(int argc, _TCHAR* argv[])
    {
    	HANDLE threadSecundar;
    	int numaraPanaLa = 10;
    	int* numaraInParalelPanaLa = new int;
    	*numaraInParalelPanaLa = 10*4;
    
    	threadSecundar = CreateThread(
    		NULL,
    		0,
    		functieThreadSecundar, //threadul secundar va executa aceasta functie
    		numaraInParalelPanaLa, //parametru transmis functiei 
    		0,
    		NULL);
    
    	for (int i = 0; i < numaraPanaLa; i++)
    	{
    		_tprintf(_T("Thread principal: %d\r\n"), i);
    		Sleep(1000); //pauza 1000ms
    	}
    
    	WaitForSingleObject(threadSecundar, INFINITE); //asteptam terminarea executiei threadului secundar
    	delete numaraInParalelPanaLa;
    
    	return 0;
    }
    
    

    Thread principal: 0
    		Thread secundar: 0
    		Thread secundar: 1
    		Thread secundar: 2
    		Thread secundar: 3
    Thread principal: 1
    		Thread secundar: 4
    		Thread secundar: 5
    		Thread secundar: 6
    		Thread secundar: 7
    		Thread secundar: 8
    Thread principal: 2
    		Thread secundar: 9
    		Thread secundar: 10
    		Thread secundar: 11
    		Thread secundar: 12
    Thread principal: 3
    		Thread secundar: 13
    		Thread secundar: 14
    		Thread secundar: 15
    Thread principal: 4
    		Thread secundar: 16
    		Thread secundar: 17
    		Thread secundar: 18
    		Thread secundar: 19
    		Thread secundar: 20
    Thread principal: 5
    		Thread secundar: 21
    		Thread secundar: 22
    		Thread secundar: 23
    		Thread secundar: 24
    Thread principal: 6
    		Thread secundar: 25
    		Thread secundar: 26
    		Thread secundar: 27
    Thread principal: 7
    		Thread secundar: 28
    		Thread secundar: 29
    		Thread secundar: 30
    		Thread secundar: 31
    Thread principal: 8
    		Thread secundar: 32
    		Thread secundar: 33
    		Thread secundar: 34
    		Thread secundar: 35
    Thread principal: 9
    		Thread secundar: 36
    		Thread secundar: 37
    		Thread secundar: 38
    		Thread secundar: 39
    
    


#5
dani.user

dani.user

    Guru Member

  • Grup: Senior Members
  • Posts: 30,238
  • Înscris: 24.02.2007

Quote

Bine bine, dar m-am saturat de consola, vreau sa creez o interfata grafica

Bun ... pai, de unde sa incep?

[5 minutes later]

Asa. Windows-ul, cum de altfel ii zice si numele, iti permite sa creezi interfete grafice de cand e. API-ul de baza e unul procedural (adica il poti folosi linistit din C, nu-i nevoie de ++) si e similar cu cel pe 16-biti de acum 20 ani, urmele "mostenirii" fiind destul de evidente pe ici pe colo si ducand uneori la intrebari de genul: asta de ce e asa?

Problema construirii unei interfete grafice nu are o solutie unica. Daca n-ai ce face, nu te opreste nimeni din a desena manual linie cu linie, punct cu punct, fiecare element si a verifica constant coordonatele mouse-ului.

Ce voi prezenta mai departe e metoda standard sau sa-i zic clasica de creere a interfetelor grafice sub Windows si are urmatoarele particularitati:
  • Toate elementele ce apar pe ecran (casute de text, butoane, etc), si chiar ecranul insusi, poarta denumirea de Window, sunt create cu ajutorul functiei CreateWindow() (respectiv CreateWindowEx()) si sunt "tinute minte" sub forma unui tip de date (un numar practic, similar unui pointer) denumit HWND.
  • Spre deosebire de o aplicatie in linie de comanda, intr-o aplicatie GUI, intrarile din partea utilizatorului devin mult mai complexe: acesta scrie ceva intr-o casuta de text, apasa pe ceva, chiar misca doar mouse-ul peste un element. Pentru a putea reactiona la toate acestea, programul trebuie instiintat cumva ca un anumit eveniment a avut loc. In cazul WinAPI acest lucru se realizeaza prin mesaje. Practic, threadul principal al programului va intreba in continuu daca nu are de primit un mesaj nou, iar, daca raspunsul este afirmativ, va trece la procesarea acestuia
    // Main message loop:
    while (GetMessage(&msg, NULL, 0, 0))
    {
    TranslateMessage(&msg);
    DispatchMessage(&msg);
    }
    
    
    De aici se observa usor o potentiala problema. Daca incep o operatiune de durata, ce imi va bloca threadul principal al aplicatiei, interfata grafica va ingheta
Sa trecem la treaba

Asa cum s-a vazut in primul post, cand dorim sa creem un nou proiect, Visual C++ ne intreaba daca nu dorim o Aplicatie Windows. Alegand acest sablon, el ne va oferi ceva cod de-a gata care afiseaza un ecran.

Quote

Ce-i asta??? Parca programam in C...

C si este Posted Image

La prima vedere, sablonul pare destul de complex, dar voi incerca sa-l explic pas cu pas si sa-l simplific, eliminand unele elemente mai putin necesare pentru inceput. Pana la final, va fi un program ce permite adunarea a 2 numere (foarte complex nu?) si care prezinta si cum se poate desena ceva folosind acest API.
  • Crearea unei ferestre
    Pana la urma, tot ce dorum sa afisam, deocamdata, se va regasi intr-o fereastra. Aceasta se creaza foarte usor apeland CreateWindow(), precum se vede din codul functiei InitInstance
    BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
    {
    hInst = hInstance; // Store instance handle in our global variable
    
    hEcranPrincipal = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
    CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);
    
    if (!hEcranPrincipal)
    {
    return FALSE;
    }
    
    ShowWindow(hEcranPrincipal, nCmdShow);
    UpdateWindow(hEcranPrincipal);
    
    return TRUE;
    }
    
    
    Dar stai putin ... de unde stie el ce fereastra vreau eu? O casuta text e destul de standard, dar o fereastra mai are si o gramada de elemente particulare:
    • Icon
    • Meniuri
    • Culoare de fundal
    • Etc
    Asa cum se observa, primul parametru al functiei CreateWindow() reprezinta un sir ce caractere ce defineste tipul ecranului ce va fi creat. Daca pentru elementele standard exista deja clase predefinite, pentru ecranul aplicatiei vom trebui sa facem acest lucru manual, asa cum se vede din codul functiei MyRegisterClass
    ATOM MyRegisterClass(HINSTANCE hInstance)
    {
    WNDCLASSEX wcex;
    
    wcex.cbSize = sizeof(WNDCLASSEX);
    
    wcex.style = CS_HREDRAW | CS_VREDRAW;
    wcex.lpfnWndProc = WndProc;
    wcex.cbClsExtra = 0;
    wcex.cbWndExtra = 0;
    wcex.hInstance = hInstance;
    wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_GUIEXAMPLE));
    wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
    wcex.hbrBackground = (HBRUSH)(COLOR_3DSHADOW);
    wcex.lpszMenuName = 0;
    wcex.lpszClassName = szWindowClass;
    wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));
    
    return RegisterClassEx(&wcex);
    }
    
    
  • Window Proc
    Se observa din codul precedent ca unui element al structurii ii este atribuita adresa functiei WndProc. Ce inseamna asta? Asta inseamna ca, de fiecare data cand se primeste un mesaj legat de fereastra principala (sau vreun copil al ei) va fi apelata aceasta functie.
  • "Popularea" ferestrei
    Dupa ce fereastra principala a fost construita se primeste mesajul WM_CREATE. In acest moment stim ca putem construi si celelalte elemente ce vor compune fereastra principala.
    void ConstruiesteElemente(HWND hEcranParinte)
    {
    HWND hTemp;
    hDefaultFont = (HFONT)GetStockObject(DEFAULT_GUI_FONT); //aleg fontul implicit din sistem
    
    hTemp = CreateWindow(_T("STATIC"), _T("Introduceţi valoarea A:"), WS_CHILD | WS_VISIBLE, 10, 20, 140, 20, hEcranParinte, NULL, hInst, NULL);
    SendMessage(hTemp, WM_SETFONT, (WPARAM)hDefaultFont, TRUE);
    hCasutaTextA = CreateWindowEx(WS_EX_CLIENTEDGE, _T("EDIT"), _T("1"), WS_BORDER | WS_CHILD | WS_VISIBLE, 140, 20, 100, 20, hEcranParinte, NULL, hInst, NULL);
    SendMessage(hCasutaTextA, WM_SETFONT, (WPARAM)hDefaultFont, TRUE);
    
    hTemp = CreateWindow(_T("STATIC"), _T("Introduceţi valoarea B:"), WS_CHILD | WS_VISIBLE, 10, 50, 140, 20, hEcranParinte, NULL, hInst, NULL);
    SendMessage(hTemp, WM_SETFONT, (WPARAM)hDefaultFont, TRUE);
    hCasutaTextB = CreateWindowEx(WS_EX_CLIENTEDGE, _T("EDIT"), _T("2"), WS_BORDER | WS_CHILD | WS_VISIBLE, 140, 50, 100, 20, hEcranParinte, NULL, hInst, NULL);
    SendMessage(hCasutaTextB, WM_SETFONT, (WPARAM)hDefaultFont, TRUE);
    
    hTemp = CreateWindow(_T("STATIC"), _T("Rezultat:"), WS_CHILD | WS_VISIBLE, 10, 80, 140, 20, hEcranParinte, NULL, hInst, NULL);
    SendMessage(hTemp, WM_SETFONT, (WPARAM)hDefaultFont, TRUE);
    hRezultat = CreateWindow(_T("STATIC"), _T("3"), WS_CHILD | WS_VISIBLE | SS_RIGHT, 140, 80, 100, 20, hEcranParinte, NULL, hInst, NULL);
    SendMessage(hRezultat, WM_SETFONT, (WPARAM)hDefaultFont, TRUE);
    
    hButonSuma = CreateWindow(_T("BUTTON"), _T("Adună"), WS_CHILD | WS_VISIBLE | BS_DEFPUSHBUTTON, 250, 20, 50, 80, hEcranParinte, NULL, hInst, NULL);
    SendMessage(hButonSuma, WM_SETFONT, (WPARAM)hDefaultFont, TRUE);
    }
    
    

    Pentru fiecare element creat va trebui sa-i specificam (printre altele) clasa (care determina ce vrem defapt sa creem), coordonatele unde dorim sa fie afisat elementul, ecranul parinte (cel principal in acest caz), optional textul ce dorim sa-l afisam.
    Din codul de mai sus se observa ca retin identificatorul fiecarei ferestre, mai putin al celor doua ajutatoare pe care nu le mai accesez ulterior: "Introduceţi valoarea ..."
  • Apasarea butonului

    Cand stiu ca s-a apasat butonul? Conform documentatiei, atunci cand este apasat un buton se transmite mesajul WM_COMMAND iar parametrul lParam contine identificatorul (HWND) butonului. Din cod se poate observa ca, atunci cand se intampla asa, va fi apelata functia Aduna_Click()
  • Adunarea numerelor si afisarea rezultatului

    In interiorul functiei Aduna_Click() se realizeaza efectiv suma celor 2 numere introduse.
    void Aduna_Click(void)
    {
    //s-a apasat butonul Adună
    TCHAR textA[128] = {0};
    TCHAR textB[128] = {0};
    
    Edit_GetText(hCasutaTextA, textA, sizeof(textA) / sizeof(TCHAR)); //citim textul introdus in casuta A
    Edit_GetText(hCasutaTextB, textB, sizeof(textB) / sizeof(TCHAR)); //citim textul introdus in casuta B
    
    double a = _ttof(textA); //extrag un double din sirul de caractere
    double b = _ttof(textB); //extrag un double din sirul de caractere
    
    double suma = a + b;
    TCHAR textSuma[128] = {0};
    _stprintf_s(textSuma, 128, _T("%f"), suma); //adaug valoarea rezultatul in sirul de caractere
    
    Edit_SetText(hRezultat, textSuma);
    }
    
    

    Nota: In casutele de text se stocheaza siruri de caractere, prin urmare va trebui atat sa extragem numerele din ele inainte de a le aduna, precum si transforma rezultatul inapoi intr-un sir de caractere inainte de afisare.

    Macrouri precum Edit_GetText() si Edit_SetText() se gasesc in WindowsX.h si au rolul unor prescurtari.
  • Elemente de desenare

    Vrei sa desenezi ceva si n-ai auzit decat de graphics.h?
    Te miri de ce nu-ti merge BGI pentru DOS sub Windows modern?
    Nu, nu trebuie sa schimbi limbajul si s-o iei de la capat, poti bine-mersi folosi API-ul furnizat de Windows pentru desenare: GDI.

    Principiul de baza in desenarea cu GDI este urmatorul: sistemul stie cand un chenar trebuie redesenat si iti trimite un mesaj (WM_PAINT) prin care iti va cere sa redesenezi. Spre deosebire de sistemele pentru DOS, in acest caz poti folosi 16.7 mil culoari, iar, pentru desenarea textului poti folosi orice font instalat in sistem.

    void Deseneaza(HDC hdc)
    {
    SetBkMode(hdc, TRANSPARENT); //fundal transparent pentru desenare
    
    //specific culoarea textului (24 biti/pixel - 16.7 mil culori posibile) si tin minte culoarea precedenta
    COLORREF culoarePrecedenta = SetTextColor(hdc, RGB(0x5F, 0, 0xFF));
    
    RECT rect; //definesc un dreptunghi
    rect.top = 100;
    rect.left = 500;
    rect.right = rect.left + 200;
    rect.bottom = rect.top + 50;
    
    //creez "pixuri" pentru a desena conturul dreptunghiului
    HPEN hPens[4] =
    {
    CreatePen(PS_SOLID, 2, RGB(0, 0, 0)),
    CreatePen(PS_DASH, 1, RGB(0, 0xA0, 0)),
    CreatePen(PS_DOT, 1, RGB(0, 0, 0xCC)),
    CreatePen(PS_DASHDOT, 1, RGB(0xB4, 0, 0)),
    };
    
    MoveToEx(hdc, rect.left, rect.top, NULL);
    SelectObject(hdc, hPens[0]);
    LineTo(hdc, rect.right, rect.top);
    SelectObject(hdc, hPens[1]);
    LineTo(hdc, rect.right, rect.bottom);
    SelectObject(hdc, hPens[2]);
    LineTo(hdc, rect.left, rect.bottom);
    SelectObject(hdc, hPens[3]);
    LineTo(hdc, rect.left, rect.top);
    
    for (int i = 0; i < 4; i++) DeleteObject(hPens[i]);
    
    rect.top += 10; //pentru a desena textul putin mai jos
    DrawText(hdc, _T("Ia uite că pot desena\r\n şi fără graphics.h"), -1, &rect, DT_CENTER);
    
    rect.top += 200;
    rect.right += 200;
    rect.bottom += 200;
    
    HFONT hAltFont = CreateFont(-MulDiv(14, GetDeviceCaps(hdc, LOGPIXELSY), 72), //dimensiune comparabila cu cea folosita din editoarele de text
    0,
    0,
    0,
    FW_NORMAL, //grosime
    TRUE, //italic
    FALSE, //underline
    FALSE, //strikeout
    DEFAULT_CHARSET,
    OUT_DEFAULT_PRECIS,
    CLIP_DEFAULT_PRECIS,
    CLEARTYPE_QUALITY,
    FF_DONTCARE,
    _T("Comic Sans MS"));
    HFONT hFontPrecedent = (HFONT)SelectObject(hdc, hAltFont);
    
    DrawText(hdc, _T("Desenat folosind Comic Sans MS"), -1, &rect, DT_LEFT);
    
    DeleteObject(hAltFont);
    SelectObject(hdc, hFontPrecedent);
    }
    
    
La final programul arata cam asa
Attached File  gdi.png   29.13K   264 downloads
iar codul este:
// GUIExample.cpp : Defines the entry point for the application.
//

#include "stdafx.h"
#include "GUIExample.h"

#define MAX_LOADSTRING 100

// Global Variables:
HINSTANCE hInst; // current instance
TCHAR szTitle[MAX_LOADSTRING]; // The title bar text
TCHAR szWindowClass[MAX_LOADSTRING]; // the main window class name

HWND hEcranPrincipal; //ecranul principal
HFONT hDefaultFont; //fontul implicit
HWND hCasutaTextA; //casuta text pentru A
HWND hCasutaTextB; //casuta text pentru B
HWND hButonSuma; //buton suma
HWND hRezultat; //label pentru afisare rezultat

// Forward declarations of functions included in this code module:
ATOM MyRegisterClass(HINSTANCE hInstance);
BOOL InitInstance(HINSTANCE, int);
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
void Deseneaza(HDC hdc);
void ConstruiesteElemente(HWND);
void Aduna_Click(void);

int APIENTRY _tWinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPTSTR lpCmdLine,
int nCmdShow)
{
UNREFERENCED_PARAMETER(hPrevInstance);
UNREFERENCED_PARAMETER(lpCmdLine);

// TODO: Place code here.
MSG msg;

// Initialize global strings
LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
LoadString(hInstance, IDC_GUIEXAMPLE, szWindowClass, MAX_LOADSTRING);
MyRegisterClass(hInstance);

// Perform application initialization:
if (!InitInstance (hInstance, nCmdShow))
{
return FALSE;
}

// Main message loop:
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}

return (int) msg.wParam;
}

ATOM MyRegisterClass(HINSTANCE hInstance)
{
WNDCLASSEX wcex;

wcex.cbSize = sizeof(WNDCLASSEX);

wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_GUIEXAMPLE));
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_3DSHADOW);
wcex.lpszMenuName = 0;
wcex.lpszClassName = szWindowClass;
wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));

return RegisterClassEx(&wcex);
}

//
// FUNCTION: InitInstance(HINSTANCE, int)
//
// PURPOSE: Saves instance handle and creates main window
//
// COMMENTS:
//
// In this function, we save the instance handle in a global variable and
// create and display the main program window.
//
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
hInst = hInstance; // Store instance handle in our global variable

hEcranPrincipal = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);

if (!hEcranPrincipal)
{
return FALSE;
}

ShowWindow(hEcranPrincipal, nCmdShow);
UpdateWindow(hEcranPrincipal);

return TRUE;
}

//
// FUNCTION: WndProc(HWND, UINT, WPARAM, LPARAM)
//
// PURPOSE: Processes messages for the main window.
//
// WM_PAINT - Paint the main window
// WM_DESTROY - post a quit message and return
//
//
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
PAINTSTRUCT ps;
HDC hdc;
HFONT hFontPrecedent;

switch (message)
{
case WM_CREATE:
ConstruiesteElemente(hWnd);
break;
case WM_COMMAND:
if ((HWND)lParam == hButonSuma)
{
Aduna_Click();
}
break;
case WM_PAINT:
hdc = BeginPaint(hWnd, &ps);

hFontPrecedent = (HFONT)SelectObject(hdc, hDefaultFont); //tin minte fontul precedent
Deseneaza(hdc);
SelectObject(hdc, hFontPrecedent); //pun la loc fontul precedent

EndPaint(hWnd, &ps);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}

void ConstruiesteElemente(HWND hEcranParinte)
{
HWND hTemp;
hDefaultFont = (HFONT)GetStockObject(DEFAULT_GUI_FONT); //aleg fontul implicit din sistem

hTemp = CreateWindow(_T("STATIC"), _T("Introduceţi valoarea A:"), WS_CHILD | WS_VISIBLE, 10, 20, 140, 20, hEcranParinte, NULL, hInst, NULL);
SendMessage(hTemp, WM_SETFONT, (WPARAM)hDefaultFont, TRUE);
hCasutaTextA = CreateWindowEx(WS_EX_CLIENTEDGE, _T("EDIT"), _T("1"), WS_BORDER | WS_CHILD | WS_VISIBLE, 140, 20, 100, 20, hEcranParinte, NULL, hInst, NULL);
SendMessage(hCasutaTextA, WM_SETFONT, (WPARAM)hDefaultFont, TRUE);

hTemp = CreateWindow(_T("STATIC"), _T("Introduceţi valoarea B:"), WS_CHILD | WS_VISIBLE, 10, 50, 140, 20, hEcranParinte, NULL, hInst, NULL);
SendMessage(hTemp, WM_SETFONT, (WPARAM)hDefaultFont, TRUE);
hCasutaTextB = CreateWindowEx(WS_EX_CLIENTEDGE, _T("EDIT"), _T("2"), WS_BORDER | WS_CHILD | WS_VISIBLE, 140, 50, 100, 20, hEcranParinte, NULL, hInst, NULL);
SendMessage(hCasutaTextB, WM_SETFONT, (WPARAM)hDefaultFont, TRUE);

hTemp = CreateWindow(_T("STATIC"), _T("Rezultat:"), WS_CHILD | WS_VISIBLE, 10, 80, 140, 20, hEcranParinte, NULL, hInst, NULL);
SendMessage(hTemp, WM_SETFONT, (WPARAM)hDefaultFont, TRUE);
hRezultat = CreateWindow(_T("STATIC"), _T("3"), WS_CHILD | WS_VISIBLE | SS_RIGHT, 140, 80, 100, 20, hEcranParinte, NULL, hInst, NULL);
SendMessage(hRezultat, WM_SETFONT, (WPARAM)hDefaultFont, TRUE);

hButonSuma = CreateWindow(_T("BUTTON"), _T("Adună"), WS_CHILD | WS_VISIBLE | BS_DEFPUSHBUTTON, 250, 20, 50, 80, hEcranParinte, NULL, hInst, NULL);
SendMessage(hButonSuma, WM_SETFONT, (WPARAM)hDefaultFont, TRUE);
}

void Aduna_Click(void)
{
//s-a apasat butonul Adună
TCHAR textA[128] = {0};
TCHAR textB[128] = {0};

Edit_GetText(hCasutaTextA, textA, sizeof(textA) / sizeof(TCHAR)); //citim textul introdus in casuta A
Edit_GetText(hCasutaTextB, textB, sizeof(textB) / sizeof(TCHAR)); //citim textul introdus in casuta B

double a = _ttof(textA); //extrag un double din sirul de caractere
double b = _ttof(textB); //extrag un double din sirul de caractere

double suma = a + b;
TCHAR textSuma[128] = {0};
_stprintf_s(textSuma, 128, _T("%f"), suma); //adaug valoarea rezultatul in sirul de caractere

Edit_SetText(hRezultat, textSuma);
}

void Deseneaza(HDC hdc)
{
SetBkMode(hdc, TRANSPARENT); //fundal transparent pentru desenare

//specific culoarea textului (24 biti/pixel - 16.7 mil culori posibile) si tin minte culoarea precedenta
COLORREF culoarePrecedenta = SetTextColor(hdc, RGB(0x5F, 0, 0xFF));

RECT rect; //definesc un dreptunghi
rect.top = 100;
rect.left = 500;
rect.right = rect.left + 200;
rect.bottom = rect.top + 50;

//creez "pixuri" pentru a desena conturul dreptunghiului
HPEN hPens[4] =
{
CreatePen(PS_SOLID, 2, RGB(0, 0, 0)),
CreatePen(PS_DASH, 1, RGB(0, 0xA0, 0)),
CreatePen(PS_DOT, 1, RGB(0, 0, 0xCC)),
CreatePen(PS_DASHDOT, 1, RGB(0xB4, 0, 0)),
};

MoveToEx(hdc, rect.left, rect.top, NULL);
SelectObject(hdc, hPens[0]);
LineTo(hdc, rect.right, rect.top);
SelectObject(hdc, hPens[1]);
LineTo(hdc, rect.right, rect.bottom);
SelectObject(hdc, hPens[2]);
LineTo(hdc, rect.left, rect.bottom);
SelectObject(hdc, hPens[3]);
LineTo(hdc, rect.left, rect.top);

for (int i = 0; i < 4; i++) DeleteObject(hPens[i]);

rect.top += 10; //pentru a desena textul putin mai jos
DrawText(hdc, _T("Ia uite că pot desena\r\n şi fără graphics.h"), -1, &rect, DT_CENTER);

rect.top += 200;
rect.right += 200;
rect.bottom += 200;

HFONT hAltFont = CreateFont(-MulDiv(14, GetDeviceCaps(hdc, LOGPIXELSY), 72), //dimensiune comparabila cu cea folosita din editoarele de text
0,
0,
0,
FW_NORMAL, //grosime
TRUE, //italic
FALSE, //underline
FALSE, //strikeout
DEFAULT_CHARSET,
OUT_DEFAULT_PRECIS,
CLIP_DEFAULT_PRECIS,
CLEARTYPE_QUALITY,
FF_DONTCARE,
_T("Comic Sans MS"));
HFONT hFontPrecedent = (HFONT)SelectObject(hdc, hAltFont);

DrawText(hdc, _T("Desenat folosind Comic Sans MS"), -1, &rect, DT_LEFT);

DeleteObject(hAltFont);
SelectObject(hdc, hFontPrecedent);
}


Ce am prezentat mai sus nu se vrea un tutorial complet pentru aceasta tehnologie, pentru asta gasiti suficienta documentatie pe net.
Alte tehnologii pentru GUI:
  • Microsoft a creat un API orientat pe obiect peste WinAPI, denumit MFC (care contine si o gramada de elemente suplimentare, gen Ribbon din Office sau ca diverse elemente din insusi Visual Studio)
  • Tot Microsoft a creat WinForms, tot orientat pe obiect, dar, de data asta bazat pe .NET Framework
  • Tot pentru .NET Framework, Microsoft au creat WPF
  • Altii au creat alte librarii (unele cross-platform) precum Qt, wxWidgets, GTK.
WinAPI nu prea mai e folosit direct in productie, insa, atunci cand nu sta seful in spatele tau, sa termini treaba cat mai repede, merita invatat si chiar folosit la proiecte pentru scoala

#6
MarianG

MarianG

    be that as it may

  • Grup: Moderators
  • Posts: 31,443
  • Înscris: 10.08.2005
o singura observatie
Atunci cand aplicatia se doreste a fi rulata pe alt sistem, se executa din terminal/consola/Command Prompt NU CU DUBLU-CLICK

#7
Krisler12

Krisler12

    Senior Member

  • Grup: Senior Members
  • Posts: 2,761
  • Înscris: 21.04.2009
De ce _tmain si nu main ? De ce cu t si de ce cu _ ?
De ce TCHAR ? Ce e ala si de unde stii ca nu trebuia acolo simplu char ? De ce de tipar ?

#8
neagu_laurentiu

neagu_laurentiu

    Guru Member

  • Grup: Senior Members
  • Posts: 40,604
  • Înscris: 30.07.2003
Click dreapta pe cuvantul ce nu-l intelegi si te duce la definitie/sursa.
Uite si tipuri noi definite in Windows (de asta avem typedef in sintaxa): http://msdn.microsof...1(v=vs.85).aspx
_tmain() nu exista in C/C++ standard dar e o extensie a lui Microsoft. In plus a aparut pentru o trecere "usoara" de la char pe 1 octet la Unicode/multibyte fiindca in functie de setarile proiectului rezulta in urma preprocesarii main() ori wmain().

In rest citeste notiuni de baza din programarea Windows.

Edited by neagu_laurentiu, 24 February 2013 - 10:51.


#9
dani.user

dani.user

    Guru Member

  • Grup: Senior Members
  • Posts: 30,238
  • Înscris: 24.02.2007
Pe vremea lui Windows98/ME, acestora, spre deosebire de NT/2000, le lipseau mare parte din functii pentru lucrul cu siruri de caractere UNICODE.
Prin urmare trebuia sa scrii o aplicatie (Unicode) pentru NT/2000, si alta, "chioara" pentru 98/ME.
Folosind insa TCHAR si functiile cu _t, pur si simplu activai/dezactivai un macro si aveai o aplicatie fie unicode, fie nu.

In libraria standard C, pentru fiecare functie ce vrea un char* ai una si care accepta wchar_t*, iar in WinAPI ai la fel, functii cu sufixul A respectiv cu sufixul W si cate un #ifdef de forma
#ifdef UNICODE
#define SetWindowText SetWindowTextW
#else
#define SetWindowText SetWindowTextA
#endif // !UNICODE



#10
mihai_logic

mihai_logic

    Member

  • Grup: Members
  • Posts: 257
  • Înscris: 15.02.2013
Eu sunt axat pe programare web, adica php, javascript, python & stuff. Vreau sa invat putin si din programarea dektop. Pot instala doar Visual C++ cu MFC? Nu vreau Visual Studio, vreau doar VC++ cu MFC.

#11
dani.user

dani.user

    Guru Member

  • Grup: Senior Members
  • Posts: 30,238
  • Înscris: 24.02.2007
MFC e doar in varianta platita si nu e nici cea mai usoara tehnologie GUI de invatat si nici de folosit.

#12
neagu_laurentiu

neagu_laurentiu

    Guru Member

  • Grup: Senior Members
  • Posts: 40,604
  • Înscris: 30.07.2003
De la varianta Visual Studio .NET (2002) nu se mai poate, totul e la pachet.
Oricum VC++ Express nu are MFC, acesta din urma e doar in varianta pe bani. Dar sunt destule alte biblioteci pentru GUI.

 dani.user, on 24 februarie 2013 - 12:40, said:

MFC [...] nu e nici cea mai usoara tehnologie GUI de invatat si nici de folosit.
Aici e relativa povestea. Cine stie OOP si C++ nu ar trebui sa aiba impedimente.

Edited by neagu_laurentiu, 24 February 2013 - 12:43.


#13
mihai_logic

mihai_logic

    Member

  • Grup: Members
  • Posts: 257
  • Înscris: 15.02.2013
Eu as vrea aplicatii native, .NET nu imi place.

Edited by mihai_logic, 24 February 2013 - 12:48.


#14
dani.user

dani.user

    Guru Member

  • Grup: Senior Members
  • Posts: 30,238
  • Înscris: 24.02.2007
Detaliez mai tarziu cum e si cu GUI-ul nativ.

#15
neagu_laurentiu

neagu_laurentiu

    Guru Member

  • Grup: Senior Members
  • Posts: 40,604
  • Înscris: 30.07.2003

 mihai_logic, on 24 februarie 2013 - 12:47, said:

Eu as vrea aplicatii native, .NET nu imi place.
Ai WinAPI (baza MFC-ului) sau wxWidgets ce e 99% stil MFC. Ori QT pentru alte gusturi.

#16
dani.user

dani.user

    Guru Member

  • Grup: Senior Members
  • Posts: 30,238
  • Înscris: 24.02.2007
Am detaliat cum sta treaba si cu interfetele grafice

#17
pax0xFF

pax0xFF

    Member

  • Grup: Members
  • Posts: 869
  • Înscris: 21.10.2012
La mine nu este "Aplicatie Windows". Aveti idee de ce? Chiar dacă am Visual C++ 2005, nu ar trebui să am? Windows Forms este.

Attached Files



#18
neagu_laurentiu

neagu_laurentiu

    Guru Member

  • Grup: Senior Members
  • Posts: 40,604
  • Înscris: 30.07.2003
Acea versiune nu avea disponibila optiunea in cauza in mod direct.
http://www.codeproje...s-Edition-to-De

Treci totusi la una mai actuala.

Anunturi

Bun venit pe Forumul Softpedia!

0 user(s) are reading this topic

0 members, 0 guests, 0 anonymous users

Forumul Softpedia foloseste "cookies" pentru a imbunatati experienta utilizatorilor Accept
Pentru detalii si optiuni legate de cookies si datele personale, consultati Politica de utilizare cookies si Politica de confidentialitate