First of all, sorry if my title is not all that descrptive and if this has already been answered, I looked around but did not find it so I decided to make my first post/thread.

I am working on a little offline game right now and what I'm trying to do now is getting a ScreenShot button to work.

I know this code

this->picMap->Image->Save("C:\\testBmp.bmp");

can be used to save the image that is on my Map. That would be fine but my player and Npc images are on their own picturebox and I need those to be included into my screenshot. So what I'm asking is how would I use something like ->Save("C:\\testBmp.bmp") to save the images in more then one Picturebox at a time? If that will not work, what would be the next best way to achieve what I am trying to do?

I am using Microsoft Visual C++ 2010.

Thanks in advance for any help.

Recommended Answers

All 12 Replies

you can have pointer array of base type, then add member function to each base such as pictureBase::save(copy pictureBase&){//save procedure}
then you can do like just like this:

for(int i=0;i<coll.size();i++)
coll.save();

or you can do this way:

myArr: public vector<pictureBase&> {
public:
void saveAll(){
for(int i=0;i<coll.size();i++)
coll.save();
}
}

to save the images in more then one Picturebox at a time?

I'm assuming you're doing this as a winforms project? (it seems like that, but there's some ambiguity).

To save more than one picturebox into a bitmap at a time, you're going to have to make a Graphics instance and assign a bitmap to it that that has dimensions big enough to hold all of picturebox images.

You can then use Graphics.DrawImage to place each of those images from the picturebox into the bitmap and save it out like you indicated in your post.

Post back if you're not using Winforms to do this or if any issues crop up.

It is a Windows Form Application.

As for the Graphics.DrawImage, I can't seem to get it working. I'm having a hard time finding information on it with examples for C++.

Would you be able to explain it a little to me or give me an example on how to use it? I need to get the image from

this->Map1->Image

and

this->Map2->Image

onto

this->picMap->Image

I don't want the code written for me, just an example of how to do it since I'm having trouble figuring it out.

I tried this (this is just the button click section of my code) to draw the image from Map1 onto the form using the DrawImage feature but when I click the button nothing happens...

private: System::Void button1_Click(System::Object^  sender, System::EventArgs^  e) {
 pictureBox1 = gcnew PictureBox;
			pictureBox1->Paint += gcnew System::Windows::Forms::PaintEventHandler( this, &Form1::pictureBox1_Paint );
		 }
   void pictureBox1_Paint( Object^ /*sender*/, System::Windows::Forms::PaintEventArgs^ e )
   {
      // Create a local version of the graphics object for the PictureBox.
      Graphics^ g = e->Graphics;

      // Create Point for upper-left corner of image.
      Point ulCorner = Point(0,0);

      // Draw image to screen.
      g->DrawImage( this->Map1->Image, ulCorner );
   }

If I can get this to work then I can use the same code and just change the Point for my second picture so they are both on the form for saving.

Ok after looking at some DrawImage examples I found, I got part of what I need to work now.

I now have this

(in void InitializeComponent(void))

this->picMap->Paint += gcnew System::Windows::Forms::PaintEventHandler(this, &Form1::Form1_Paint);

then I have this -

System::Void Form1_Paint(System::Object^ sender, System::Windows::Forms::PaintEventArgs^ e)
        {
            			Image^ img = this->Map1->Image;
				Image^ img2 = this->Map2->Image;
            e->Graphics->DrawImage(img, 0, 0); // Map1
			e->Graphics->DrawImage(img2, 100, 100); // Map2
        }

That works as far as Drawing two images into my picturebox, but there are two problems.

First, it only draws the image when the first part of the code (this->picMap->Paint) is in the void InitializeComponent(void). I can't get it to do the Form1_Paint function on a button click which is what I need so I can have different Map's drawn on the picMap. Also this paints the image onto the picturebox which is fine for viewing, but I can't figure out how to save the picMap image now. I used this before

this->picMap->Image->Save("C:\\testBmp.bmp");

But since we are painting the Maps on now instead of setting the Image of picMap this save code will not work since the picMap->Image is still blank.

Sorry it took me so long to get back. I had tried to reinstall VC++ 2008 on my computer so I could get better intellisense, but I wasn't able to, so I cobbled this together in VC++ 2010 today.

I never liked to mess around with the Paint handlers unless I knew I was redrawing something over and over. You end up having to invalidate it to get it to redraw.

I'll give my rationale in the comments, you may need to retool this a bit to get what you need.

int combinedwidth = pictureBox1->Width + pictureBox2->Width;
int maxheight = Math::Max(pictureBox1->Height,pictureBox2->Height);
//this assumes the pictureboxes will be mapped right next to each other
//so grab the combined length and get the highest height


Bitmap ^ bmp = gcnew Bitmap(combinedwidth,maxheight);
//We're going to draw on this bitmap

Graphics ^ g = Graphics::FromImage(bmp);
//create a graphics instance and link it up with our premade bitmap

Rectangle rectpb1 = Rectangle(Point(0,0),pictureBox1->Size);
Rectangle rectpb2 = Rectangle(Point(pictureBox1->Width+1,0),pictureBox2->Size);
//Since the 2 original bitmaps had been scaled down to fit the pictureboxes, I'm //building two rectangles the same size of the picturebox, but 2nd is offset the //width of the first picture
//Obviously you can determine the offsets directly from the variables if you need to

g->DrawImage(pictureBox1->BackgroundImage,rectpb1);
g->DrawImage(pictureBox2->BackgroundImage,rectpb2);
//Draw the images right onto the graphics instance

bmp->Save("C:\\Users\\XXXXX\\Pictures\\workofart.jpg");

See if that overall technique works better. Before this code, I had preset the jpgs to the BackgroundImage property of the pictureboxes, and used ImageLayout::Stretch so they were centered.

I'm having a hard time finding information on it with examples for C++.

Yes, this is a chronic problem for doing winforms in C++/CLI. You're best bet is to look for similar C# examples and translate them, as it's really the same .NET framework for both. One of the best I've found is here.

Using the code you provided after making some modifications to it to fit my program I got it to work if I just press one button to draw two pictures and then save it. The problem I'm having now is when I try to incorporate it with what my programs does I am having problems.

Right now this is my current program (only showing the parts of the code that matter to this)

private: System::Void Chunk1_Click(System::Object^  sender, System::EventArgs^  e) {
				 DrawMap(1);
			 }
private: System::Void Chunk2_Click(System::Object^  sender, System::EventArgs^  e) {
				 DrawMap(2);
		 }
private: System::Void Chunk3_Click(System::Object^  sender, System::EventArgs^  e) {
				 DrawMap(3);
		 }
private: System::Void button1_Click(System::Object^  sender, System::EventArgs^  e) {
			 DrawMap(0);
		 }

void DrawMap(int MapNum){
			Bitmap ^ Map = gcnew Bitmap(375,307); 
Graphics ^ g = Graphics::FromImage(Map);
      switch ( MapNum )
      {
         case 0:
			 Map->Save("C:\\testBmp.bmp");
            break;
         case 1:
			 g->DrawImage(Map1->Image, 0, 0);
            break;
         case 2:
			 g->DrawImage(Map2->Image, 50, 50);
			break;
         case 3:
			 g->DrawImage(Map2->Image, 100, 100);
            break;
         default:
			break;
      }		 
 }

The reason I'm using void DrawMap is because I have it so when you click on one of the Chunks it will draw a different image that goes with that chunk (I'm building kind of like a Map Editor program) I need to have the

Bitmap ^ Map = gcnew Bitmap(375,307); 
Graphics ^ g = Graphics::FromImage(Map);

part of the code in the void DrawMap or else I get errors when I go to DrawImage, the problem with this is now every time I call DrawMap void since it calls the bitmap ^ Map code each time it wipes out the old bitmap ^ Map and makes a new one so when I go to save nothing is on the Map to save...

If you declare Map and g as private member variables of your form, you can make a function that instantiates them (sets the values to gcnew Bitmap(375,307) and Graphics::FromImage(Map) respectively. Call this function once from the forms constructor, and any subsequent times you need to "clear" your map. In unmanaged code, any subsequent calls to the function would cause a tremendous memory leak, but the garbage collector will free the memory.

I must be doing something wrong because whenever I try to Declare the Map and g anywhere else in the code I get a lot of different errors. Where and how would I declare them once so I don't have to in void DrawMap?

Up in the middle of the Form1.h where all of the pictureboxes, etc. are declared. Add:

private: Bitmap ^ map;
private: Graphics ^g;

Make a method:

private static void resetGraphics()
{
   map = gcnew Bitmap(375,307); //though you should code these based on dimensions of 
                                //your pictures
   g = Graphics::FromImage(map);
}

And in your form's constructor, call resetGraphics();

Ohhh, I see what you mean now. Ya declaring and then initializing then made it work correctly now. Now I can have all three chunks shown on picMap and saved into a image.

Now I just need to get Control::MousePosition working correctly to set the points where I click because right now it sets them really far off of where I actually click in picMap.

Thanks a lot for your help jonsca, most of my Map Editor is done now and my Screenshot feature in my game works..

Here is the final code for my games Screenshot feature that is fully working now.

void ScreenShot(){
		  Bitmap ^ Screen = gcnew Bitmap(330, 205);
 
			Graphics ^ g = Graphics::FromImage(Screen);	
 
		g->DrawImage(this->BackgroundImage, 0, 0); // Background image (Map/GUI)
g->DrawString(this->lblHp->Text, this->lblHp->Font, System::Drawing::Brushes::Red, this->lblHp->Location); // Hp Label
g->DrawString(this->CombatText1->Text, this->CombatText1->Font, System::Drawing::Brushes::White, this->CombatText1->Location); // TextBox1
g->DrawString(this->CombatText2->Text, this->CombatText2->Font, System::Drawing::Brushes::White, this->CombatText2->Location); // TextBox2
g->DrawString(this->CombatText3->Text, this->CombatText3->Font, System::Drawing::Brushes::White, this->CombatText3->Location); // TextBox3
		g->DrawImage(this->piclvl1heal1->Image, this->piclvl1heal1->Location); // Heal Potion Image
		g->DrawImage(this->Player->Image, this->Player->Location); // Player Image
		g->DrawImage(this->Monster->Image, this->Monster->Location); // Balron Image
 
		  String^ Dir = L"C:\\ZacarasEmpire-Offline\\ScreenShots";
		System::String^ Connect1= System::String::Concat( L"C:\\ZacarasEmpire-Offline\\Screenshots\\ScreenShot_", ScreenShotNum);
	System::String^ Connect= System::String::Concat( Connect1, L".bmp");

		System::String^ Add1= System::String::Concat( L"C:\\ZacarasEmpire-Offline\\ScreenShots\\Screenshot_", (ScreenShotNum + 1));
	System::String^ Add= System::String::Concat( Add1, L".bmp");
			  if (  !Directory::Exists( Dir ) ){ // Check for ScreenShot Directory
				 Directory::CreateDirectory( Dir );
			  }
		  if ( File::Exists( Connect ) ){ // Check for other ScreenShots
				Screen->Save( Add );
		  } else {
				Screen->Save( Connect );
		  }
	ScreenShotNum = (ScreenShotNum + 1);
		ScreenShotNum = ScreenShotNum;
}
commented: Hello I come from Vietnam. I am learning to use opencv. I think your project is very good, could you please ask me for your project? I thank you very +0
Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.