www.rgc.ro Web analytics

Jump to content

Recommended Posts

Posted

Salut!

Am de facut o aplicatie Windows ce codeaza si decodeaza (cu metoda lui Huffman) un anumit text sau o anumita secventa binara.

Am dat de o mica problema... Cand intru in meniu la "Introdu manual textul" imi creaza un Edit Control, acolo pot scrie textul si mi-l codeaza. Deci pana aici merge cum trebuie. Problema apare daca vreau (inainte sau dupa ce codez textul, nu conteaza cand) sa inchid acest Edit Control. Nu merge nici din X si nici din butonul "Inchide".

 

hEditWnd este Edit Controlul, newWnd este fereastra principala care este creata la inceputul rularii aplicatiei.

Am incercat sa o inchid si cu ShowWindow(hEditWnd, SW_HIDE) si cu EndDialog(hEditWnd, 0) si cu DestroyWindow(hEditWnd). Ori nu face absolut nimic, ori imi inchide cu tot cu fereastra principala. Ce e de facut? Am cautat pe net si am incercat mai multe variante din ce zicea lumea, dar nu am reusit...

 

AICI ESTE APELAREA FUNCTIEI CARE CREEAZA CONTROLUL

 

case ID_INTRODUTEXT:

{

//Se creaza un dialog box ce contine caseta de introducere/editare text

 

bool CLICK = DialogBox(GetModuleHandle(NULL),

MAKEINTRESOURCE(IDD_CODARE),

newWnd,

CreateEditBox);

if (CLICK) ShowWindow(hEditWnd, SW_SHOW);

}

break;

 

AICI ESTE FUNCTIA CreateEditBox

 

BOOL CALLBACK CreateEditBox(HWND newWnd,

UINT Message,

WPARAM wParam,

LPARAM lParam)

{

 

//In textBuffer se va retine textul introdus in caseta, pentru a fi prelucrat

 

char textBuffer[bUFFERSIZE];

switch(Message)

{

case WM_CREATE:

{

 

//hfDefault este un handle catre font-ul folosit in caseta pentru text

 

HFONT hfDefault;

 

//hEditWnd este variabila globala

 

hEditWnd = CreateWindowEx(WS_EX_CLIENTEDGE,

_T("EDIT"), _T("CODARE"),

WS_CHILD | WS_VISIBLE | ES_MULTILINE | WS_VSCROLL | ES_AUTOVSCROLL,

0, 0, 100, 100, newWnd, NULL, GetModuleHandle(NULL), NULL);

 

//Daca nu se reuseste crearea, atunci se va afisa un mesaj de eroare

 

if (hEditWnd == NULL)

MessageBox(newWnd, _T("Eroare! Caseta pentru introducere/editare text nu a putut fi creata"), _T("Eroare"), MB_OK | MB_ICONERROR);

 

//Initializam font-ul cu cel implicit

 

hfDefault = (HFONT) GetStockObject(DEFAULT_GUI_FONT);

SendMessage(hEditWnd, WM_SETFONT, (WPARAM) hfDefault, MAKELPARAM(FALSE, 0));

}

break;

 

//Redimensionam caseta text in functie de fereastra parinte (in cazul nostru in functie de newWnd)

 

case WM_SIZE:

{

RECT rcClient;

GetClientRect(newWnd, &rcClient);

hEditWnd = GetDlgItem(newWnd, IDC_EDITCODARE);

SetWindowPos(hEditWnd, NULL, 0, 0, rcClient.right, rcClient.bottom, SWP_NOZORDER);

}

break;

 

case WM_COMMAND:

switch(LOWORD(wParam))

{

 

//IDOK reprezinta butonul "Codeaza" al ferestrei

//In urma apasarii pe buton, textul va fi pastrat in textBuffer

//apoi va fi prelucrat

 

case IDOK:

{

GetDlgItemTextA(newWnd,

IDC_EDITCODARE,

textBuffer,

BUFFERSIZE);

 

initializareHuffman();

calculeazaFrecvente(textBuffer);

construiesteArboreHuffman();

construiesteVocabular();

 

char *buffer = (char *) malloc (sizeof (char) * strlen(textBuffer) +2);

int dimBuf;

compresieHuffman(textBuffer, buffer, dimBuf);

 

HANDLE hOutput;

 

hOutput = CreateFile(_T("outputCodeHuffman.bin"),

GENERIC_WRITE,

0,

NULL,

CREATE_ALWAYS,

FILE_ATTRIBUTE_NORMAL,

NULL);

 

DWORD dwBytesToWrite = (DWORD) strlen (textCodat);

DWORD dwBytesWritten = 0;

 

WriteFile(hOutput,

textCodat,

dwBytesToWrite,

&dwBytesWritten,

NULL);

 

//Dupa ce este prelucrat, apare un mesaj de confirmare

 

MessageBox(NULL,

_T("Text codat!\n"),

_T("Informatii"),

MB_OK);

 

}

break;

 

 

URMATOAREA PARTE NU FUNCTIONEAZA CUM AR TREBUI

 

case IDCANCEL:

ShowWindow(hEditWnd, SW_HIDE);

break;

}

case WM_CLOSE:

{

ShowWindow(hEditWnd, SW_HIDE);

return TRUE;

}

break;

default:

return FALSE;

}

return TRUE;

}

 

