Windows Forms Paint effect (C++)
Andris Jansons
Posted on February 16, 2018
Simulating a looping function while mouse is pressed
Microsoft paint kind of style:
What this function does is - it makes your function run every 10ms
for example while working with Windows forms. Since such an event does not directly exist within the Windows Forms, we can achieve the same result using a few different ones together.
There are 2 scenarios:
- Either draw on the grid clicking one pixel at a time with the regular
MouseEventHandler(this, &project::panel1_MouseClick);
(I know it does not seem as bad on such huge pixels); - Or, click and drag for as long as you wish to achieve continuous line (Let me show you how).
For this we are going to need 3 events, although the last one is optional:
this->panel1->MouseDown += gcnew System::Windows::Forms::MouseEventHandler(this, &frmAdventrureMap::panel1_MouseDown);
this->panel1->MouseUp += gcnew System::Windows::Forms::MouseEventHandler(this, &frmAdventrureMap::panel1_MouseUp);
this->panel1->MouseMove += gcnew System::Windows::Forms::MouseEventHandler(this, &frmAdventrureMap::panel1_MouseMove);
And a timer:
private: System::Windows::Forms::Timer^ timerMouseDrag;
this->timerMouseDrag = (gcnew System::Windows::Forms::Timer(this->components));
//Let's add a tick event
this->timerMouseDrag->Tick += gcnew System::EventHandler(this, &frmAdventrureMap::timerMouseDrag_Tick);
//And specify the interval
this->timerMouseDrag->Interval = 10;
To anyone just using Visual Studio Design View, this can not become any easier:
Now to the fun part
Some of you may already see where I am going with this, because what's left is just 2 lines of code:
private: System::Void panel1_MouseDown(System::Object^ sender, System::Windows::Forms::MouseEventArgs^ e)
{
//Mouse pressed - Start the timer
timerMouseDrag->Start();
}
private: System::Void panel1_MouseUp(System::Object^ sender, System::Windows::Forms::MouseEventArgs^ e)
{
//Mouse released - Stop the timer
timerMouseDrag->Stop();
}
And finally:
private: System::Void timerMouseDrag_Tick(System::Object^ sender, System::EventArgs^ e)
{
//Your code here (This is where I make the drawing happen)
}
That is it! "Simplicity is the ultimate sophistication."(Leonardo da Vinci)
But let's take this a step further
Remember the mouse move event we initialized earlier?
We use that one to pass our mouse position to our timer event or any other function we might call.
Simply creating a private attribute of MouseEventArgs^
or just assigning mouse x and y position:
private:
System::Windows::Forms::MouseEventArgs^ mouse;
//or
int x, y;
And updating them each time MouseMove
happens:
private: System::Void panel1_MouseMove(System::Object^ sender, System::Windows::Forms::MouseEventArgs^ e)
{
mouse = e;
//Or
x = e->X;
y = e->Y;
}
To anyone thinking the same could be done without the timer but inside the MouseMove
event - You're totally right, but what you are missing is the simple option to choose your preferred interval, furthermore MouseMove
happens all the time, while our timer is working only when mouse is pressed.
In the end of the day, each and every project has its own methods it works best with.
Hope this helped someone or raised some new ideas, and if so, feel free to comment below.
Posted on February 16, 2018
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.