Click to See Complete Forum and Search --> : n00b Questions for Visual C++ .NET


functor
April 11th, 2005, 05:10 PM
Hey!

I'm new to the whole .NET scene, and infact the windows programming scene too. I'm used to command line stuff in linux. I'm making an app that accesses a database, retreives some information. When I get the information from the DB, I put it into some classes that I built to store the information.

So far I've been able to create 2 listviews and have data show up in them. I am quite certain that I don't have things setup correctly tho. Right now, I have all my code for populating the listviews in InitializeComponents() function. I'm pretty sure its not supposed to be there as when I put it there, I can no longer alter the look of my form using the GUI.

I also tried putting it in System::Void listView1_SelectedIndexChanged (ie - the function that comes up when you double click on the listview in the GUI), but I can't access the data in my classes without creating a new object and retreieving all my information from the database again - I need to make it accessibale to all functions.

Also, as it is right now the contents of listview2 are static, but what I need to happen is when I click on a row in listview1, listview 2 changes its contents to the appropriate data.

If someone could point me in the right direction or maybe has a link to some beginners tutorials that might help me out, It'd really be appreciated. Thanks!

dumbquestion
April 12th, 2005, 12:59 PM
I'm not sure when you would like your listViews populated, but if you want that done when the form window is opened, you could put that code under the "Load" event. A quick way to create this event is to double-click on the title bar of the form in the GUI view.

As for the updating listView2 based on a change in listView1, I think using the listView1_SelectedIndexChanged event is the way to go. It might help if you post your code.

functor
April 12th, 2005, 05:04 PM
Thanks! I have no clue as to where things are supposed to go.

I moved my declarations over to the load function and now I get a weird result. The program runs with no errors, but in my first 3 rows in the listview, the 2nd, 3rd, 4th and 5th subitems are deleted. These items are fine in rows 4 and 5. I used the debug and the data in my objects is all correct, and I also checked where I put them into the listview and it was correct going in. It's almost like they are being overwritten after they are being inserted. I have no other code that alters the listviews. I also tried cut/paste the code from my load function into the InitializeComponents function just to see if that still worked and everything is fine when it is in there, but I don't think I should have it in there. This is my load function:

private: System::Void Form1_Load(System::Object * sender, System::EventArgs * e)
{
bingomonitor bm;
bm.getBingoHalls();

String *ItemObject1;
String *ItemObject2;
String *ItemObject3;
String *ItemObject4;
String *ItemObject5;

for (int i = 0; i < bm.numHalls; i++)
{
ListViewItem *items = new ListViewItem(S"helal",0);

ItemObject1 = bm.halls[i].hallCode;
ItemObject2 = bm.halls[i].hallName;
ItemObject3 = bm.halls[i].stationID;
ItemObject4 = bm.halls[i].stationName;
ItemObject5 = bm.halls[i].hallStatus;

listView1->Items->Add(ItemObject1);
listView1->Items->Item[i]->SubItems->Add(ItemObject2);
listView1->Items->Item[i]->SubItems->Add(ItemObject3);
listView1->Items->Item[i]->SubItems->Add(ItemObject4);
listView1->Items->Item[i]->SubItems->Add(ItemObject5);
}

for ( i = 0; i < bm.halls[1].numGames; i++)
{
ListViewItem *items = new ListViewItem(S"helal2",0);

ItemObject1 = bm.halls[1].hallGames[i].gameNumber;
ItemObject2 = bm.halls[1].hallGames[i].currentBooked;
ItemObject3 = bm.halls[1].hallGames[i].transmitSales;
ItemObject4 = bm.halls[1].hallGames[i].gameStatus;

listView2->Items->Add(ItemObject1);
listView2->Items->Item[i]->SubItems->Add(ItemObject2);
listView2->Items->Item[i]->SubItems->Add(S"---");
listView2->Items->Item[i]->SubItems->Add(S"---");
listView2->Items->Item[i]->SubItems->Add(ItemObject3);
listView2->Items->Item[i]->SubItems->Add(S"---");
listView2->Items->Item[i]->SubItems->Add(ItemObject4);
}
}

dumbquestion
April 12th, 2005, 07:39 PM
I checked out the .NET help under "listView class" in the "listView overview" section and they had a good example. I simplified it a little bit below, and added it as a function that is called after "InitializeComponent()". I don't think you need to call it in the Load handler as I had suggested before.


#pragma once

