Hi im writing a win32 application in C++ at the moment and I have really a problem to get zooming into the content of my window. Here is the pseudo code I started with to get zooming done:
// point One
int XPointOne = -200;
int YPointTwo = 0;
// point Two
int XPointTwo = 200;
int YPointTwo = 0;
// Draw point function.
DrawPoint(XCoordinate * ScalingFactor, YCoordinate * ScalingFactor) {
....
}
My coordinate system is set up to have its origin in the center of the window. I would like to zoom when the mouse wheel is used. The problem with the solution above is that zooming always happens from the center of the window. This kinda looks ugly when your mouse isnt at the center of the window. I would like to zoom into the region where the mouse is but i can not find a suitable algorithm to caclulate the offsets in x and y direction. For example if the mouse has the coordinates (-200, 0) point one should have the coordinates (-200, 0) and point two the coordinates (600, 0) with a scaling factor of two. I already tried alot of things but didnt get it to work especially when the mouse moves to other locations between zooming everything gets messed up. Anyone knows how to solve this problem?
Here is some example code of my appliaciton. The first snippet is my callback function for handling the WM_MOUSEWHEEL message.
VOID OnMouseWheel(WPARAM const& WParam, LPARAM const& LParam) {
if(GET_WHEEL_DELTA_WPARAM(WParam) > 0)
{
// Zoom in
Draw.ScaleFactor += 0.1;
}
else
{
// Zoom out
}
}
Draw is simply a class that wraps the GDI functions. It has a scaling factor member. The snippet below is the DrawCircle member function of my Draw object using the scale factor to present the circle correctly on the screen.
VOID DrawCircle(DOUBLE const& XCoordinate, DOUBLE const& YCoordinate, DOUBLE const& Radius, COLORREF const& Color) {
HBRUSH Brush = CreateSolidBrush(Color);
HBRUSH OldBrush = (HBRUSH)SelectObject(this->MemoryDC, Brush);
Ellipse(this->MemoryDC, (INT) ((XCoordinate - Radius) * this->ScaleFactor),
-(INT)((YCoordinate + Radius) * this->ScaleFactor),
(INT)((XCoordinate + Radius) * this->ScaleFactor),
-(INT)((YCoordinate - Radius) * this->ScaleFactor));
SelectObject(this->MemoryDC, OldBrush);
DeleteObject(Brush);
}
As you can see my DrawCircle function does not take the mouse position into account when applying the current scale factor.
EDIT
Ok i got closer to the solution here is the updated version of my mouse callback function.
VOID OnMouseWheel(WPARAM const& WParam, LPARAM const& LParam) {
// Get Mouse position in real coordinates and not window coordinates.
INT XOffset = (Window.GetClientWidth() / -2) + XMousePos;
INT YOffset = (Window.GetClientHeight() / 2) - YMousePos;
if(GET_WHEEL_DELTA_WPARAM(WParam) > 0)
{
Draw.ScaleFactor += 0.1;
Draw.XOffsetScale = -XOffset * (Draw.ScaleFactor - 1.0);
Draw.YOffsetScale = YOffset * (Draw.ScaleFactor - 1.0);
}
else
{
// ...
}
}
And here is the function that draws the circle.
VOID DrawCircle(DOUBLE const& XCoordinate, DOUBLE const& YCoordinate, DOUBLE const& Radius, COLORREF const& Color) {
HBRUSH Brush = CreateSolidBrush(Color);
HBRUSH OldBrush = (HBRUSH)SelectObject(this->MemoryDC, Brush);
Ellipse(this->MemoryDC, (INT) ((XCoordinate - Radius) * this->ScaleFactor + XOffsetScale) ,
-(INT)((YCoordinate + Radius) * this->ScaleFactor - YOffsetScale),
(INT)((XCoordinate + Radius) * this->ScaleFactor + XOffsetScale),
-(INT)((YCoordinate - Radius) * this->ScaleFactor - YOffsetScale));
SelectObject(this->MemoryDC, OldBrush);
DeleteObject(Brush);
}
This does work as long as i keep the mouse at the same position but when i move to another position it doesnt zoom as expected once after that it zooms correctly again. Maybe this helps a bit.
Thanks in advance!
Solved
Ok, I solved my Problem now. I just moved the origin of my coordinate system based on the mouse position multiplied with the scaling factor. Thank for your answers.