WPF 프로그램의 ScrollViewer에서 Windows PTP(Precision Touch-Pad) Driver를 사용하는 터치패드로 스크롤시 스크롤이 너무 빨라지는 오류 수정법

결론부터 말하면, WPF의 버그이다. 같은 SDK를 사용하는 Win Forms에서는 나타나지 않는 현상이다.

문제가 되는 현상은 WPF 프로그램ScrollViewer를 사용하는 UI Element에서 PTP 드라이버를 사용하는 터치패드(요즘 나오는 랩탑에서는 많이 사용한다)로 스크롤하면 스크롤 속도가 말도 안되게 빨라지는 현상이다. 거의 스크롤 거리에 비해 10~20배는 빠르다.

이를 수정하려면 ScrollViewerPreviewMouseWheel 를 설정해야한다.

원리는 간단하다. PreviewMouseWheel에서 EventArgsHandledtrue로 설정하면스크롤이 되지 않는다. 이 때 EventArgsDelta를 받아와 일정 threshold를 넘지 않게 스크롤 시켜주면 된다.

아마도 오류 자체는 Delta값이 매우 커지는 것과 관련된 것같다. PreviewMouseWheel 이벤트가 과도하게 불리는 것은 아니라는 것이다.

또한, 경험상 threshold 값은 int값 48이 가장 적당했다.

PreviewMouseWheel 이벤트 메소드의 예시 코드는 아래와 같다.

public static void HandleScroll(object sender, MouseWheelEventArgs e)
{
    int threshold = 48;
    ScrollViewer scrollViewer = (ScrollViewer)sender;
    double target = scrollViewer.VerticalOffset - Math.Min(Math.Max(e.Delta, -threshold), threshold);
    scrollViewer.ScrollToVerticalOffset(target);
    e.Handled = true;
}

C#에서 Private Key를 이용한 SFTP 접속하기

C#에서 Private Key(.pem이나 .ppk)파일을 이용하여 SFTP 연결을 성립하기 위한 방법을 공유합니다.

일단, ppk 파일을 사용한다는 가정 하에 진행하도록 하겠습니다. (pem 파일을 ppk 파일로 변환하는법은 여기를 클릭해주세요)

  1. C# 프로젝트의 nuget 검색을 통해 WINSCP 패키지를 설치해주세요.
  2. 이후, 아래 예제코드를 참고하여 프로그램을 작성하면 됩니다

예제 코드 :

using WinSCP;

namespace SAMPLE
{
	public partial class MainWindow : Window
	{
		private Session session;
		public MainWindow()
		{
			InitializeComponent();
			//HostName, UserName SshPrivateKeyPath 변경할것
			SessionOptions sessionOptions = new SessionOptions
			{
				Protocol = Protocol.Sftp,
				HostName = "HOST",
				UserName = "USERNAME",
				SshPrivateKeyPath = "PATH_TO_PPK_FILE",
				GiveUpSecurityAndAcceptAnySshHostKey = true
			};
			session = new Session();
			session.Open(sessionOptions);
			TransferOptions transferOptions = new TransferOptions();
			//아래 두 옵션은 입맞에 맞게 수정해주세요.
			transferOptions.TransferMode = TransferMode.Automatic;
			transferOptions.OverwriteMode = OverwriteMode.Overwrite;

			//GetFiles 또는 PutFiles 사용
			TransferOperationResult transferResult = session.GetFiles("호스트 파일 경로", "로컬 파일 경로");
			if (transferResult.IsSuccess)
			{
				MessageBox.Show("다운로드 성공");
			}
			else
			{
				MessageBox.Show("다운로드 실패");
			}
		}
	}
}