namespace listviewtry
{
using namespace System;
using namespace System::ComponentModel;
using namespace System::Collections;
using namespace System::Windows::Forms;
using namespace System::Data;
using namespace System::Drawing;

/// <summary>
/// Summary for Form1
///
/// WARNING: If you change the name of this class, you will need to change the
/// 'Resource File Name' property for the managed resource compiler tool
/// associated with all .resx files this class depends on. Otherwise,
/// the designers will not be able to interact properly with localized
/// resources associated with this form.
/// </summary>
public __gc class Form1 : public System::Windows::Forms::Form
{
public:
Form1(void)
{
InitializeComponent();
CreateMyListView();
}

protected:
void Dispose(Boolean disposing)
{
if (disposing && components)
{
components->Dispose();
}
__super::Dispose(disposing);
}

private: System::Windows::Forms::ListView * listView1;

private:
/// <summary>
/// Required designer variable.
/// </summary>
System::ComponentModel::Container * components;

/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
void InitializeComponent(void)
{
this->listView1 = new System::Windows::Forms::ListView();
this->SuspendLayout();
//
// listView1
//
this->listView1->Location = System::Drawing::Point(24, 40);
this->listView1->Name = S"listView1";
this->listView1->Size = System::Drawing::Size(400, 424);
this->listView1->TabIndex = 2;
//
// Form1
//
this->AutoScaleBaseSize = System::Drawing::Size(5, 13);
this->ClientSize = System::Drawing::Size(456, 510);
this->Controls->Add(this->listView1);
this->Name = S"Form1";
this->Text = S"Form1";
this->ResumeLayout(false);
}

private:
void CreateMyListView()
{
listView1->View = View::Details;
// Allow the user to edit item text.
listView1->LabelEdit = true;
// Allow the user to rearrange columns.
listView1->AllowColumnReorder = true;
// Display check boxes.
listView1->CheckBoxes = true;
// Select the item and subitems when selection is made.
listView1->FullRowSelect = true;
// Display grid lines.
listView1->GridLines = true;
// Sort the items in the list in ascending order.
//listView1->Sorting = SortOrder::Ascending;

String *_ItemObject1 = S"hallcode";
String *_ItemObject2 = S"hallname";
String *_ItemObject3 = S"stationid";
String *_ItemObject4 = S"stationname";
String *_ItemObject5 = S"hallstatus";

String *ItemObject1, *ItemObject2, *ItemObject3, *ItemObject4, *ItemObject5;

listView1->Columns->Add(S"hall code", -2, HorizontalAlignment::Left);
listView1->Columns->Add(S"hall name", -2, HorizontalAlignment::Left);
listView1->Columns->Add(S"station id", -2, HorizontalAlignment::Left);
listView1->Columns->Add(S"station name", -2, HorizontalAlignment::Left);
listView1->Columns->Add(S"hall status", -2, HorizontalAlignment::Left);

ListViewItem *item;
int i;
for (i=0; i<3; i++)
{
item = new ListViewItem(S"helal",0);
ItemObject1 = String::Concat(_ItemObject1, Convert::ToString(i));
ItemObject2 = String::Concat(_ItemObject2, Convert::ToString(i));
ItemObject3 = String::Concat(_ItemObject3, Convert::ToString(i));
ItemObject4 = String::Concat(_ItemObject4, Convert::ToString(i));
ItemObject5 = String::Concat(_ItemObject5, Convert::ToString(i));

item->SubItems->Add(ItemObject2);
item->SubItems->Add(ItemObject3);
item->SubItems->Add(ItemObject4);
item->SubItems->Add(ItemObject5);

listView1->Items->Add(item);
}
}

};
}



Not sure if this is exactly what you were hoping for, but hope it helps!

functor
April 13th, 2005, 05:02 PM
Thanks man! I was able to get the lists displaying what they should be display with your help.

Where I am right now, is I have moved all the list populating stuff over to the Load function as when I had it in the CreateList function I wasn't able to access the list information when in listView1_SelectedIndexChanged. But now I can. What I have setup now is when you click on a row in listView1 it clears listView2. Once listView2 is cleared, seems to me like I can just rebuild the data in it just like I did the first time... But there is another problem - the scope of my own class object.

In the listView1_SelectedIndexChanged function I try and access an object I created in the Load function and it says its undefined. Below is the function. I get the error on bm.numHalls - undeclared identifier. I tried moving it (it being the declaration of 'bm') into InitializeComponents, I tried moving it to the load function, I tried making it a global variable in form.cpp, and always get the same error. I need to get acceess to this information to correctly populate the 2nd list. Where do I need to put the declaration or how do I need to declare it so that it is accessible to all the functions?

private: System::Void listView1_SelectedIndexChanged(System::Object * sender, System::EventArgs * e)
{
String *selectedHallCode;
selectedHallCode = listView1->SelectedItems->get_Item(0)->ToString();
listView2->Items->Clear();

int index = 0;
while (index < bm.numHalls)
{
if (bm.halls[index].hallCode == selectedHallCode)
break;
index++;
}

for (i = 0; i < bm.halls[index].numGames; i++)
{
ItemObject1 = bm.halls[index].hallGames[i].gameNumber;
ItemObject2 = bm.halls[index].hallGames[i].currentBooked;
ItemObject3 = bm.halls[index].hallGames[i].transmitSales;
ItemObject4 = bm.halls[index].hallGames[i].gameStatus;

item = new ListViewItem(ItemObject1,0);

item->SubItems->Add(ItemObject2);
item->SubItems->Add(S"---");
item->SubItems->Add(S"---");
item->SubItems->Add(ItemObject3);
item->SubItems->Add(S"---");
item->SubItems->Add(ItemObject4);

listView2->Items->Add(item);
}

}

