Các Phương Pháp Phát Hiện Sự Cố Touch Trong Ứng Dụng WPF Khi Khởi Động

Trong quá trình phát triển dự án OPS, chúng tôi phát hiện thấy vấn đề các ứng dụng tự khởi động bằng WPF đôi khi không phản hồi với thao tác touch khi thực hiện chuyển đổi hệ thống, bật/tắt máy hoặc khởi động lại. Các ứng dụng gặp sự cố này đều là ứng dụng toàn màn hình. Khi sử dụng công cụ Snoop để kiểm tra, không có sự kiện Touch hay Stylus nào được kích hoạt, nhưng các sự kiện chuột lại hoạt động bình thường. Các ứng dụng khác trên hệ thống vẫn sử dụng touch được tốt. Đây là một trong những tình huống phổ biến gặp phải khi làm việc với ứng dụng WPF.

Dưới đây là các phương pháp kiểm tra trạng thái touch khi khởi động ứng dụng WPF

1. Phát hiện hệ thống có thiết bị touch hay không

  [DllImport("user32.dll")]
  private static extern int GetSystemMetrics(int metricIndex);

public static bool KiemTraThietBiTouchHeThong() => GetSystemMetrics(94) > 0 || GetSystemMetrics(95) > 0 || GetSystemMetrics(86) > 0;

2. Kiểm tra WPF đã tải thiết bị touch chưa

 public static bool KiemTraTouchWPF() => Tablet.TabletDevices.Count > 0;

3. Phát hiện bộ chuyển đổi touch (đòi hỏi tham chiếu WinRT, qua NuGet: Microsoft.Windows.SDK.Contract)

 private static bool HeThongDuocPhepTouch()
 {
     var tinhNangTouch = new TouchCapabilities();
     var coTouch = tinhNangTouch.TouchPresent > 0;
     return coTouch;
 }

4. Kiểm tra sự tồn tại kích thước của thiết bị touch

  public static bool CoKichThuocThietBiTouch()
 {
    bool ketQua = false;
    foreach (TabletDevice thietBi in (IEnumerable) Tablet.TabletDevices)
    {
      PropertyInfo thuocTinh = thietBi.GetType().GetProperty("TabletDeviceImpl", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.GetProperty);
      doiTuong = (object) thuocTinh == null ? (object) thietBi : thuocTinh.GetValue((object) thietBi);
      if (doiTuong.GetType().GetProperty("TabletSize", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.GetProperty)?.GetValue(doiTuong, (object[]) null) is Size kichThuoc && thietBi.StylusDevices.Count > 0 && kichThuoc.Width > 0)
        ketQua = true;
      if (ketQua)
        break;
    }
    return ketQua;
  }

5. Lắng nghe ngoại lệ liên quan đến bút cảm ứng

 
   AppDomain.CurrentDomain.FirstChanceException += XuLyNgoaiLe;

private void XuLyNgoaiLe(object nguon, FirstChanceExceptionEventArgs e)
 {
     AppDomain.CurrentDomain.FirstChanceException -= XuLyNgoaiLe;
     try
     {
         if (e.Exception.StackTrace.Contains("Penimc.IPimcManager2.GetTablet"))
         {
             //xử lý sự cố
         }
         else if (e.Exception.StackTrace.Contains("Windows.Input.StylusWisp.WispLogic.RegisterStylusDeviceCore"))
         {
             //xử lý sự cố
         }
     }
     finally
     {
         AppDomain.CurrentDomain.FirstChanceException -= XuLyNgoaiLe;
         AppDomain.CurrentDomain.FirstChanceException += XuLyNgoaiLe;
     }
 }

Dựa trên kinh nghiệm trước đây, chúng tôi đã kết hợp phương pháp 1 và 2, nhưng vẫn phát hiện có sự cố touch. Sau đó, chúng tôi thêm phương pháp 3 và 4 kèm theo ghi log, và nhận thấy khi hệ thống có thiết bị touch và ứng dụng WPF phát hiện có thiết bị touch, kết quả từ phương pháp 3 và 4 lại cho thấy có sự bất thường.

Kết luận:

Vì các tình huống touch失效 trong ứng dụng WPF rất đa dạng và khó hiểu, hiện tại các phương pháp trên chỉ có thể giúp phát hiện và khắc phục bằng cách khởi động lại ứng dụng khi gặp sự cố.

Thẻ: WPF touch OPS WinRT digitizer

Đăng vào ngày 26 tháng 5 lúc 06:15