我的問題有效地歸結為準確的滑鼠移動檢測。
我需要創建自己的 InkCanvas 實作,并且大部分都成功了,除了準確地繪制筆觸。
void OnMouseMove(object sneder, MouseEventArgs e)
{
var position = e.GetPosition(this);
if (!Rect.Contains(position))
return;
var ratio = new Point(Width / PixelDisplay.Size.X, Height / PixelDisplay.Size.Y);
var intPosition = new IntVector(Math2.FloorToInt(position.X / ratio.X), Math2.FloorToInt(position.Y / ratio.Y));
DrawBrush.Draw(intPosition, PixelDisplay);
UpdateStroke(intPosition); // calls CaptureMouse
}
這行得通。位圖 (PixelDisplay) 已更新,一切正常。但是,任何型別的快速滑鼠移動都會導致繪圖中出現較大的跳躍。我已將問題范圍縮小到e.GetPosition(this),這會阻止事件足夠長的時間以致不準確。
有這個問題早已超越復興,它的答案不清楚或根本沒有明顯的區別。經過更多測驗,所述解決方案和類似想法特別失敗,因為e.GetPosition.
我知道 InkCanvas 在查看源代碼后使用了類似的方法;檢測設備,如果是滑鼠,獲取其位置并捕獲。我認為沒有理由讓相同的程序在這里不一樣。
uj5u.com熱心網友回復:
我最終能夠部分解決這個問題。
var position = e.GetPosition(this);
if (!Rect.Contains(position))
return;
if (DrawBrush == null)
return;
var ratio = new Point(Width / PixelDisplay.Size.X, Height / PixelDisplay.Size.Y);
var intPosition = new IntVector(Math2.FloorToInt(position.X / ratio.X), Math2.FloorToInt(position.Y / ratio.Y));
// Calculate pixel coordinates based on the control height
var lastPoint = CurrentStroke?.Points.LastOrDefault(new IntVector(-1, -1));
// Uses System.Linq to grab the last stroke, if it exists
PixelDisplay.Lock();
// My special locking mechanism, effectively wraps Bitmap.Lock
if (lastPoint != new IntVector(-1, -1)) // Determine if we're in the middle of a stroke
{
var alphaAdd = 1d / new IntVector(intPosition.X - lastPoint.Value.X, intPosition.Y - lastPoint.Value.Y).Magnitude;
// For some interpolation, calculate 1 / distance (magnitude) of the two points.
// Magnitude formula: Math.Sqrt(Math.Pow(X, 2) Math.Pow(Y, 2));
var alpha = 0d;
var xDiff = intPosition.X - lastPoint.Value.X;
var yDiff = intPosition.Y - lastPoint.Value.Y;
while (alpha < 1d)
{
alpha = alphaAdd;
var adjusted = new IntVector(
Math2.FloorToInt((position.X (xDiff * alpha)) / ratio.X),
Math2.FloorToInt((position.Y (yDiff * alpha)) / ratio.Y));
// Inch our way towards the current intPosition
DrawBrush.Draw(adjusted, PixelDisplay); // Draw to the bitmap
UpdateStroke(intPosition);
}
}
DrawBrush.Draw(intPosition, PixelDisplay); // Draw the original point
UpdateStroke(intPosition);
PixelDisplay.Unlock();
此實作在最后一點和當前點之間進行插值以填補任何空白。例如,當使用非常小的畫筆尺寸時,它并不完美,但仍然是一種解決方案。
一些備注
IntVector是我懶惰地實作的 Vector2,只是使用整數代替。
Math2是一個助手類。FloorToInt簡稱(int)MathF.Round(...))
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/471393.html
標籤:wpf
