الفريق العربي للبرمجةأرشيف المنتديات · 2000 – 2023
نسخة أرشيفية للقراءة فقط — التسجيل والمشاركة مغلقان، والمحتوى محفوظ كما كان.

مثال للTreeview و الNestedStructs

مغلق
بدأه neo في 19 مارس 2006 · 10 رد · 1,021 مشاهدة · في لغة C و ++C
مشاركة: واتساب X فيسبوك تيليجرام
#1 صاحب الموضوع

السلام عليكم و رحمة الله و بركاته

كنت بقدم على و ظيفة فى أحد الشركات و كان هناك ورشة عمل لابد من القيام بها

المهم قمت بعمل المهمه المطلوبة و هى كانت كالأتى

"عمل برنامج لقرأة Struct من ملف Binary و عرض محتوياتة فى شكل Tree المهم هو أن الـStruct عبارة عن Nested structs"

و اليكم الحل و أرجوا أن تستفيدوا منه

#include <windows.h>
#include "resource\resource.h"
#include "Struct.h"
#include <commctrl.h>
#include <stdlib.h>
#include <fstream.h>
#include <string.h>

HINSTANCE hInst; 
#define WIN32_LEAN_AND_MEAN 
TV_ITEM tvi;
TV_INSERTSTRUCT tvinsert;   
HIMAGELIST hImageList;      
HBITMAP hBitMap;            
HWND hTree;
fstream F;
HTREEITEM Master;
HWND hEdit;
int strLen(char *target);
void DelteAllTree(HWND hWnd_);
void IntToChar(int target,char *returnChar);
void FloatToChar(float target,char *returnChar);
char *Concat(char *AddTo,char *Addthis);
void TerminateCharArray(char *target);
HTREEITEM AddNode(HTREEITEM Parent_ ,char *Title, HWND hWnd_);
HTREEITEM AddRoot(char *Title,HWND hWnd_);

