2012-08-10 64 views
3

我在WinForms中使用Magnification API在網上發現了library,它的工作很棒。我試圖讓它與WPF一起工作,但沒有運氣,沒有例外或錯誤,一切似乎都沒問題。我開始認爲它不適合使用WPF。使用從WinForms到WPF的Magnification API

的WinForms代碼:

public class Magnifier : IDisposable 
{ 
    private Form form; 
    private IntPtr hwndMag; 
    private float magnification; 
    private bool initialized; 
    private RECT magWindowRect = new RECT(); 
    private System.Windows.Forms.Timer timer; 

    public Magnifier(Form form) 
    { 
     if (form == null) 
      throw new ArgumentNullException("form"); 

     magnification = 2.0f; 
     this.form = form; 
     this.form.Resize += new EventHandler(form_Resize); 
     this.form.FormClosing += new FormClosingEventHandler(form_FormClosing); 

     timer = new Timer(); 
     timer.Tick += new EventHandler(timer_Tick); 

     initialized = NativeMethods.MagInitialize(); 
     if (initialized) 
     { 
      SetupMagnifier(); 
      timer.Interval = NativeMethods.USER_TIMER_MINIMUM; 
      timer.Enabled = true; 
     } 
    } 

    void form_FormClosing(object sender, FormClosingEventArgs e) 
    { 
     timer.Enabled = false; 
    } 

    void timer_Tick(object sender, EventArgs e) 
    { 
     UpdateMaginifier(); 
    } 

    void form_Resize(object sender, EventArgs e) 
    { 
     ResizeMagnifier(); 
    } 

    ~Magnifier() 
    { 
     Dispose(false); 
    } 

    protected virtual void ResizeMagnifier() 
    { 
     if (initialized && (hwndMag != IntPtr.Zero)) 
     { 
      NativeMethods.GetClientRect(form.Handle, ref magWindowRect); 
      // Resize the control to fill the window. 
      NativeMethods.SetWindowPos(hwndMag, IntPtr.Zero, 
       magWindowRect.left, magWindowRect.top, magWindowRect.right, magWindowRect.bottom, 0); 
     } 
    } 

    public virtual void UpdateMaginifier() 
    { 
     if ((!initialized) || (hwndMag == IntPtr.Zero)) 
      return; 

     POINT mousePoint = new POINT(); 
     RECT sourceRect = new RECT(); 

     NativeMethods.GetCursorPos(ref mousePoint); 

     int width = (int)((magWindowRect.right - magWindowRect.left)/magnification); 
     int height = (int)((magWindowRect.bottom - magWindowRect.top)/magnification); 

     sourceRect.left = mousePoint.x - width/2; 
     sourceRect.top = mousePoint.y - height/2; 


     // Don't scroll outside desktop area. 
     if (sourceRect.left < 0) 
     { 
      sourceRect.left = 0; 
     } 
     if (sourceRect.left > NativeMethods.GetSystemMetrics(NativeMethods.SM_CXSCREEN) - width) 
     { 
      sourceRect.left = NativeMethods.GetSystemMetrics(NativeMethods.SM_CXSCREEN) - width; 
     } 
     sourceRect.right = sourceRect.left + width; 

     if (sourceRect.top < 0) 
     { 
      sourceRect.top = 0; 
     } 
     if (sourceRect.top > NativeMethods.GetSystemMetrics(NativeMethods.SM_CYSCREEN) - height) 
     { 
      sourceRect.top = NativeMethods.GetSystemMetrics(NativeMethods.SM_CYSCREEN) - height; 
     } 
     sourceRect.bottom = sourceRect.top + height; 

     if (this.form == null) 
     { 
      timer.Enabled = false; 
      return; 
     } 

     if (this.form.IsDisposed) 
     { 
      timer.Enabled = false; 
      return; 
     } 

     // Set the source rectangle for the magnifier control. 
     NativeMethods.MagSetWindowSource(hwndMag, sourceRect); 

     // Reclaim topmost status, to prevent unmagnified menus from remaining in view. 
     NativeMethods.SetWindowPos(form.Handle, NativeMethods.HWND_TOPMOST, 0, 0, 0, 0, 
      (int)SetWindowPosFlags.SWP_NOACTIVATE | (int)SetWindowPosFlags.SWP_NOMOVE | (int)SetWindowPosFlags.SWP_NOSIZE); 

     // Force redraw. 
     NativeMethods.InvalidateRect(hwndMag, IntPtr.Zero, true); 
    } 

