Jump to content
Xtreme .Net Talk

Recommended Posts

Posted

Hello,

 

I am very new to GDI and Windows .net Forms - please forgive me for any sacrilegeous use of its components! :)

 

Fiddling with tutorials, I have devised the class whose code is detailed below. All the methods work fine, the custom 'drawFittest' function draws what it is required to draw. However, it is being called frequently from inside a while loop in the main program and the form becomes irresponsive while displaying its contents.

 

This GUIDE class is meant to be a viewscreen that shows data as it is being processed. Right now, it displays ok - but I cannot resize or move etc. If I drag the mouse over the form the windows hourglass shows, and if I attempt to drag it - there is a slight delay before it does drag, and after this it does not display contents properly anymore.

 

Any help appreciated, it is being called like this:

 

main program:

int main( void ){
GUIDE   *screen = new GUIDE();
screen->Show();
screen->Refresh();

run_GA( screen ); // this calls the loop that calls the drawFittest method
if( csv ) fout.close();

return 0;
}

 

 

#using <mscorlib.dll>
#using <System.dll>
#using <System.Drawing.dll>
#using <System.Windows.Forms.dll>

using namespace System;
using namespace System::Drawing;
using namespace System::Windows::Forms;

__gc class GUIDE : public Form {
private:
PictureBox  *PictBox;
Point        p1, p2;
Graphics    *g;
Pen		    *red, *black;
CITY        *c, *d;
double       lastFitness;
unsigned int from, to;
public:

void GUIDE::drawFittest( GASTRING * fittest ){

	if( fittest->fitness != 1000000000 && fittest->fitness != lastFitness ){
		Refresh();
		std::vector<CITY*>::iterator i;
		for( i = cities.begin() ; i != cities.end() ; ++i ){
			c  = *i;
			p1 = Point( (int)c->x, (int)c->y );
			p2 = Point( (int)c->x, (int)c->y + 5 );
			g->DrawLine( black, scale( p1 ), scale( p2 ) );
		}
		
		unsigned int size = fittest->genome.size();
		for( unsigned int i = 0 ; i < size ; i++ ){
			from = fittest->genome[i] - 1;
			to   = fittest->genome[(i+1)%size] - 1;
               c    = cities[from];			
			d    = cities[to];
			p1   = Point( (int)c->x, (int)c->y );
			p2   = Point( (int)d->x, (int)d->y );
			g->DrawLine( red, scale( p1 ), scale( p2 ) );            
		}

		lastFitness = fittest->fitness;
	}
}

Point scale( Point p ){
	int width      = 540;
	int height     = 480;
	int max_width  = 1800;
	int max_height = 1800;

	return Point( p.X * width / max_width , p.Y * height / max_height  );
}

GUIDE(){
	Text				 = S"Map box";
	Size				 = Drawing::Size(580, 545);
	PictBox				 = new PictureBox;
	PictBox->BorderStyle = BorderStyle::FixedSingle;
	PictBox->BackColor   = Drawing::Color::White;
	PictBox->Location    = Point(16, 16);
	PictBox->Size		 = Drawing::Size(540, 480);
	Controls->Add(PictBox);
	g					 = Graphics::FromHwnd( PictBox->Handle );
	red					 = new Pen( Color::Red, 1 );
	black				 = new Pen( Color::Black, 1 );
	lastFitness			 = 0;
}
};

 

Thanks for any help!

Regards.

Alex

Posted

If you're so very new to .net like you told... why did you start with the hardest language?? :P

 

Not only most of us wouldn't be able to help you but you'll have a lot of troubles on your path...

 

A friend advise woulb be for you to consider start with C# (I say C# cause it's the most C++ alike language) and when you feel confortable with the .net plattform and feel the need to take the leap to C++.net it wuold be a lot easyer...

 

Just to note that you'll never feel the need to use C++.net unless you need to code something very very very specific like a driver or something like that...

 

Alex :p (friend advisor) :D:D

Software bugs are impossible to detect by anybody except the end user.
Posted

Hi,

 

I've been doing c++ on linux for a long time now - my challenge isn't with the language - but instead with the GDI+ which is windows based (new world for me). Sometimes it's just easier on linux ;) Unfortunately, this is to be presented on a windows platform.

 

I'm not very fond of platform specific languages, and as such I will likely stay away from C#. This is a genetic algorithm and I'd like to keep things as bitwise as possible :)

 

 

Cheers.

Alex

Posted

Hi.

 

I've since changed my guide class to look like this:

 

#using <mscorlib.dll>
#using <System.dll>
#using <System.Drawing.dll>
#using <System.Windows.Forms.dll>

using namespace System;
using namespace System::Drawing;
using namespace System::Windows::Forms;