BOOL CALLBACK DialogProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	switch (message) 
	{   

  case WM_INITDIALOG: 
  {
 	 InitCommonControls();     
 	 hTree=GetDlgItem(hWnd,IDC_TREE1);
 	 
 	 
 	 hImageList=ImageList_Create(16,16,ILC_COLOR16,3,10);       
 	 hBitMap=LoadBitmap(hInst,MAKEINTRESOURCE(IDB_TREE));       
 	 ImageList_Add(hImageList,hBitMap,NULL);              
 	 DeleteObject(hBitMap);              

      SendDlgItemMessage(hWnd,IDC_TREE1,TVM_SETIMAGELIST,0,(LPARAM)hImageList); 
 	 
 	 tvinsert.hParent=NULL; 	 
 	 tvinsert.hInsertAfter=TVI_ROOT; 
            tvinsert.item.mask=TVIF_TEXT|TVIF_IMAGE|TVIF_SELECTEDIMAGE;
         tvinsert.item.pszText="Parent";
 	 tvinsert.item.iImage=0;
 	 tvinsert.item.iSelectedImage=1;  
  }
  break;


  case WM_PAINT: 
  {
 	 return 0;
  }
  break;
  
  case WM_COMMAND: 
  {
 	 switch (LOWORD(wParam)) 
 	 {
    case IDC_ADDROOT:
    {
   	 int count=0;
   	 DelteAllTree(hWnd);
   	 HTREEITEM Parent_1;
   	 HTREEITEM struct_1;
   	 HTREEITEM struct_2;
   	 HTREEITEM struct_3;
   	 HTREEITEM struct_4;
   	 HTREEITEM struct_5;
   	 HTREEITEM struct_6;

   	 F.open(".\\Input.bin",ios::binary|ios::in|ios::out);
   	 while (!F.eof())
   	 {
      count++;
      MainStruct MainStructInstance,MainStructInstance_;
      F.read((char*)&MainStructInstance,56);
      MainStructInstance_=MainStructInstance;
      char MS_yu,c1,c2,c3;
      c1=MainStructInstance.b.hh;
      c2=MainStructInstance.c.b.hh;
      c3=MainStructInstance.io;
      char *tempp;
      IntToChar(count,&MS_yu);
      tempp=Concat(" MainStruct #",&MS_yu);
      Parent_1 = AddRoot(tempp,hWnd);
      struct_1=AddNode(Parent_1," A ",hWnd);
      
      IntToChar(MainStructInstance.a.nn,&MS_yu);
      tempp = " nn = ";
      tempp =Concat(tempp,&MS_yu);
     	 AddNode(struct_1,tempp,hWnd);
     	 TerminateCharArray(tempp);TerminateCharArray(&MS_yu);MainStructInstance=MainStructInstance_;
      
      FloatToChar(MainStructInstance.a.ii,&MS_yu);
      tempp = " ii = ";
      tempp =Concat(tempp,&MS_yu);
     	 AddNode(struct_1,tempp,hWnd);
     	 TerminateCharArray(tempp);TerminateCharArray(&MS_yu);MainStructInstance=MainStructInstance_;

      struct_2=AddNode(Parent_1," B ",hWnd);
     	 struct_4=AddNode(struct_2," A ",hWnd);
     	 
     	 IntToChar(MainStructInstance.b.a.nn,&MS_yu);
     	 tempp = " nn = ";
     	 tempp =Concat(tempp,&MS_yu);
        AddNode(struct_4,tempp,hWnd);
        TerminateCharArray(tempp);TerminateCharArray(&MS_yu);MainStructInstance=MainStructInstance_;
     	 
     	 FloatToChar(MainStructInstance.b.a.ii,&MS_yu);
     	 tempp = " ii = ";
     	 tempp =Concat(tempp,&MS_yu);
        AddNode(struct_4,tempp,hWnd);
        TerminateCharArray(tempp);TerminateCharArray(&MS_yu);MainStructInstance=MainStructInstance_;

     	 tempp = &c1; tempp++; *tempp=0;
     	 tempp = " hh = ";
     	 tempp =Concat(tempp,&c1);
     	 AddNode(struct_2,tempp,hWnd);
     	 TerminateCharArray(tempp);TerminateCharArray(&MS_yu);MainStructInstance=MainStructInstance_;

      struct_3=AddNode(Parent_1," C ",hWnd);
     	 struct_5=AddNode(struct_3," A ",hWnd);
     	 
     	 IntToChar(MainStructInstance.c.a.nn,&MS_yu);
     	 tempp = " nn = ";
     	 tempp =Concat(tempp,&MS_yu);
        AddNode(struct_5,tempp,hWnd);
        TerminateCharArray(tempp);TerminateCharArray(&MS_yu);MainStructInstance=MainStructInstance_;
        
     	 FloatToChar(MainStructInstance.c.a.ii,&MS_yu);
     	 tempp = " ii = ";
     	 tempp =Concat(tempp,&MS_yu);
        AddNode(struct_5,tempp ,hWnd);
        TerminateCharArray(tempp);TerminateCharArray(&MS_yu);MainStructInstance=MainStructInstance_;
     	 struct_6=AddNode(struct_3," B ",hWnd);
        struct_4=AddNode(struct_6," A ",hWnd);
        
        IntToChar(MainStructInstance.c.b.a.nn,&MS_yu);
        tempp = " nn = ";
        tempp =Concat(tempp,&MS_yu);
       	 AddNode(struct_4,tempp,hWnd);
       	 TerminateCharArray(tempp);TerminateCharArray(&MS_yu);MainStructInstance=MainStructInstance_;
        FloatToChar(MainStructInstance.c.b.a.ii,&MS_yu);
        tempp = " ii = ";
        tempp =Concat(tempp,&MS_yu);
       	 AddNode(struct_4,tempp,hWnd);
       	 TerminateCharArray(tempp);TerminateCharArray(&MS_yu);MainStructInstance=MainStructInstance_;
        

        tempp = &c2; tempp++; *tempp=0;
        tempp = " hh = ";
        tempp =Concat(tempp,&c2);
        AddNode(struct_6,tempp,hWnd);
        TerminateCharArray(tempp);TerminateCharArray(&MS_yu);MainStructInstance=MainStructInstance_;
        
     	 FloatToChar(MainStructInstance.c.gg,&MS_yu);
     	 tempp = " gg = ";
     	 tempp =Concat(tempp,&MS_yu);
        AddNode(struct_3,tempp,hWnd);
        TerminateCharArray(tempp);TerminateCharArray(&MS_yu);MainStructInstance=MainStructInstance_;
   	 IntToChar(MainStructInstance.hj,&MS_yu);
   	 tempp = " hj = ";
   	 tempp =Concat(tempp,&MS_yu);
      AddNode(Parent_1,tempp,hWnd);
      TerminateCharArray(tempp);TerminateCharArray(&MS_yu);MainStructInstance=MainStructInstance_;
   	 
   	 FloatToChar(MainStructInstance.yu,&MS_yu);
   	 tempp = " yu = ";
   	 tempp =Concat(tempp,&MS_yu);
      AddNode(Parent_1,tempp,hWnd);
      
      tempp = &c3; tempp++; *tempp=0;
      tempp = " io = ";
      tempp =Concat(tempp,&c3);
      AddNode(Parent_1,tempp,hWnd);
   	 }
   	 F.close();
   	 UpdateWindow(GetDlgItem(hWnd,IDC_TREE1));
    }
    break;

    case IDC_DELALL:
    {
   	 DelteAllTree(hWnd);
   	 UpdateWindow(hWnd);
    }
    break;	
 	 }
 	 break;

 	 case WM_CLOSE: 
 	 {
    EndDialog(hWnd,0); 
 	 }
 	 break;
  }
  break;
	}
	return 0;
}

