Opening Multiple Files

Hello, I'm fairly new to C++ programming and I need some help with this code I'm trying to manipulate.

I was given this code for this program that opens .raw files and reads them, but the problem is that when I click the button and add the image .raw file I can only select one. Then I have to repeat this process all over again (click the button, find the file, click open). It gets kind of ridiculous when I have 40+ files. Ideally I would like to be able to hold the control key and select all the files and have the program read them one by one, but I'm not quite sure how to go about it this way. The only way I can comprehend is making a FOR loop, but I'm not sure exactly where to put it. All the files are in the same folder on the C:\\ drive, and they're all named a1.raw, a2.raw, a3.raw... etc. It seems like it would be a simple loop but I can't quite figure it out. Any help would be greatly appreciated. Thanks.

Here's the code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
private: System::Void button1_Click(System::Object^  sender, System::EventArgs^  e)
/********************button 1 add image file and display scaled resultant************/

{	OpenFileDialog^ openfile=gcnew OpenFileDialog();
				openFileDialog1->InitialDirectory = "C:\\";
				openFileDialog1->Filter = 
				"Raw Image (*.raw)|*.raw";
				openFileDialog1->FilterIndex = 1;
				
			
			if (openFileDialog1->ShowDialog() == System::Windows::Forms::DialogResult::OK )
	
			{	
				
				
			int valueA;
			int i;
			int j;
			//Read the binary file				
			FileStream^ f1 = gcnew FileStream(openFileDialog1->FileName, FileMode::Open);
			BinaryReader^ br1 = gcnew BinaryReader(f1);
				
			// ... from here it goes on to read the binary file

			}						 
	}
I apologize that I don't have time to throw together a quick example - but I believe you need to set the "Multiselect" property of the dialog before showing it:

openFileDialog1->Multiselect = true;

Having completed the selection, you should be able to use openFileDialog1->SafeFileNames which is an array of strings representing each filename.

for each (String^ file in openFileDialog1->SafeFileNames) {
// Do something with "file" here
}

Hope this helps,
CC
Last edited on
Thank you so much for getting me started CC, it means a lot. However I'm still having some difficulty, which is probably due to my lack of knowledge of openFileDialog.

So I've taken what you said and tried to put whatever made sense to me in the code. Here's the updated code (hopefully this is correct, but I might be misplacing things):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
private: System::Void button1_Click(System::Object^  sender, System::EventArgs^  e)
/********************button 1 add image file and display scaled resultant************/

{	OpenFileDialog^ openfile=gcnew OpenFileDialog();
				openFileDialog1->InitialDirectory = "C:\\";
				openFileDialog1->Filter = 
				"Raw Image (*.raw)|*.raw";
				openFileDialog1->FilterIndex = 1;
				openFileDialog1->Multiselect = true;	
				openFileDialog1->SafeFileNames;	
				for each (String^ file in openFileDialog1->SafeFileNames) { 
                                     // Do something with "file" here
                                     }
			
			if (openFileDialog1->ShowDialog() == System::Windows::Forms::DialogResult::OK )
	
			{	
				
				
			int valueA;
			int i;
			int j;
			//Read the binary file				
			FileStream^ f1 = gcnew FileStream(openFileDialog1->FileName, FileMode::Open);
			BinaryReader^ br1 = gcnew BinaryReader(f1);
				
			// ... from here it goes on to read the binary file

			}						 
	}


But I'm not sure exactly what to do with the "file". Is this where I indicate what the files will look like (e.g. a1.raw, a2.raw, ... etc)? If this is the case, would I have to make it look similar to ai.raw, where i = 1,2,3,... etc? Thanks for any help in advance.
Sorry - the order should be a little different:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

private: System::Void button1_Click(System::Object^  sender, System::EventArgs^  e)
/********************button 1 add image file and display scaled resultant************/

{	OpenFileDialog^ openfile=gcnew OpenFileDialog();
				openFileDialog1->InitialDirectory = "C:\\";
				openFileDialog1->Filter = 
				"Raw Image (*.raw)|*.raw";
				openFileDialog1->FilterIndex = 1;
				openFileDialog1->Multiselect = true;	
			
			if (openFileDialog1->ShowDialog() == System::Windows::Forms::DialogResult::OK )
	
			{	
				for each (String^ file in openFileDialog1->SafeFileNames) { 
                                     // This line will be executed once for each file that was selected.
		                     //Read the binary file				
			            FileStream^ f1 = gcnew FileStream(file, FileMode::Open);
			            BinaryReader^ br1 = gcnew BinaryReader(f1);
				
			             // ... from here it goes on to read the binary file
                        }
		}						 
	}


I'm not in a position to compile the above - buy I hope that explains what I meant.

The SafeFileNames member of the class gets set when files are selected and okay is clicked. At that point it will fill in the array to contain one entry for each filename. So when it finally returns from ShowDialog, that array is ready for you to use.

