GDI+ Sample: Move the Origin


This is an example of simulating a screen saver I was trying to write. A circle is drawn with its center at the intersection of the axes. Then the horizontal and the vertical axis are drawn with the origin in the center of the circle. To simulate a screen saver, the origin is moved around the screen. The circle must always be drawn with its center at the origin. Therefore, as the origin is moving, the circle also is moving. Or, as the circle is moving, the origin also is moving. The axes are drawn like the old axes of AutoCAD.

Practical Learning: Starting the Exercise

  1. Start Microsoft Visual C++ .Net and create a new Windows  named MoveOrigin
  2. Change the properties of the form as follows:
    BackColor: Black
    FormBorderStyle: None
    WindowState: Maximized
  3. Double-click the middle of the form to generate its Load event
  4. Return to the form and, in the Events section of the Properties window, generate a KeyPress event for it
  5. Return to the form and add a Timer control to it
  6. Set the timer's Enabled to True and its Interval to 10 (or, set to 5 for a fast speed or 20 or 40 to go slower)
  7. Double-click the timer and change the file as follows
    #pragma once
    namespace MoveOrigin
    	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
    		void Dispose(Boolean disposing)
    			if (disposing && components)
    	private: System::Windows::Forms::Timer *  timer1;
    	private: System::ComponentModel::IContainer *  components;
    		/// <summary>
    		/// Required designer variable.
    		/// </summary>
    		/// <summary>
    		/// Required method for Designer support - do not modify
    		/// the contents of this method with the code editor.
    		/// </summary>
    		void InitializeComponent(void)
    			this->components = new System::ComponentModel::Container();
    		this->timer1 = new System::Windows::Forms::Timer(this->components);
    			// timer1
    			this->timer1->Enabled = true;
    			this->timer1->Interval = 10;
    			this->timer1->Tick += new System::EventHandler(this, timer1_Tick);
    			// Form1
    			this->AutoScaleBaseSize = System::Drawing::Size(5, 13);
    			this->BackColor = System::Drawing::Color::Black;
    			this->ClientSize = System::Drawing::Size(292, 266);
    		this->FormBorderStyle = System::Windows::Forms::FormBorderStyle::None;
    			this->Name = S"Form1";
    			this->Text = S"Form1";
    	this->WindowState = System::Windows::Forms::FormWindowState::Maximized;
    this->KeyPress += new System::Windows::Forms::KeyPressEventHandler(this, Form1_KeyPress);
    			this->Load += new System::EventHandler(this, Form1_Load);
    	private: System::Void Form1_Load(System::Object *  sender, System::EventArgs *  e)
    private: System::Void Form1_KeyPress(System::Object *  sender, 
    		System::Windows::Forms::KeyPressEventArgs *  e)
    				  if( e->KeyChar == Keys::Escape )
    private: System::Void timer1_Tick(System::Object *  sender, System::EventArgs *  e)
    		 // Get the graphics object of this form
    		 Graphics *graph = Graphics::FromHwnd(this->Handle);
    		 // These variables are declared static because they will keep changing
    		 // The X origin
    		 static int x = 0;
    		 // The Y origin
    		 static int y = 0;
    		 // This will check whether the origin is moving right or left
    		 static bool IsMovingRight;
    		 // This will check whether the origin is moving down or up
    		 static bool IsMovingDown;
    		 // If the status of the origin indicates that it is moving right,
    		 // then increase the horizontal axis
    		 if( IsMovingRight == true )
    		 else // If it's moving left, then decrease the horizontal movement
    		 // If the status of the origin indicates that it is moving down,
    		 // then increase the vertical axis
    		 if( IsMovingDown == true )
    		 else // Other wise, decrease it
    		 // Collision: if the right side of the circle hits the right side of the screen,
    		 // then set the horizontal moving status to "Right", which will be used
    		 // by the above code
    		 if( (x+40) > this->ClientSize.Width )
    			 IsMovingRight = false;
    		 if( x < 0 )
    			 IsMovingRight = true;;
    		 if( (y+40) > this->ClientSize.Height )
    			 IsMovingDown = false;
    		 if( y < 0 )
    			 IsMovingDown = true;
    		 // Before doing what we want, erase the screen
    		 // Draw the new axis
    		 graph->DrawLine(Pens::Aqua, x+20, 0, x+20, this->ClientSize.Height);
    		 graph->DrawLine(Pens::Aqua, 0, y+20, ClientSize.Width, y+20);
    		 // Draw the circle
    		 graph->DrawEllipse(Pens::Fuchsia, x, y, 40, 40);
    		 // Restart over
  8. Execute the application

Home Copyright © 2004-2005 FunctionX, Inc.