Alin N Posted June 28, 2013 Share Posted June 28, 2013 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? Link to comment Share on other sites More sharing options...
iulian Posted June 28, 2013 Share Posted June 28, 2013 Nu ar trebui sa apelezi DetroyWindow(hEditWnd) ?? case WM_CLOSE: DestroyWindow(hEditWnd); return 0; Link to comment Share on other sites More sharing options...
Stimpson J. Cat Posted June 28, 2013 Share Posted June 28, 2013 (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 June 28, 2013 by Stimpson J. Cat Link to comment Share on other sites More sharing options...
ggg Posted June 28, 2013 Share Posted June 28, 2013 (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 June 28, 2013 by ggg Link to comment Share on other sites More sharing options...
Alin N Posted June 28, 2013 Author Share Posted June 28, 2013 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. Link to comment Share on other sites More sharing options...
iulian Posted June 28, 2013 Share Posted June 28, 2013 nu era mai simplu sa bagi doua edit controls si un buton? in primul bagi text, apesi butonul si in al doilea afisezi codatul? Link to comment Share on other sites More sharing options...
ggg Posted June 28, 2013 Share Posted June 28, 2013 Am incercat cu DestroyWindow si nu mi-a mers. Remarks A thread cannot use DestroyWindow to destroy a window created by a different thread. If the window being destroyed is a child window that does not have the WS_EX_NOPARENTNOTIFY style, a WM_PARENTNOTIFY message is sent to the parent. http://msdn.microsoft.com/en-us/library/windows/desktop/ms632682(v=vs.85).aspx Link to comment Share on other sites More sharing options...
Alin N Posted June 28, 2013 Author Share Posted June 28, 2013 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. Link to comment Share on other sites More sharing options...
Stimpson J. Cat Posted June 28, 2013 Share Posted June 28, 2013 (edited) @ggg: tot codul e pe acelasi thread, nu apare nicaieri CreateThread si in plus nu cred ca omul e destul de "nebun" incat sa o mai faca si aplicatie multithreading. Acel DestroyWindow nici nu apuca sa se apeleze cat timp dialogul exista. Edited June 28, 2013 by Stimpson J. Cat Link to comment Share on other sites More sharing options...
ggg Posted June 28, 2013 Share Posted June 28, 2013 (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 Edited June 28, 2013 by ggg Link to comment Share on other sites More sharing options...
Stimpson J. Cat Posted June 28, 2013 Share Posted June 28, 2013 @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. Link to comment Share on other sites More sharing options...
ggg Posted June 28, 2013 Share Posted June 28, 2013 (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 Edited June 28, 2013 by ggg 1 Link to comment Share on other sites More sharing options...
Stimpson J. Cat Posted June 28, 2013 Share Posted June 28, 2013 (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 June 28, 2013 by Stimpson J. Cat 1 Link to comment Share on other sites More sharing options...
ggg Posted June 28, 2013 Share Posted June 28, 2013 (edited) Cred ca totusi se poate implementa un soi de SendMessage folosind PostThreadMessage si un Wait(hEventNamedAfterHwnd). Asa, in mare... Bineinteles ca se poate. Dar cred ca vor apare si situatii de compromis. . Edited June 28, 2013 by ggg Link to comment Share on other sites More sharing options...
Recommended Posts
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 accountSign in
Already have an account? Sign in here.
Sign In Now