2012-08-10 2 views
3

WinForms에서 Magnification API를 사용하여 웹에서 library을 발견했습니다. 나는 WPF와 함께 작동하도록 만들었지 만, 아무런 예외 나 예외도 없었습니다. 모든 것이 OK 인 것 같습니다. 나는 이것이 WPF로 작동하지 않는다고 생각하기 시작했습니다.WinForms에서 WPF까지의 확대 API 사용

윈폼 번호 :

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을 사용하여 위해 -

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 클래스를 수정 Fo에서 초기화하십시오. rm/Window의 생성자. ,

  • 추가 "HWND"필드를 돋보기 생성자에서 초기화 :

    -Changes 나는 WPF에서했다.

  • 대체 됨 System.Windows.Forms.Timer가 으로 대체되었습니다. System.Windows.Threading.DispatcherTimer.
  • 변경된 양식. window.SizeChanged 및 form.FormClosing을 window.Closing으로 변경했습니다. 하지만 이건 맞지 않아?
  • 부터 UpdateMagnifier()에 (this.window.IsDisposed)가있는 경우 Window에 IsDisposed 속성이 없습니다.
  • Dispose()의 처분 확인에 대한 설명입니다.

-I 문자 제한으로 인해 네이티브 메서드 및 구조를 추가 할 수 없습니다.

도움을 주시면 대단히 감사하겠습니다.

답변

2

윈도우가로드되고 창 핸들을 검색 할 수있는로드 된 이벤트에서 돋보기를 초기화해야합니다. 그렇지 않으면 항상 0입니다.

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

+0

winforms 코드는 버그가 있습니다 ... 작동하기 시작할 때까지 창의 크기를 조정해야합니다. 그렇지 않으면 검정색 화면이 표시됩니다. – JobaDiniz