Сам нашел решение.
Расписал аккуратно матрицы, вручную перемножил, получил готовую матрицу масштабирования относительно курсора, подставил в программу и все работает.
Стал смотреть в чем дело у меня в программе.
Оказалось: я неправильно понимал порядок перемножения матриц при применении метода Multiply(Matrix). К счастью у Multiply есть перегруженная версия с произвольным выбором порядка операндов.
Должно быть так:
public class DrawingAreaControl : UserControl
{
public DrawingAreaControl()
{
DoubleBuffered = true;
transform = new Matrix();
}
public Matrix transform { get; set; }
protected override void OnPaint(PaintEventArgs e)
{
e.Graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
e.Graphics.Transform = transform;
base.OnPaint(e);
}
const float SCALE_MUL = 1.05f;
protected override void OnMouseWheel(MouseEventArgs e)
{
base.OnMouseWheel(e);
var matrixOrder = MatrixOrder.Append;
var K = e.Delta > 0 ? SCALE_MUL : 1 / SCALE_MUL;
transform.Multiply(new Matrix(1, 0, 0, 1, -e.Location.X, -e.Location.Y), matrixOrder);
transform.Multiply(new Matrix(K, 0, 0, K, 0, 0), matrixOrder);
transform.Multiply(new Matrix(1, 0, 0, 1, e.Location.X, e.Location.Y), matrixOrder);
Invalidate();
}
}
Возможно, тот мой вариант с вручную подготовленной матрицей несколько эффективнее в вычислительном плане, но представленный вариант - читабельнее.