darwen
April 13th, 2005, 06:06 PM
One sentence :

Use C#

You're knowledge with C++.NET won't be wasted. That's the advantage of using a .NET language. It's just so much easier to do things in C# than C++.NET.

The above solution will still work, but please take a look at C#.

Intellisense is much better under C#, and I'd be surprised if the VC++.NET form designer is as good as C#'s. That point I can be proven wrong on of course...

Darwen.

functor
April 14th, 2005, 09:24 AM
Could it have anything to do with the way I have created my classes? I just made my own .h and .cpp files like I used to for console programs. Here are my 3 .h files for 3 classes:

//bingomonitor.h
//-------------------
#pragma once
using namespace System;
using namespace System::ComponentModel;
using namespace System::Collections;
using namespace System::Windows::Forms;
using namespace System::Data;
using namespace System::Drawing;

class bingomonitor
{
public:
bingomonitor(void);
~bingomonitor(void);
void getBingoHalls(void);
void stringToCharArray(char *, String *);
int findHallCodeIndex(String *);

hall halls[MAX_HALLS];

int numHalls;

};


//hall.h
//-------
#pragma once
#include "game.h"
#using <mscorlib.dll>
using namespace System;
using namespace System::Collections;
using namespace System::ComponentModel;
using namespace System::Windows::Forms;
using namespace System::Data;
using namespace System::Drawing;

class hall
{
public:
hall(void);
~hall(void);
void getGames(void);
void stringToCharArray(char *, String *);

char hallCode[MAX_STRING_LENGTH];
char hallName[MAX_STRING_LENGTH];
char stationID[MAX_STRING_LENGTH];
char stationName[MAX_STRING_LENGTH];
char hallStatus[MAX_STRING_LENGTH];

game hallGames[MAX_GAMES_PER_HALL];
int numGames;
};


//game.h
//---------
#pragma once
#using <mscorlib.dll>
using namespace System;
using namespace System::Collections;

class game
{
public:
game(void);
~game(void);

char gameNumber[MAX_STRING_LENGTH];
char currentBooked[MAX_STRING_LENGTH];
char lastReBooked[MAX_STRING_LENGTH];
char printed[MAX_STRING_LENGTH];
char transmitSales[MAX_STRING_LENGTH];
char transmitSalesSuccess[MAX_STRING_LENGTH];
char gameStatus[MAX_STRING_LENGTH];
};

functor
April 14th, 2005, 04:50 PM
Ok, I got it working!!! I click on one item in list1 and it changes the appropriate contents in list2. Of course its not perfect...

The first time I click on a row in list1 it changes list2 nicely. After it changes list2, if I click on another row in list1 i get an unhandled exception with the following text:

System.ArgumentOutOfRangeException: Specified argument was out of the range of valid values.
Parameter name: index
at System.Windows.Forms.SelectedListViewItemCollection.get_Item(Int32 index)
at BM2.Form1.listView1_SelectedIndexChanged(Object sender, EventArgs e) in c:\documents and settings\dhooper\my documents\visual studio projects\bm2\bm2\form1.h:line 120

The if I click "Continue" the program just continues on with the correct information being displayed in the lists even though every time I click on a row (after the first time) in list1 i get the unhandled exception.

Here is the code for my change function. What do I need to do to take care of this? I've marked line 120 with // line 120:

private: System::Void listView1_SelectedIndexChanged(System::Object * sender, System::EventArgs * e)
{
String * selectedHallCode;
selectedHallCode = listView1->SelectedItems->get_Item(0)->Text->ToString();

Char selHallCode[];
selHallCode = selectedHallCode->ToCharArray(); // line 120

int index = 0;
int i = 0;
int j = 0;

bingomonitor bm2;
bm2.getBingoHalls();

for (i = 0; i < bm2.numHalls; i++)
{
while (bm2.halls[i].hallCode[j] == selHallCode[j])
{
if ((j + 1) == selHallCode->get_Length())
{
index = i;
break;
}
j++;
}
j = 0;
}

listView2->Items->Clear();
ListViewItem *item;

String *ItemObject1,
*ItemObject2,
*ItemObject3,
*ItemObject4;

for (int i = 0; i < bm2.halls[index].numGames; i++)
{
ItemObject1 = bm2.halls[index].hallGames[i].gameNumber;
ItemObject2 = bm2.halls[index].hallGames[i].currentBooked;
ItemObject3 = bm2.halls[index].hallGames[i].transmitSales;
ItemObject4 = bm2.halls[index].hallGames[i].gameStatus;

item = new ListViewItem(ItemObject1,0);

item->SubItems->Add(ItemObject2);
item->SubItems->Add(S"---");
item->SubItems->Add(S"---");
item->SubItems->Add(ItemObject3);
item->SubItems->Add(S"---");
item->SubItems->Add(ItemObject4);

listView2->Items->Add(item);
}

}