Hope that helps,
CC
Last edited on
Sorry I think I screwed up when I copied the code over. Some of the brackets ended before I thought they would, but let me explain what happened in the code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
private: System::Void button1_Click(System::Object^  sender, System::EventArgs^  e)
/********************button 1 add image file and display scaled resultant************/
		 {	OpenFileDialog^ openfile=gcnew OpenFileDialog();
				openFileDialog1->InitialDirectory = "C:\\";
				openFileDialog1->Filter = 
				"Raw Image (*.raw)|*.raw";
				openFileDialog1->FilterIndex = 1;
				openFileDialog1->Multiselect = true;			//added
			
			if (openFileDialog1->ShowDialog() == System::Windows::Forms::DialogResult::OK )
			{	
			for each (String^ file in openFileDialog1->SafeFileNames) {  //this currently only selects one .raw image even if two or more are highlighted.

			int valueA;
			int i;
			int j;
			//Read the binary file				
			FileStream^ f1 = gcnew FileStream(openFileDialog1->FileName, FileMode::Open);             //should this still say openFileDialog1->FileName?
			BinaryReader^ br1 = gcnew BinaryReader(f1);
				
			
						for ( j = 0 ; j < (480) ; j++) {
						for ( i = 0 ; i < (640) ; i++){
						valueA=unsigned(br1->ReadInt32());
						
						img[j][i]=valueA;}
						}
			

						f1->Close();
			delete (IDisposable^) f1;}							//added "}" for SafeFileNames
			}									//this bracket ends the IF (openFileDialog->ShowDialog... )statement

			//When "for each (String^ file in openFileDialog1->SafeFileNames)" is placed here the image counter reads the number of highlighted .raw files, but still only imports one.

			dbGraphics->Clear(Color::White);
			
			int i;
			int j;
			
			int max,min;
				for ( j = 0 ; j < (480) ; j++) {
				for ( i = 0 ; i < (640) ; i++){
						acc[j][i]=acc[j][i]+safe_cast<signed int>(img[j][i]);
						scaled[j][i]=acc[j][i];}
						}
			imgcounter=imgcounter+1;											//Here is the image counter
			imgcount->Text=imgcounter.ToString();
			max=0;
			min=scaled[0][0];
			int sig;
			float signal;
			for ( j = 0 ; j < (480) ; j++) {
						for ( i = 0 ; i < (640) ; i++ ){
						if (scaled[j][i]>max)
						{max=scaled[j][i];}
						else if(scaled[j][i]<min)
						{min=scaled[j][i];}
						}
						}
			for ( j = 0 ; j < (480) ; j++) {
			for ( i = 0 ; i < (640) ; i++ ){
						sig=scaled[j][i]-min;
						signal=safe_cast<float>(sig);
						if (signal!=0){	
							signal=(signal/(max-min))*maxscale;}
						scaled[j][i]=safe_cast<int>(signal);
						float xx= safe_cast<float>(i);
						float yy= safe_cast<float>(j);			
						dbGraphics->DrawLine(redblue[(scaled[j][i])],xx,yy,xx+1,yy+1);}
			}


 
   
			
						for ( j = 0 ; j < (480) ; j++) {
						for ( i = 0 ; i < (640) ; i++){
						img[j][i]=0;}
						}

 

									 
	}


/*************************************End button 1***********************************************/


Is there something that is missing for the Multiselect to work?
I think I see the problem: you have been used to using the member openFileDialog1->FileName, which is a string, but when you use the dialog with MultiSelect enabled, we instead use openFileDialog1->SafeFileNames - because we need a collection to hold that collection of file names.

Additionally, I've probably confused you by using:
 
for each (String^ file in openFileDialog1->SafeFileNames) {


Remember - all this is doing is looping through an array of strings. What it means is, for each member of the "SafeFileNames" array (i.e. for each selected file) execute the code is the brackets "{}". When inside those brackets the variable "file" is equal to the current member of the array.

In the snippet of code you wrote below, you

1
2
//Read the binary file				
FileStream^ f1 = gcnew FileStream(openFileDialog1->FileName, FileMode::Open);             //should this still say openFileDialog1->FileName? 


It should have said:
1
2
//Read the binary file				
FileStream^ f1 = gcnew FileStream( file, FileMode::Open);


Nearly there :)
CC

I feel like we're really close, but when I use:
1
2
//Read the binary file				
FileStream^ f1 = gcnew FileStream( file, FileMode::Open);

in place of:
1
2
//Read the binary file				
FileStream^ f1 = gcnew FileStream(openFileDialog1->FileName, FileMode::Open);

I get an error message that tells me it can't find the file: "An unhandled exception of type 'System.IO.FileNotFoundException' occurred in mscorlib.dll
Additional information: Could not find file 'c:\documents and settings\rmlab\desktop\data2\data\data\a2.raw'."

I'm a little confused because the actual path that should be followed to get to file a2.raw isn't what it reads in the additional information "c:\documents and settings\...etc." So I understand that the "SafeFileNames" array contains the strings (aka .raw files), but I'm guessing that the FileStream is able to read the string but is having trouble finding where exactly these files are. Is this logical? If this is the case I'm not too sure how to go about changing the pathway to the file.

Thanks again for all your help.
Nevermind CC, I've finally figured it out. I'm not sure if this was the most efficient way, but it works.

I realized that FileNames was the array that stored all the paths to the .raw files. So all I had to do was change SafeFileNames to FileNames and it works. :)

Thanks for all your help, couldn't have done it without you.
Well done - happy to have helped.

You are absolutely correct in your analysis: The MS documentation points out that "SafeFileNames" member does not include path name! It's some sort of safety feature (hence the name I suppose).

Sorry for the confusion - and well done for discovering the answer on your own :)
CC
Last edited on
Topic archived. No new replies allowed.