int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow)
{
	hInst=hInstance;
	DialogBoxParam(hInstance, MAKEINTRESOURCE(IDD_DIALOG1), NULL, (DLGPROC)DialogProc,0);
	return 0;
}

HTREEITEM AddRoot(char *Title,HWND hWnd_)
{
   	 tvinsert.hParent=NULL;
   	 tvinsert.hInsertAfter=TVI_ROOT;
   	 tvinsert.item.pszText=Title;
   	 HTREEITEM retVal=(HTREEITEM)SendDlgItemMessage(hWnd_,IDC_TREE1,TVM_INSERTITEM,0,(LPARAM)&tvinsert);
   	 TreeView_SelectDropTarget(GetDlgItem(hWnd_,IDC_TREE1),retVal);
   	 return retVal;
}

HTREEITEM AddNode(HTREEITEM Parent_ ,char *Title, HWND hWnd_)
{
   	 tvinsert.hParent=Parent_;
   	 tvinsert.hInsertAfter=TVI_LAST;
   	 tvinsert.item.pszText=Title;
   	 HTREEITEM retVal=(HTREEITEM)SendDlgItemMessage(hWnd_,IDC_TREE1,TVM_INSERTITEM,0,(LPARAM)&tvinsert);
   	 TreeView_SelectDropTarget(GetDlgItem(hWnd_,IDC_TREE1),retVal);
   	 return retVal;
}
void DelteAllTree(HWND hWnd_)
{
int TreeCount=TreeView_GetCount(GetDlgItem(hWnd_,IDC_TREE1));
   	 for(int i=0;i<TreeCount;i++)
      TreeView_DeleteAllItems(GetDlgItem(hWnd_,IDC_TREE1));
}

void IntToChar(int target,char *returnChar)
{
	itoa(target,returnChar, 10);
}