    public float Magnification 
    { 
     get { return magnification; } 
     set 
     { 
      if (magnification != value) 
      { 
       magnification = value; 
       // Set the magnification factor. 
       Transformation matrix = new Transformation(magnification); 
       NativeMethods.MagSetWindowTransform(hwndMag, ref matrix); 
      } 
     } 
    } 

    protected void SetupMagnifier() 
    { 
     if (!initialized) 
      return; 

     IntPtr hInst; 

     hInst = NativeMethods.GetModuleHandle(null); 

     // Make the window opaque. 
     form.AllowTransparency = true; 
     form.TransparencyKey = Color.Empty; 
     form.Opacity = 255; 

     // Create a magnifier control that fills the client area. 
     NativeMethods.GetClientRect(form.Handle, ref magWindowRect); 
     hwndMag = NativeMethods.CreateWindow((int)ExtendedWindowStyles.WS_EX_CLIENTEDGE, NativeMethods.WC_MAGNIFIER, 
      "MagnifierWindow", (int)WindowStyles.WS_CHILD | (int)MagnifierStyle.MS_SHOWMAGNIFIEDCURSOR | 
      (int)WindowStyles.WS_VISIBLE, 
      magWindowRect.left, magWindowRect.top, magWindowRect.right, magWindowRect.bottom, form.Handle, IntPtr.Zero, hInst, IntPtr.Zero); 

     if (hwndMag == IntPtr.Zero) 
     { 
      return; 
     } 

     // Set the magnification factor. 
     Transformation matrix = new Transformation(magnification); 
     NativeMethods.MagSetWindowTransform(hwndMag, ref matrix); 
    } 

    protected void RemoveMagnifier() 
    { 
     if (initialized) 
      NativeMethods.MagUninitialize(); 
    } 

    protected virtual void Dispose(bool disposing) 
    { 
     timer.Enabled = false; 
     if (disposing) 
      timer.Dispose(); 
     timer = null; 
     form.Resize -= form_Resize; 
     RemoveMagnifier(); 
    } 

    #region IDisposable Members 

    public void Dispose() 
    { 
     Dispose(true); 
     GC.SuppressFinalize(this); 
    } 

    #endregion 
} 

在WPF代碼我只是修改了Magnifer類:

public class Magnifier : IDisposable 
{ 
    private Window window; 
    private IntPtr hwnd; 
    private IntPtr hwndMag; 
    private float magnification; 
    private bool initialized; 
    private RECT magWindowRect = new RECT(); 
    private DispatcherTimer timer; 

    public Magnifier(Window window) 
    { 
     if (window == null) 
      throw new ArgumentNullException("form"); 

     hwnd = new WindowInteropHelper(window).Handle; 
     magnification = 2.0f; 
     this.window = window; 
     this.window.SizeChanged += form_Resize; 
     this.window.Closing += form_FormClosing; 

     timer = new DispatcherTimer(); 
     timer.Tick += timer_Tick; 

     initialized = NativeMethods.MagInitialize(); 
     if (initialized) 
     { 
      SetupMagnifier(); 
      timer.Interval = TimeSpan.FromMilliseconds(NativeMethods.USER_TIMER_MINIMUM); 
      timer.IsEnabled = true; 
     } 
    } 