La toate celelalte DialogBox-urile pe care le mai folosesc (gen About, Help si ce mai am eu pe aici) procedez exact la fel ca in acest caz atunci cand vine vorba de creare si inchidere.

 

Ce as putea sa ii fac?

Posted (edited)

"DialogBox" este o functie blocanta. Tu o apelezi din procedura de fereastra a ferestrei principale. Cat timp DialogBox functioneaza, fereastra principala e blocata, nu poti face nimic in ea. Nu prea inteleg ce vrei sa faci: initial creezi un dialog modal, apoi procedura lui de fereastra creeaza un edit box al carui parinte NU este dialogul. Acest edit box va ramane blocat, pentru ca tu inca esti in dialogul modal. Ar fi bine sa creezi edit-ul cu editorul de resurse, ar fi mai simplu. Tu ai creat edit-ul dinamic, trebuie creat cu parintele ca fiind dialogul initial si distrus edit-ul pe WM_ENDDIALOG. Te cam complici. Mai e o greseala: tu creezi acel edit dinamic pe WM_CREATE-ul dialogului (ar trebui pe WM_INITDIALOG), apoi pe WM_SIZE faci GetDlgItem(IDC_EDITCODARE). Ar trebui sa te hotarasti daca folosesti un edit static creat cu editorul de resurse (adica IDC_EDITCODARE) sau un edit dinamic creat cu CreateWindow si distrus pe WM_ENDDIALOG.

Edited by Stimpson J. Cat
Posted (edited)

Tocmai a scris Stimpson despre "object inheritance", mult mai bine decat editasem eu . Controalele trebuiesc initializate dupa ce thread-ul ferestrei , functioneaza (WM_INITDIALOG). Daca thread-urile nu sunt "mostenite" corespunzator (parent-child) , nu va mai functiona nimic.

In alta oridine de idei , nu incerca sa compari NULL .

Daca vrei sa verifici pt NULL, atunci

 

if (!object)

{

//este null

}

else

{

//este valid

}

Edited by ggg
Posted

Am incercat cu DestroyWindow si nu mi-a mers.

red, alocarea respectiva era din codul pentru codarea huffman pe care il am intr-un pdf de la curs. Codul pt codarea propriu-zisa nu am stat sa il analizez, doar l-am copiat direct.

 

O sa incerc sa repar bubele urmand sfaturile lui gg si Stimpson, probabil diseara sau maine.

Va multumesc pentru raspunsuri.

Posted

Iulian, aplicatia este pentru un proiect pentru facultate. Asa mi-a fost cerut sa fac. Sa am optiunea sa introduc textul de la tastatura sau sa incarc un fisier, iar codul textului sa fie generat intr-un fisier binar. Iar pentru decodare sa fie doar optiunea cu incarcare de fisier binar care imi va genera un fisier text.

 

ggg... Thanks for the link... Adevarul e ca e primul meu proiect de tipul asta si imi cam prind urechile in ele... Intr-o parte le vad explicate intr-un fel, intr-o parte in alt fel plus ca profu' nu a facut absolut nimic sa ne ajute. Doar ne-a aruncat un link pe mail cu un tutorial "Aici aveti tutorialul pentru proiect. Spor la treaba!". Sa nu mai zic ce si-a batut salamul de mine cand m-am dus prima oara sa ii prezint o parte din proiect si sa ii cer ajutorul... Eu am incercat sa culeg de peste tot ce am putut si sa le adaptez pentru ce imi trebuie mie.

Posted (edited)

Este adevarat ca nu este creat nici un thread in mod special . Dar orice proces rulat sub OS Windows lanseaza cateva thread-uri cu scop preemptiv (unul dintre ele este pt metoda CallBack) . In toate documentatiile Microsoft , se spune foarte des despre "parent-child inheritance" care poate fi relativ la anumiti pointeri sau alte "child" threads . Dar practic ,un "handler" este adresa de memorie a pointerului catre structura de date a unui obiect care ruleaza intr-un astfel thread . Poti sa verifici cu orice tool pt vizualizarea memoriei . DestroyWindow() este posibil sa nu raspunda sau sa nu fie apelat corespunzator pt ca parametrul obiect, apartine unei alte "ramuri" de asemenea "mosteniri" (thread,pointer,data structure) .

 

plus ca profu' nu a facut absolut nimic sa ne ajute. Doar ne-a aruncat un link pe mail cu un tutorial ....