__gc class GUIDE : public Form {
private:
PictureBox			*PictBox;
Point				 p1, p2, fpoint;
Graphics			*g;
Pen					*red, *black;
CITY				*c, *d;
double				 lastFitness;
unsigned int		 from, to;
Drawing::Font       *arial;
Drawing::SolidBrush *brush;

public:

void GUIDE::drawFittest( GASTRING * fittest, int generation ){
	stringstream s;
	if( fittest->fitness != 1000000000 && ( fittest->fitness != lastFitness  || generation % 100 == 0 )  ){
		Refresh();
		std::vector<CITY*>::iterator i;
		for( i = cities.begin() ; i != cities.end() ; ++i ){
			c  = *i;
			p1 = Point( (int)c->x, (int)c->y );
			p2 = Point( (int)c->x, (int)c->y + 5 );
			g->DrawLine( black, scale( p1 ), scale( p2 ) );
		}
		
		unsigned int size = fittest->genome.size();
		for( unsigned int i = 0 ; i < size ; i++ ){
			from = fittest->genome[i] - 1;
			to   = fittest->genome[(i+1)%size] - 1;
               c    = cities[from];			
			d    = cities[to];
			p1   = Point( (int)c->x, (int)c->y );
			p2   = Point( (int)d->x, (int)d->y );
			g->DrawLine( red, scale( p1 ), scale( p2 ) );            
		}

		s  << "Distance [" << fittest->fitness << "]";
		System::String *fitstr = new System::String( s.str().c_str() );
		g->DrawString( fitstr, arial, brush, fpoint );
		lastFitness = fittest->fitness;
	}
}

Point scale( Point p ){
	int width      = 540;
	int height     = 480;
	int max_width  = 1800;
	int max_height = 1800;

	return Point( p.X * width / max_width , p.Y * height / max_height  );
}

GUIDE(){
	Text				 = S"Map box";
	Size				 = Drawing::Size(580, 545);
	PictBox				 = new PictureBox;
	PictBox->BorderStyle = BorderStyle::FixedSingle;
	PictBox->BackColor   = Drawing::Color::White;
	PictBox->Location    = Point(16, 16);
	PictBox->Size		 = Drawing::Size(540, 480);
	Controls->Add(PictBox);
	g					 = Graphics::FromHwnd( PictBox->Handle );
	red					 = new Pen( Color::Red, 1 );
	black				 = new Pen( Color::Black, 1 );
	lastFitness			 = 0;
	arial			     = new System::Drawing::Font( "Arial", 10 );
	brush                = new System::Drawing::SolidBrush( Color::Black );
	fpoint				 = Point( 410, 460 );
}
};

 

And the function that gets this going looks like this:

 

int main( void ){
GUIDE   *screen = new GUIDE();
screen->Show();
screen->Refresh();

fittest = new GASTRING();
fittest->fitness = 1000000000;
srand( (unsigned)time(NULL) );

if( csv ) fout.open( "output.txt" );

load_cities();
build_travel_matrix();
generate_population();
run_GA( screen );
if( csv ) fout.close();

return 0;
}

void run_GA( GUIDE * screen ){

bool	match			= false;
double  last_distance	= 0;
int		last_count		= 0;	

while( !match && ++generation ){	
	screen->drawFittest( fittest, generation );
	reproduction_cycle();			    // mate + xover + mutation
	
	if( fittest->fitness == last_distance ){
		last_count++;
	}
	else{	
		last_count    = 0;
		last_distance = fittest->fitness;
	}

	if( last_count == 1000 ){
		cout << "Fitness has not changed in past 1000 generations.  Exiting." << endl;
           match = true;
	}
}
return;
}

 

Thanks!

Alex

  • *Experts*
Posted

You don't seem to give your application enough time to process messages. Its stuck in the loop only doing what you specified in the loop. To allow your application to process messages use this:

System::Windows::Forms::Application::DoEvents();

Now your application will be able to process the messages including resize, move etc. Stick that line of code at the bottom of your loop or anywhere in your loop.

Posted

Looks like I've answered my own question by simply trying it out :) I have another for you though..

 

When I close the screen now (moving and everything works wonderfully. I get this error:

 

Unhandled Exception: System.Runtime.InteropServices.ExternalException: A generic

error occurred in GDI+.

at System.Drawing.Graphics.DrawLine(Pen pen, Int32 x1, Int32 y1, Int32 x2, In

t32 y2)

at System.Drawing.Graphics.DrawLine(Pen pen, Point pt1, Point pt2)

at GUIDE.drawFittest(GASTRING* fittest, Int32 generation) in guide.h:line 33

 

I've tried perhaps considering that the screen once closed would become null and wrapping the calls inside an:

 

	if( screen ){
		screen->drawFittest( fittest, generation );
		System::Windows::Forms::Application::DoEvents();
	}

 

However this doesn't seem to be the ticket. What happens to the screen object once closed? How can I prevent from any writing once the screen gets disposed of?

 

Thanks!

Alex

  • *Experts*
Posted
You can prevent drawing to the form by checking the Created property of the Form object. If its false then the form is closed and you can exit the loop.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...