    void form_FormClosing(object sender, CancelEventArgs e) 
    { 
     timer.IsEnabled = false; 
    } 

    void timer_Tick(object sender, EventArgs e) 
    { 
     UpdateMaginifier(); 
    } 

    void form_Resize(object sender, RoutedEventArgs e) 
    { 
     ResizeMagnifier(); 
    } 

    ~Magnifier() 
    { 
     Dispose(false); 
    } 

    protected virtual void ResizeMagnifier() 
    { 
     if (initialized && (hwndMag != IntPtr.Zero)) 
     { 
      NativeMethods.GetClientRect(hwnd, ref magWindowRect); 
      // Resize the control to fill the window. 
      NativeMethods.SetWindowPos(hwndMag, IntPtr.Zero, 
       magWindowRect.left, magWindowRect.top, magWindowRect.right, magWindowRect.bottom, 0); 
     } 
    } 

    public virtual void UpdateMaginifier() 
    { 
     if ((!initialized) || (hwndMag == IntPtr.Zero)) 
      return; 

     POINT mousePoint = new POINT(); 
     RECT sourceRect = new RECT(); 

     NativeMethods.GetCursorPos(ref mousePoint); 

     int width = (int)((magWindowRect.right - magWindowRect.left)/magnification); 
     int height = (int)((magWindowRect.bottom - magWindowRect.top)/magnification); 

     sourceRect.left = mousePoint.x - width/2; 
     sourceRect.top = mousePoint.y - height/2; 


     // Don't scroll outside desktop area. 
     if (sourceRect.left < 0) 
     { 
      sourceRect.left = 0; 
     } 
     if (sourceRect.left > NativeMethods.GetSystemMetrics(NativeMethods.SM_CXSCREEN) - width) 
     { 
      sourceRect.left = NativeMethods.GetSystemMetrics(NativeMethods.SM_CXSCREEN) - width; 
     } 
     sourceRect.right = sourceRect.left + width; 

     if (sourceRect.top < 0) 
     { 
      sourceRect.top = 0; 
     } 
     if (sourceRect.top > NativeMethods.GetSystemMetrics(NativeMethods.SM_CYSCREEN) - height) 
     { 
      sourceRect.top = NativeMethods.GetSystemMetrics(NativeMethods.SM_CYSCREEN) - height; 
     } 
     sourceRect.bottom = sourceRect.top + height; 

     if (this.window == null) 
     { 
      timer.IsEnabled = false; 
      return; 
     } 

     //if (this.window.IsDisposed) 
     //{ 
     // timer.IsEnabled = false; 
     // return; 
     //} 

     // Set the source rectangle for the magnifier control. 
     NativeMethods.MagSetWindowSource(hwndMag, sourceRect); 

     // Reclaim topmost status, to prevent unmagnified menus from remaining in view. 
     NativeMethods.SetWindowPos(hwnd, NativeMethods.HWND_TOPMOST, 0, 0, 0, 0, 
      (int)SetWindowPosFlags.SWP_NOACTIVATE | (int)SetWindowPosFlags.SWP_NOMOVE | (int)SetWindowPosFlags.SWP_NOSIZE); 

     // Force redraw. 
     NativeMethods.InvalidateRect(hwndMag, IntPtr.Zero, true); 
    } 

    public float Magnification 
    { 
     get { return magnification; } 
     set 
     { 
      if (magnification != value) 
      { 
       magnification = value; 
       // Set the magnification factor. 
       Transformation matrix = new Transformation(magnification); 
       NativeMethods.MagSetWindowTransform(hwndMag, ref matrix); 
      } 
     } 
    } 

