Creating TOpenDialog manually in C++ Builder XE 8 (firemonkey)

305 views Asked by At

I am using C++ Builder XE8. As the TOpenDialog doesn't work on Android, I am trying to make such thing myself. My logic is very simple. It'll start to check file and folders from "/storage" and show all items on TListView. If I touch a folder (name) it'll open that folder and if I touch a file, it should show the name on a label. So I assigned a function to TListView's OnItemClick event.

Here is code. fpath is String, Label1 is showing current folder and Label2 is showing selected file.

void __fastcall TForm1::lviewitemclck(TObject * const Sender, TListViewItem * const AItem)
{
if (AItem->Text == "<< BACK") {
        if (!fpath.LastDelimiter("/") == 0) {
            fpath = fpath.SubString(0, fpath.LastDelimiter("/"));

            Label1->Text = fpath;
            Form1->showfiles(fpath);
        }
   }
   else if ( DirectoryExists(fpath+ AItem->Text)) {
            fpath = fpath+ AItem->Text;

            Label1->Text = fpath;
            Form1->showfiles(fpath);
    }
    else if (FileExists(fpath+ AItem->Text)) {
         Label2->Text ="File: "+ fpath+ AItem->Text;
   }
}

Below is the code of function to scan for files & folders and show them. stringlist is TStringList.

void __fastcall TForm1::showfiles (String path)
{

TSearchRec sr;  // for scaning files and folders
TSearchRec fr;  // to check whether the folder is accessible or not.

if (FindFirst(path+"/*", faAnyFile, sr) == 0)
    {
        stringlist->Clear();
        stringlist->Add("<< BACK");  // being used to replace the ".."

        do{
            if(sr.Name != "."   &&   sr.Name != ".."){

                    if (DirectoryExists(path+"/"+sr.Name)) {
                        if (FindFirst(path+"/"+sr.Name+"/*", faAnyFile, fr) == 0) { // to check if the folder is accessible
                            stringlist->Add("/"+ sr.Name);
                        }
                        FindClose(fr);
                    }
                    else{
                        stringlist->Add("/"+ sr.Name);
                    }

            }
        }  while (FindNext(sr) == 0);
    }
    FindClose(sr);

  stringlist->Sort();

  Form1->Item->Free();

  Form1->ListView1->BeginUpdate();

  Form1->ListView1->ClearItems();

for( int i =0;i< stringlist->Count; i++){
     Form1->Item = Form1->ListView1->Items->Add();
     Form1->Item->Text = stringlist->Strings[i];
}
 Form1->ListView1->EndUpdate();

}

Here the problem is, if I use ListView1->ClearItems() in TForm1::showfiles it shows me an error saying "Access violation at address (random no), accessing address 00000009". And if I dont use ClearItems() it just add more lines with already existed lines. I am a beginer, so I dont know where I am doing wrong.

3

There are 3 answers

1
Nompa On

You should use:

ListView1->Items->Clear
0
Jit9 On

The best way I have found so far is to dynamically create TListView and delete it each time you want to add new items( or calling showfiles function). I have written a small function (named it refresh) to release already created TListView and call another function(named it create_lview ) which can create an instance again then it calls the showfiles method.

void __fastcall TForm1::refresh()
{
 if (!lview1->Released()) {
  try{
    lview1->Release();
    Form1->create_lview();
    Form1->showfiles(fpath);
}
catch(...){
    Label2->Text = "error in cleaning";
    }
  }
}

Here is the code to create the TListView whenever you want.

void __fastcall TForm1::create_lview()
{
    lview1 = new TListView(Form1);
    lview1->Parent = Form1;
    lview1->Height = 600;
    lview1->Width = 400;
    lview1->Position->X = 0;
    lview1->Position->Y = 0;
    lview1->Visible = true;
    lview1->Enabled = true;
    lview1->OnItemClick = lviewitemclck;
    lview1->CanSwipeDelete = false;
}

Please comment if you find any mistake or you can do it more efficiently.

0
ito On

I have tried another way to avoid the error by replacing the Clear method with updating the Item Text, then deletes the unused last row of the ListView within the ListView1Change event.

void __fastcall TForm1::ListView1Change(TObject *Sender)
{
  //Delete last item
  while (ListView1->Items->Count>stringlist->Count){
  ListView1->Items->Delete(ListView1->Items->Count-1);
  }
}

void __fastcall TForm1::showfiles (String path)
{


TSearchRec sr;  // for scaning files and folders
TSearchRec fr;  // to check whether the folder is accessible or not.
             //path+PathDelim+

if (FindFirst(path+PathDelim+'*', faAnyFile, sr) == 0)
    {
        stringlist->Clear();
        stringlist->Add("<<--BACK");  // being used to replace the ".."

        do{
            if(sr.Name != "."   &&   sr.Name != ".."){

                    if (DirectoryExists(path+PathDelim+sr.Name)) {
                        if (FindFirst(path+PathDelim+sr.Name+PathDelim+"*", faAnyFile, fr) == 0) { // to check if the folder is accessible
                            stringlist->Add(sr.Name);

                        }
                        FindClose(fr);
                    }
                    else{
                        stringlist->Add(sr.Name);
                    }

            }
        }  while (FindNext(sr) == 0);
    }
    FindClose(sr);

  stringlist->Sort();

  for( int i =0;i< ListView1->Items->Count; i++){
     ListView1->Items->Item[i]->Text="";
  }



 ListView1->BeginUpdate();
 try {


      for( int i =0;i< stringlist->Count; i++)
        {
           if (ListView1->Items->Count-1<i)
           {
            TListViewItem* Item=ListView1->Items->Add();
            Item->Text=stringlist->Strings[i];
           } else
           {
            TListViewItem* Item=ListView1->Items->Item[i];
            Item->Text=stringlist->Strings[i];

           }
        }

     }
 catch (...) {
             }


ListView1->EndUpdate();

/* */
}