Arghhhh...cunosc foarte bine mediul asta ! Despre profesori , numai de bine :D

Edited by ggg
Posted

@ggg Am dat intr-o usoara polemica, dar cred ca va fi constructiva pentru amandoi. Din experienta mea am inteles ca procedura de fereastra pentru ferestrele create de acelasi thread ruleaza tot in acel thread care a apelat CreateWindow. Poti verifica cu debuggerul punand breakpoint in WindowProc. Procedura de fereastra e invocata la un moment dat de DispatchMessage (ca si de alte functii de Windows, cum ar fi CreateWindow) la modul cat se poate de iterativ.

Threadurile se creeaza doar explicit, acum depinde de functia API respectiva daca intern creeaza un alt thread. Nu am cunostinta despre thread-uri temporare folosite de Windows la dispecerizare de mesaje.

HANDLE-urile sunt niste pointeri valabil in tot procesul, ele nu "ruleaza intr-un thread", sunt date in memorie. Le poti crea intr-un thread si distruge in altul. Semnificatia HANDLE-ului e ceva de nivel mai inalt, adica deja vorbim despre un obiect in sine, cu niste proprietati.

HWND semnifica la nivel mai inalt decat un simplu pointer un obiect "fereastra", care are niste restrictii, dar conceptuale, nu de alocare sau adresare.

Posted (edited)

@ggg Am dat intr-o usoara polemica,

Din partea mea , nu este niciun fel de problema :)

Kernel-ul de la Windows are niste mecanisme destul de odioase care-i tradeaza varsta. Este incredibil cum si in actualul Kernel exista inca functii scrise de pe vremea lui WIndows 2.x .

Meteahna este urmatoare ,

- dupa cum bine ai observat SendMessage() si GetMessage() sunt in tot si in toate pt ca functiilea astea complementare cam guverneaza peste Windows. Dupa ce apelam tot felul de functii ale kernelului care pregateste sistemul pt a fi folosit intr-un anumit scop este apelat SendMessage() pt a pune in executie , iar GetMessage() pt citirea status. Este un fel de "call interupt" in ASM . De fapt de acolo este si inspirata aceasta metoda .

Acum sunt si derivate ale acestor functii dominante in Windows .De exemplu , un derivat SendMessage() este tocmai DispatchMessage() care are capabilitatea sa faca o comunicare cu o alta procedura care ruleaza intr-un alt fir de executie . Dar acel thread nu este creat si nici apelat de utilizator, ci de mecanismele Kernel.

Uite cum arata parametrul MSG al DispatchMessage()

typedef struct tagMSG {

HWND hwnd;

UINT message;

WPARAM wParam;

LPARAM lParam;

DWORD time;

POINT pt;

} MSG

si cum arata formal SendMessage

LRESULT WINAPI SendMessage(

_In_ HWND hWnd,

_In_ UINT Msg,

_In_ WPARAM wParam,

_In_ LPARAM lParam

);

 

 

Pe masura ce vom lua la puricat aceste functii ajungem usor,usor la geneza...DOS ! Adica , musca si fugi :D

Edited by ggg
  • Like 1
Posted (edited)

@ggg: "Call interrupt" stiu ca se foloseste la thread scheduling: se pun exceptii cu timeouturi mici si cand expira, ruleaza o rutina de transfer a controlului de thread care face un "call" unde a ramas ultima oara. Am gasit asta prin sursele de Symbian (leak-uite pe net), mi s-a parut o chestie supertare, chiar nu stiam cum se face thread scheduling pana in momentul ala.

SendMessage mi-a zis cineva care a lucrat la MS si a avut acces la surse ca e o functie "monstruoasa" ca implementare. Daca SendMessage trece peste thread scheduler si face ea "call interrupt", e chiar mai monstruoasa decat credeam! Eu credeam ca doar verifica coada de mesaje si eventual mai apeleaza ea direct WindowProc-uri, dupa caz (spre exemplu BM_GETCHECK). Sincronizarea cu WindowProc-ul ferestrei target e destul de intriganta.

Cred ca totusi se poate implementa un soi de SendMessage folosind PostThreadMessage si un Wait(hEventNamedAfterHwnd). Asa, in mare... Adica fara "call interrupt".

Windows-ul modern are ceva code base vechi, dar totusi sper ca undeva acolo, nucleul pastreaza traditia Windows NT4 (Windows 8 este totusi Windows NT 6.2) si nu de Win9X! Chiar vreau sa cred asta! Ai zis de geneza DOS, ma sperii...

Eh... as vrea sa discut la fel de relaxat si despre game, arpegii si combinarea modurilor, ca tot suntem pe Guitarist Community. Deocamdata raman doar cu visele...

Edited by Stimpson J. Cat
  • Like 1

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...

Important Information

"This site uses cookies. By continuing to browse the site you are agreeing to our use of cookies.