void FloatToChar(float target,char *returnChar)
{
	gcvt((double)target,20,returnChar);
}

char *Concat(char *AddTo,char *Addthis)
{
	int ValOfAddTo =strLen(AddTo),ValOfAddthis =strLen(Addthis),i,j;
	char *temp;
	temp=new char[ValOfAddTo+ValOfAddthis];	
	for (i=0;i<ValOfAddTo;i++)
  {
 	 temp=*AddTo;
 	 AddTo++;
  }
	for (j=0;j<ValOfAddthis;j++)
  {
 	 temp[i+j]=*Addthis;
 	 Addthis++;
  }
	return temp;
}


int strLen(char *target)
{
	int i=0;
	while(*target!=0)
	{
  target++;
  i++;
	}
	return i;
}
void TerminateCharArray(char *target)
{
	while (*target=0)
	{
  *target = 0;
  target++;
	}
}

مرفق مع الموضوع ملف الذى يحتوى على كل المشروع

أرجوا منكم الأطلاع و المناقشة

Ahmed_Essam_Workshop.rar

تم تعديل هذه المشاركة بواسطة neo في 19 مارس 2006 في 16:28

Nothing to mention except that I am Muslim

Using your brain is not bad as you think

My Blog

logo.jpg

#2

رائع و لكن لم افهم غرض هذه الدالة

char *Concat(char *AddTo,char *Addthis)

BEng , Electronics and communications.

Embedded systems engineer.

Graphics Programmer

عالم الكومبيوتر هو من لديه المعرفة في علوم الكومبيوتر ، الرياضيات ، هندسة الالكترونيات -احمد صالح

#3

تقوم الدالة Concat بدمجة 2 سلسة حرفية بدون التعرض للمدخلات

 char *Concat(char *AddTo,char *Addthis)
{
/* 1  */ int ValOfAddTo =strLen(AddTo),ValOfAddthis =strLen(Addthis),i,j;
/* 2  */ char *temp;
/* 3  */ temp=new char[ValOfAddTo+ValOfAddthis]; 
/* 4  */ for (i=0;i<ValOfAddTo;i++)
/* 5  */  {
/* 6  */   temp=*AddTo;
/* 7  */   AddTo++;
/* 8  */  }
/* 9  */ for (j=0;j<ValOfAddthis;j++)
/* 10 */  {
/* 11 */   temp[i+j]=*Addthis;
/* 12 */   Addthis++;
/* 13 */  }
/*  */ return temp;
}

فى السطر الثانى حجز مؤشر من نوع char

فى السطر الثالث قمت بتحديد مساحة السلسة وهى عبارة عن طول السلسة الأولى و الثانية وهدا لمنع مشكلة "Memory violation"

من السطر الرابع الى السطر الربع loop تقوم بنقل محتوبات السلسة الأولى الى محتويات السلسلة المؤقتة

من السطر التاسغ الى السطر الثالث عشر loop تقوم بنقل محتوبات السلسة الثانيه الى محتويات السلسلة المؤقتة

فى السطر الأخير نقوم باعدة مؤشر من نوع char يشير السلسة النهائية

نلاحظ شئ وهو أننى لم أقوم بعمل Delete للمتغير temp و الفائدة هنا هو أن الـTemp هى ناتج الدالة و أدا تم أستعمال delete ان نجد نتيجة للدالة

أتمنى أن يكون هدا الشرح وافيا :)

شكرا على الأهتمام و المناقشة ( يا رب ديما :) )

تم تعديل هذه المشاركة بواسطة neo في 19 مارس 2006 في 21:49

Nothing to mention except that I am Muslim

Using your brain is not bad as you think

My Blog

logo.jpg

#4

توجد بعض الملاحظات سريعا ...

بالنسبة لـ

int strLen(char *target) {
  int i=0;
  while(*target!=0) {
    target++;
    i++;
  }
  return i;
}

جرب

