Масштабирование окна рисования владельцем вокруг точки мыши - PullRequest
0 голосов
/ 24 апреля 2020

У меня есть рисованный владельцем PictureBox (picGrid), и я хочу, чтобы пользователь мог изменять масштаб с помощью колесика мыши. Эта часть проста. Но я хочу автоматически прокрутить так, чтобы логическая точка под мышью была все еще логическая точка под мышью после увеличения.

Вот что у меня есть до сих пор. Это почти работает, но просто не правильно. XScroll и YScroll являются моими позициями прокрутки и будут использоваться для установки полосы прокрутки (в дополнение к смещению изображения).

/// <summary>
/// Sets the current zoom percent.
/// </summary>
/// <param name="percent">The percent that the zoom should be set (100 == 1:1 scaling).</param>
/// <param name="x">X coordinate of the mouse in pixels.</param>
/// <param name="y">Y coordinate of the mouse in pixels.</param>
public void SetZoom(int percent, int x, int y)
{
    // If needed, this method translates mouse coordinate to logical coordinates
    // but doesn't appear to be needed here.
    //TranslateCoordinates(ref x, ref y);

    // Calculate new scale (1.0f == 1:1 scaling)
    float newDrawScale = (float)percent / 100;

    // Enforce zoom limits
    if (newDrawScale < 0.1f)
        newDrawScale = 0.1f;
    else if (newDrawScale > 1500.0f)
        newDrawScale = 1500.0f;

    // Set new zoom (if it's changed)
    if (newDrawScale != DrawScale)
    {
        DrawScale = newDrawScale;

        // *** Here's the part that isn't right ***

        // Scroll to keep same logical point under mouse
        float delta = (DrawScale - 1f);
        XScroll = (x * delta);
        YScroll = (y * delta);

        // Reflect change in scrollbars
        UpdateScrollbars();

        // Redraw content
        picGrid.Invalidate();
    }
}

Как рассчитать новую позицию прокрутки, чтобы она соответствовала Логическая точка остается под указателем мыши после увеличения?

1 Ответ

1 голос
/ 25 апреля 2020

Мне удалось пройти через это. Это то, что я придумал. (Обратите внимание, что XOffset и YOffset в экранных координатах соответствуют полосам прокрутки.)

public void SetZoom(int percent, int x, int y)
{
    // Calculate new scale (100% == 1:1)
    float newDrawScale = (float)percent / 100;

    // See if scale has changed
    if (newDrawScale != DrawScale)
    {
        // Update scale and adjust offsets
        ScreenToWorld(x, y, out float logicalX, out float logicalY);
        DrawScale = newDrawScale;
        WorldToScreen(logicalX, logicalY, out float screenX, out float screenY);
        XOffset += (screenX - x);
        YOffset += (screenY - y);

        // Update scrollbars and redraw
        UpdateScrollbars();
        picGrid.Invalidate();
    }
}

private void WorldToScreen(float srcX, float srcY, out float destX, out float destY)
{
    destX = (srcX * DrawScale) - XOffset;
    destY = (srcY * DrawScale) - YOffset;
}

private void ScreenToWorld(float srcX, float srcY, out float destX, out float destY)
{
    destX = (srcX + XOffset) / DrawScale;
    destY = (srcY + YOffset) / DrawScale;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...