Масштабируйте и сохраняйте форму по центру указателя мыши.C#

Место общения программистов C#
Ответить
Anonymous
 Масштабируйте и сохраняйте форму по центру указателя мыши.

Сообщение Anonymous »

Я пытаюсь реализовать функцию масштабирования для приложения, которое рисует фигуры на экране. Эти фигуры создаются в миллиметрах, преобразованных в пиксели, в зависимости от значения dpi.
Рисование выполняется в PictureBox, который размещается на панели, для которой включена истинная автопрокрутка.
Каждое масштабирование увеличивает размер PictureBox по горизонтали. и по вертикали.
Когда я увеличиваю масштаб с помощью прокрутки колеса мыши, вертикальная полоса прокрутки также перемещается, в то время как горизонтальная полоса прокрутки остается неизменной при прокрутке колеса.
По этой причине фигура остается в правильном положении на экран горизонтально, но вертикально он перемещается вниз шаг за шагом, прокрутка за прокруткой.
Поэтому мне нужна функция, которая компенсирует это движение.
Мой код выглядит примерно так:
private int deltaScroll = 0;
private float previousZoom;
private void viewport_MouseWheel(object sender, MouseEventArgs e)
{
mousePoint = viewport.PointToClient(Cursor.Position);

deltaScroll += e.Delta / 120;
if (e.Delta > 0)
{
ZoomIn();
}
else if (e.Delta < 0)
{
ZoomOut();
}
}

private void ZoomIn()
{
if (zoomFactor < 20.0f) // Prevent zooming in too much
{
previousZoom = zoomFactor; // Store the old zoom factor
zoomFactor += 0.2f;
ApplyZoom();

// Calculate and apply scroll offsets
CompensateScroll(previousZoom, zoomFactor);
}
}

private void ZoomOut()
{
if (zoomFactor > 0.21f) // Prevent zooming out too much
{
previousZoom = zoomFactor; // Store the old zoom factor
zoomFactor -= 0.2f;
ApplyZoom();

// Calculate and apply scroll offsets
CompensateScroll(previousZoom, zoomFactor);
}
}

private void CompensateScroll(float previousZoom, float newZoom)
{
int mouseX = viewport.HorizontalScroll.Value + mousePoint.X;
int mouseY = viewport.VerticalScroll.Value + mousePoint.Y;

// Calculate scaling factor
float scaleFactor = newZoom / previousZoom;

// Calculate new scroll deltas, applying the wheel delta to vertical scroll compensation
int deltaX = (int)((mouseX * scaleFactor) - mouseX);
int deltaY = (int)((mouseY * scaleFactor) - mouseY);

// Clamp new scroll values to stay within bounds
int newScrollX = MathExtensions.Clamp(viewport.HorizontalScroll.Value + deltaX, viewport.HorizontalScroll.Minimum, viewport.HorizontalScroll.Maximum);
int newScrollY = MathExtensions.Clamp(viewport.VerticalScroll.Value + deltaY, viewport.VerticalScroll.Minimum, viewport.VerticalScroll.Maximum);

// Apply adjusted scroll positions
viewport.AutoScrollPosition = new Point(newScrollX, newScrollY);
}

private void ApplyZoom()
{
foreach (var shape in shapes)
{
shape.ZoomFactor = zoomFactor;
}

double percentage = 100.0 * zoomFactor;
toolStripLabel2.Text = percentage.ToString("00") + "%";

SetPictureBoxSize(); // Set zoomed pictureBox size (width*zoomFactor, height*zoomFactor)
pictureBox1.Invalidate(); // Refresh
}

Похоже, следующий код работает очень близко к тому, что я хочу:
private int preZoomVerticalScroll;
private void viewport_MouseWheel(object sender, MouseEventArgs e)
{
mousePoint = viewport.PointToClient(Cursor.Position);
preZoomVerticalScroll = (int)(mousePoint.Y * (zoomFactor - 1));

if (ModifierKeys == Keys.Control)
{
if (e.Delta > 0)
{
ZoomIn();
}
else if (e.Delta < 0)
{
ZoomOut();
}
}
}

float previousZoom;
private void ZoomIn()
{
if (zoomFactor < 20.0f) // Prevent zooming in too much
{
previousZoom = zoomFactor; // Store the old zoom factor
zoomFactor *= 1.2f;
ApplyZoom();
// Calculate and apply scroll offsets
CompensateScroll(previousZoom, zoomFactor);
}
}

private void ZoomOut()
{
if (zoomFactor > 0.21f) // Prevent zooming out too much
{
previousZoom = zoomFactor; // Store the old zoom factor
zoomFactor /= 1.2f;
ApplyZoom();

// Calculate and apply scroll offsets
CompensateScroll(previousZoom, zoomFactor);
}
}

private void CompensateScroll(float previousZoom, float newZoom)
{
// Get the current scroll position (both X and Y)
int currentScrollX = viewport.HorizontalScroll.Value;
int currentScrollY = preZoomVerticalScroll;

// Get the mouse position relative to the viewport, including current scroll offsets
int mouseX = mousePoint.X + currentScrollX;
int mouseY = mousePoint.Y + currentScrollY;

// Calculate scale factors for X and Y axes based on zoom
float scaleFactor = newZoom / previousZoom;

// Calculate the deltas for both X and Y axes (how much the content should move after zoom)
int deltaX = (int)(mouseX * scaleFactor) - mouseX;
int deltaY = (int)(mouseY * scaleFactor) - mouseY;

// Adjust the scroll position based on the deltas, ensuring they stay within bounds
int newScrollX = MathExtensions.Clamp(currentScrollX + deltaX, viewport.HorizontalScroll.Minimum, viewport.HorizontalScroll.Maximum);
int newScrollY = MathExtensions.Clamp(currentScrollY + deltaY, viewport.VerticalScroll.Minimum, viewport.VerticalScroll.Maximum);
// Set the new scroll position for the viewport
viewport.AutoScrollPosition = new Point(newScrollX, newScrollY);

}

private void ApplyZoom()
{
foreach (var shape in shapes)
{
shape.ZoomFactor = zoomFactor;
}

double percentage = 100.0 * zoomFactor;
toolStripLabel2.Text = percentage.ToString("00") + "%";

SetPictureBoxSize(); // Set zoomed pictureBox size (width*zoomFactor, height*zoomFactor)

}


Подробнее здесь: https://stackoverflow.com/questions/792 ... se-pointer
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «C#»