unsigned long StrLen(const char *str) {
  unsigned long i = -1;
  while(str[++i]);
  return i;
}

مع هذا لا تحتاج لهذه الدالة , حيث انها موجوده strlen في المكتبة string.h والتي يتضمنها الكود

وبالنسبة لـ

char *Concat(char *AddTo,char *Addthis) {
  int ValOfAddTo =strLen(AddTo),ValOfAddthis =strLen(Addthis),i,j;
  char *temp;
  temp=new char[ValOfAddTo+ValOfAddthis];	
  for (i=0;i<ValOfAddTo;i++) {
    temp=*AddTo;
    AddTo++;
  }
  for (j=0;j<ValOfAddthis;j++) {
    temp[i+j]=*Addthis;
    Addthis++;
  }
  return temp;
}

استبدلها بـ

char * Concat(const char *str1, const char *str2) {
  char *temp = new char[StrLen(str1)+StrLen(str2)];
  strcpy(temp, str1);
  strcat(temp, str2);
  return temp;
}

لاحظ انك تقوم في كل مره تستدعي هذه الدالة بانشاء مساحة جديده في الذاكرة , وتحتاج لتحرير الذاكرة بعد الانتهاء من استخدامها , والا..... انت عارف ;)

طيب, نتابع الكود لنلاحظ مشكلة

char *tempp; // انشاء مؤشر لاستقبال عنوان الذاكرة العائدة من Concat
IntToChar(count,&MS_yu);
tempp = Concat(" MainStruct #",&MS_yu); // تم وضع عنوان الذاكرة في المؤشر
Parent_1 = AddRoot(tempp,hWnd); // تم استخدام الذاكرة

tempp = " nn = "; // لاحظ أن المؤشر الان فقد العنوان السابق
tempp =Concat(tempp,&MS_yu); // الان يشير الى عنوان جديد في الذاكرة
AddNode(struct_1,tempp,hWnd); // يتم استخدام العنوان الجديد

اذاً أين يتم تحرير الذاكرة ؟

ننظر داخل الدوال التي تستخدم هذه المساحة من الذاكرة

HTREEITEM AddRoot(char *Title,HWND hWnd_) {
  tvinsert.hParent = NULL;
  tvinsert.hInsertAfter = TVI_ROOT;
  tvinsert.item.pszText = Title; // نحتاج الذاكرة
  HTREEITEM retVal = (HTREEITEM)SendDlgItemMessage(hWnd_,IDC_TREE1,TVM_INSERTITEM,0,(LPARAM)&tvinsert); // استخدمنا الذاكرة
  // الان هل تحتاج هذه المساحة من الذاكرة ؟ لماذا لا تقوم بتحريرها هنا ؟
  TreeView_SelectDropTarget(GetDlgItem(hWnd_,IDC_TREE1),retVal);
  return retVal;
}

نفس الشيء مع AddNode

ماذا تقصد من هذه الدالة

void TerminateCharArray(char *target) {
  while (*target=0) {
    *target = 0;
    target++;
  }
}

لاحظ

while (*target=0)

وما الهدف منها هنا بالتحديد؟

#5

:D

شكرا على التعليقات المفيدة

كان على أن أقوم بتحرير الذاكرة فى نهاية العميلة

و لكن لا أظنها مشكلة كبيرة لان حجم البرنامج ليس كبير, بالأضافة الى أن نسبة التعامل لن تكون ضخمة مع بيانات كبيرة و مع ذلك الكلام صحيح لابد من تحرير الذاكرة :) بس أنا نسيت ( على ضغط جامد جدا :D )

شكرك جدا على هذه المناقشات المفيدة :)

void TerminateCharArray(char *target) {
 while (*target=0) {
   *target = 0;
   target++;
 }
}

هذا الكود يقوم بوضع 0 فى كل مكونات المصفوفة الحرفية

تم تعديل هذه المشاركة بواسطة neo في 20 مارس 2006 في 09:54