    protected void SetupMagnifier() 
    { 
     if (!initialized) 
      return; 

     IntPtr hInst; 

     hInst = NativeMethods.GetModuleHandle(null); 

     // Make the window opaque. 
     //form.AllowTransparency = true; (done in xaml) 
     //window.Background = Brushes.Transparent; (done in xaml) 
     //window.Opacity = 255; 

     // Create a magnifier control that fills the client area. 
     NativeMethods.GetClientRect(hwnd, ref magWindowRect); 
     hwndMag = NativeMethods.CreateWindow((int)ExtendedWindowStyles.WS_EX_CLIENTEDGE, NativeMethods.WC_MAGNIFIER, 
      "MagnifierWindow", (int)WindowStyles.WS_CHILD | (int)MagnifierStyle.MS_SHOWMAGNIFIEDCURSOR | 
      (int)WindowStyles.WS_VISIBLE, 
      magWindowRect.left, magWindowRect.top, magWindowRect.right, magWindowRect.bottom, hwnd, IntPtr.Zero, hInst, IntPtr.Zero); 

     if (hwndMag == IntPtr.Zero) 
     { 
      return; 
     } 

     // Set the magnification factor. 
     Transformation matrix = new Transformation(magnification); 
     NativeMethods.MagSetWindowTransform(hwndMag, ref matrix); 
    } 

    protected void RemoveMagnifier() 
    { 
     if (initialized) 
      NativeMethods.MagUninitialize(); 
    } 

    protected virtual void Dispose(bool disposing) 
    { 
     timer.IsEnabled = false; 
     //if (disposing) 
     // timer.Dispose(); 
     timer = null; 
     window.SizeChanged -= form_Resize; 
     RemoveMagnifier(); 
    } 

    #region IDisposable Members 

    public void Dispose() 
    { 
     Dispose(true); 
     GC.SuppressFinalize(this); 
    } 

    #endregion 
} 

XAML:

<Window x:Class="WpfApplication11.MagnifierWindow" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    Title="MagnifierWindow" Height="350" Width="525" AllowsTransparency="True" WindowStyle="None"> 

<Window.Background> 
    <SolidColorBrush /> 
</Window.Background> 

- 要使用I類只是在Fo中初始化它rm/Window的構造函數。

-Changes我在WPF做:

  • 增加了 「HWND」 領域,在放大鏡的構造函數初始化它。
  • 替換System.Windows.Forms.Timer與 System.Windows.Threading.DispatcherTimer。
  • 將form.Resize更改爲window.SizeChanged並將form.FormClosing更改爲 window.Closing。但這是不相干的權利?
  • 如果(this.window.IsDisposed)在UpdateMagnifier()中被註釋,因爲 Window中沒有IsDisposed屬性。
  • 在Dispose()中註釋了處理檢查。

- 由於字符限制,我無法添加Native方法和結構。

幫助將不勝感激,謝謝。

回答

2

你應該在加載窗口的Loaded事件中初始化你的放大鏡,並且可以檢索窗口句柄。否則,它總是零。

public Magnifier(Window window) 
{ 
    if (window == null) 
     throw new ArgumentNullException("form"); 

    hwnd = new WindowInteropHelper(window).Handle; 
    magnification = 2.0f; 
    this.window = window; 
    this.window.SizeChanged += form_Resize; 
    this.window.Closing += form_FormClosing; 

    timer = new DispatcherTimer(); 
    timer.Tick += timer_Tick; 
    Loaded+=MainWindow_Loaded; 
} 

void MainWindow_Loaded(object sender, RoutedEventArgs e) 
{ 
    initialized = NativeMethods.MagInitialize(); 
    if (initialized) 
    { 
     handle = new WindowInteropHelper(this).Handle; 
     SetupMagnifier(); 
     timer.Interval = TimeSpan.FromMilliseconds(NativeMethods.USER_TIMER_MINIMUM); 
     timer.Start();// = true; 
    } 
} 
+0

在我這裏沒有工作......你有沒有想過它? – JobaDiniz 2017-09-11 12:24:10

+0

winforms代碼是越野車...我們需要調整窗口大小直到它開始工作,否則它會顯示黑屏。 – JobaDiniz 2017-09-11 12:40:01