Nothing to mention except that I am Muslim

Using your brain is not bad as you think

My Blog

logo.jpg

#6
اقتباس
هذا الكود يقوم بوضع 0 فى كل مكونات المصفوفة الحرفية

يوجد خطأ بسيط يجعل هذا الكود يضع 0 في أو بايت فقط من المضفوفة , وأشرت اليه في المشاركة السابقة

while (*target=0)

اللوب لن يتم تنفيذه لأن الشرط سيعيد 0 لل while من أول مره , لأنه ليس شرط في الاساس وانما هي عملية اسناد

عدل الكود لهذا الشكل

while (*target)

أو

while (*target!=0)

عموما لن تحتاج اليها هنا

TerminateCharArray(tempp);

لأنك لا تستخدم هذه المساحة من الذاكرة بعد ذلك

كذلك يمكن استبدال

TerminateCharArray(&MS_yu);

بـ

ZeroMemory(MS_yu, sizeof(MS_yu);

في حالة كون MS_yu مصفوفة حروف

أو تستبدلها بـ

MS_yu = '\0';

في حالة MS_yu كانت مجرد حرف واحد

لاحظت في الكود أنك أعلنت عن MS_yu على انها حرف

ثم استخدمتها على انها مصفوفة حروف

char MS_yu,c1,c2,c3;
.....
IntToChar(count,&MS_yu);
......
......
void IntToChar(int target,char *returnChar) {
  itoa(target,returnChar, 10);
}
#7

أقوم بعمل Terminate للمفوفة الحرفية حتى لا يحدث مشاكل ( تتمثل فى ظهور باقى سلسة حرفية فى حالة أن السلسة الرحفية الجديدة أقصر من القديمة ) أنا لا أريد الغائها من الذاكرة للأبد أنا فقط أريدها خاليه

سوف أقوم ببعض التعديلات التى سوف تحسن الأداء الى حد ما

Nothing to mention except that I am Muslim

Using your brain is not bad as you think

My Blog

logo.jpg

#8

تعديل بسيط لتحسين الأداء

int strLen(char *target)
{
__asm
	{
	mov ebx,target
lp : mov al,byte ptr [ebx]
  inc  ebx
  cmp al,0
  jne lp
     dec ebx
  sub ebx,target
  mov eax,ebx
	}	
}
void TerminateCharArray(char *target)
{
	__asm
	{
  mov ebx,target
lp : mov al,byte ptr [ebx]
  mov [ebx],0
  inc ebx
  cmp al,0
  jne lp
	}
}

Nothing to mention except that I am Muslim

Using your brain is not bad as you think

My Blog

logo.jpg

#9

مفيش تعليق على شوية الأسمبلي دول :D

Nothing to mention except that I am Muslim

Using your brain is not bad as you think

My Blog

logo.jpg

#10

طالما , قلبت للأسمبلي يبقى نهتم بكل صغيرة وكبيرة

unsigned long StrLen(char *target) {
  __asm {
    mov ebx,target
    xor eax, eax
lp:
    mov al,byte ptr [ebx+eax]
    inc eax
    cmp al,0
    jne lp
    dec eax
  } 
}

void TerminateCharArray(char *target) {
  __asm {
    mov ebx, target
    xor ax, ax
lp:
    mov byte ptr [ebx], ah
    inc ebx
    mov al, byte ptr [ebx]
    cmp al, ah
    jne lp
  }
}

;)

#11

أنا فعلا كنت كاتب الكود بهذا الشكل عند الترجمة كان عندما يبدأ البرنامج فى العمل يحدث مشاكل لا أعرف لماذا

كانت الدوال تعطى نتيجة خطأ دائما

و شكرا على الاهتمام ;)

Nothing to mention except that I am Muslim

Using your brain is not bad as you think

My Blog

logo.jpg

هذا الموضوع مغلق.

مواضيع مشابهة