¿Es posible mover/achicar ventanas de otros programas con .NET?

Iniciado por SrTrp, 26 Noviembre 2017, 05:21 AM

0 Miembros y 1 Visitante están viendo este tema.

SrTrp

Quería saber eso por ejemplo que al presionar el boton poner la ventana de google chrome en 700 de ancho y 700 de altura y ponerla en la posisión x=0 y y =0 :/ no quiero que me brinden un código solo si pudiesen decirme que se puede eh estado buscando documentación pero no encuentro.

Eleкtro

#1
Cita de: SrTrp en 26 Noviembre 2017, 05:21 AMque al presionar el boton poner la ventana de google chrome en 700 de ancho y 700 de altura y ponerla en la posisión x=0 y y =0

Mediante la función MoveWindow  de la API de Windows puedes llevar a cabo ambas cosas, es decir, mover la ventana y también redimensionarla. A continuación te muestro un ejemplo completo:

NOTA INFORMATIVA:
---
EL SIGUIENTE CÓDIGO HA SIDO EXTRAIDO Y OFRECIDO DE FORMA GRATUITA A PARTIR DE MI FRAMEWORK COMERCIAL ELEKTROKIT FRAMEWORK , EL CUAL CONTIENE UNA INFINIDAD DE UTILIDADES ENFOCADAS A UNA AMPLIA VARIEDAD DE TEMÁTICAS Y ESCENARIOS EN LA PROGRAMACIÓN .NET, COMO ÉSTE. SI QUIEREN CONOCER MÁS ACERCA DEL PRODUCTO, PUEDEN ENCONTRARLO EN MI FIRMA DE USUARIO DEL FORO.
ESTE CÓDIGO SE PUEDE USAR Y MODIFICAR DE FORMA LIBRE COMO LES APETEZCA.

---

Definición de estructuras nativas ( RECT ):

Código (vbnet) [Seleccionar]
#Region " Imports "

Imports System.Diagnostics
Imports System.Drawing
Imports System.Runtime.InteropServices

#End Region

#Region " NativeRectangle (RECT) "

Namespace ElektroKit.Interop.Win32.Types

   ''' <summary>
   ''' Defines the coordinates of the upper-left and lower-right corners of a rectangle.
   ''' </summary>
   ''' <remarks>
   ''' <see href="http://msdn.microsoft.com/en-us/library/windows/desktop/dd162897%28v=vs.85%29.aspx"/>
   ''' <para></para>
   ''' <see href="http://www.pinvoke.net/default.aspx/Structures/rect.html"/>
   ''' </remarks>
   <StructLayout(LayoutKind.Sequential)>
   <DebuggerStepThrough>
   Public Structure NativeRectangle

#Region " Auto-implemented Properties "

       ''' <summary>
       ''' Gets or sets the x-coordinate of the upper-left corner of the rectangle.
       ''' </summary>
       Public Property Left As Integer

       ''' <summary>
       ''' Gets or sets the y-coordinate of the upper-left corner of the rectangle.
       ''' </summary>
       Public Property Top As Integer

       ''' <summary>
       ''' Gets or sets the x-coordinate of the lower-right corner of the rectangle.
       ''' </summary>
       Public Property Right As Integer

       ''' <summary>
       ''' Gets or sets the y-coordinate of the lower-right corner of the rectangle.
       ''' </summary>
       Public Property Bottom As Integer

#End Region

#Region " Constructors "

       ''' <summary>
       ''' Initializes a new instance of the <see cref="NativeRectangle"/> struct.
       ''' </summary>
       Public Sub New(ByVal left As Integer, ByVal top As Integer,
                      ByVal right As Integer, ByVal bottom As Integer)

           Me.Left = left
           Me.Top = top
           Me.Right = right
           Me.Bottom = bottom

       End Sub

       ''' <summary>
       ''' Initializes a new instance of the <see cref="NativeRectangle"/> struct.
       ''' </summary>
       Public Sub New(ByVal rect As Rectangle)
           Me.New(rect.Left, rect.Top, rect.Right, rect.Bottom)
       End Sub

#End Region

#Region " Operator Conversions "

       ''' <summary>
       ''' Performs an implicit conversion from <see cref="NativeRectangle"/> to <see cref="Rectangle"/>.
       ''' </summary>
       Public Shared Widening Operator CType(ByVal rect As NativeRectangle) As Rectangle
           Return New Rectangle(rect.Left, rect.Top, (rect.Right - rect.Left), (rect.Bottom - rect.Top))
       End Operator

       ''' <summary>
       ''' Performs an implicit conversion from <see cref="Rectangle"/> to <see cref="NativeRectangle"/>.
       ''' </summary>
       Public Shared Widening Operator CType(rect As Rectangle) As NativeRectangle
           Return New NativeRectangle(rect)
       End Operator

#End Region

   End Structure

End Namespace

#End Region


Definición de funciones nativas de Windows:

Código (vbnet) [Seleccionar]
#Region " Imports "

Imports System.Diagnostics
Imports System.Runtime.InteropServices
Imports System.Security

Imports ElektroKit.Interop.Win32.Types

#End Region

#Region " NativeMethods "

Namespace ElektroKit.Interop.Win32

   ''' <summary>
   ''' Platform Invocation methods (P/Invoke), access unmanaged code.
   ''' <para></para>
   ''' This class does not suppress stack walks for unmanaged code permission.
   ''' <see cref="SuppressUnmanagedCodeSecurityAttribute"/> must not be applied to this class.
   ''' <para></para>
   ''' This class is for methods that can be used anywhere because a stack walk will be performed.
   ''' </summary>
   ''' <remarks>
   ''' <see href="http://msdn.microsoft.com/en-us/library/ms182161.aspx"/>
   ''' </remarks>
   Public NotInheritable Class NativeMethods ' <SuppressUnmanagedCodeSecurity>

#Region " Constructors "

       ''' ----------------------------------------------------------------------------------------------------
       ''' <summary>
       ''' Prevents a default instance of the <see cref="NativeMethods"/> class from being created.
       ''' </summary>
       ''' ----------------------------------------------------------------------------------------------------
       <DebuggerNonUserCode>
       Private Sub New()
       End Sub

#End Region

#Region " User32.dll Functions "

       ''' <summary>
       ''' Retrieves the dimensions of the bounding rectangle of the specified window.
       ''' <para></para>
       ''' The dimensions are given in screen coordinates that are relative to the upper-left corner of the screen.
       ''' </summary>
       ''' <remarks>
       ''' <see href="http://msdn.microsoft.com/es-es/library/windows/desktop/ms633519%28v=vs.85%29.aspx"/>
       ''' </remarks>
       ''' <param name="hwnd">
       ''' A <see cref="IntPtr"/> handle to the window.
       ''' </param>
       ''' <param name="refRect">
       ''' A pointer to a <see cref="NativeRectangle"/> structure that receives the screen coordinates of the
       ''' upper-left and lower-right corners of the window.
       ''' </param>
       ''' <returns>
       ''' <see langword="True"/> if the function succeeds, <see langword="False"/> otherwise.
       ''' </returns>
       <DllImport("User32.dll", SetLastError:=True)>
       Public Shared Function GetWindowRect(ByVal hwnd As IntPtr,
                                      <Out> ByRef refRect As NativeRectangle
       ) As <MarshalAs(UnmanagedType.Bool)> Boolean
       End Function

       ''' <summary>
       ''' Retrieves the dimensions of the bounding rectangle of the specified window.
       ''' <para></para>
       ''' The dimensions are given in screen coordinates that are relative to the upper-left corner of the screen.
       ''' </summary>
       <DllImport("User32.dll", SetLastError:=True)>
       Public Shared Function GetWindowRect(ByVal hwnd As HandleRef,
                                      <Out> ByRef refRect As NativeRectangle
       ) As <MarshalAs(UnmanagedType.Bool)> Boolean
       End Function

       ''' <summary>
       ''' Changes the position and dimensions of the specified window.
       ''' <para></para>
       ''' For a top-level window, the position and dimensions are relative to the upper-left corner of the screen.
       ''' <para></para>
       ''' For a child window, they are relative to the upper-left corner of the parent window's client area.
       ''' </summary>
       ''' <remarks>
       ''' <see href="http://msdn.microsoft.com/en-us/library/windows/desktop/ms633534%28v=vs.85%29.aspx"/>
       ''' </remarks>
       ''' <param name="hwnd">
       ''' A handle to the window.
       ''' </param>
       ''' <param name="x">
       ''' The new position of the left side of the window.
       ''' </param>
       ''' <param name="y">
       ''' The new position of the top of the window.
       ''' </param>
       ''' <param name="width">
       ''' The new width of the window.
       ''' </param>
       ''' <param name="height">
       ''' The new height of the window.
       ''' </param>
       ''' <param name="repaint">
       ''' Indicates whether the window is to be repainted.
       ''' <para></para>
       ''' If this parameter is <see langword="True"/>, the window receives a message.
       ''' If the parameter is <see langword="False"/>, no repainting of any kind occurs.
       ''' <para></para>
       ''' This applies to the client area, the nonclient area (including the title bar and scroll bars),
       ''' and any part of the parent window uncovered as a result of moving a child window.
       ''' </param>
       ''' <returns>
       ''' <see langword="True"/> if the function succeeds, <see langword="False"/> otherwise.
       ''' </returns>
       <DllImport("User32.dll", SetLastError:=True)>
       Public Shared Function MoveWindow(ByVal hwnd As IntPtr,
                                         ByVal x As Integer,
                                         ByVal y As Integer,
                                         ByVal width As Integer,
                                         ByVal height As Integer,
         <MarshalAs(UnmanagedType.Bool)> ByVal repaint As Boolean
       ) As <MarshalAs(UnmanagedType.Bool)> Boolean
       End Function

       ''' <summary>
       ''' Changes the position and dimensions of the specified window.
       ''' <para></para>
       ''' For a top-level window, the position and dimensions are relative to the upper-left corner of the screen.
       ''' <para></para>
       ''' For a child window, they are relative to the upper-left corner of the parent window's client area.
       ''' </summary>
       <DllImport("User32.dll", SetLastError:=True)>
       Public Shared Function MoveWindow(ByVal hwnd As HandleRef,
                                         ByVal x As Integer,
                                         ByVal y As Integer,
                                         ByVal width As Integer,
                                         ByVal height As Integer,
         <MarshalAs(UnmanagedType.Bool)> ByVal repaint As Boolean
       ) As <MarshalAs(UnmanagedType.Bool)> Boolean
       End Function

#End Region

   End Class

End Namespace

#End Region


Definición de wrappers para las funciones nativas:

Código (vbnet) [Seleccionar]
#Region " Imports "

Imports System.ComponentModel
Imports System.Diagnostics
Imports System.Runtime.InteropServices
Imports System.Security

Imports ElektroKit.Interop.Win32
Imports ElektroKit.Interop.Win32.Types

#End Region

''' <summary>
''' Provides utilities for window automation.
''' </summary>
<DebuggerStepThrough>
Public NotInheritable Class WindowAutomationUtil

   ''' <summary>
   ''' Set the position for the main window of the specified process.
   ''' </summary>
   ''' <param name="process">
   ''' The source <see cref="Process"/>.
   ''' </param>
   ''' <param name="position">
   ''' The new window position.
   ''' </param>
   ''' <returns>
   ''' <see langword="True"/> if successful; <see langword="False"/> otherwise.
   ''' </returns>
   Public Shared Function MoveWindow(ByVal process As Process,
                                     ByVal position As Point) As Boolean

       If (process Is Nothing) Then
           Throw New ArgumentException(message:="No process found with the specified name.", paramName:="processName")

       Else
           Dim unmanagedRect As NativeRectangle         ' Windows Rectangle definition.
           Dim managedRect As Rectangle = unmanagedRect ' .NET Rectangle definition.

           Dim result As Boolean
           Dim win32err As Integer

           result = NativeMethods.GetWindowRect(process.MainWindowHandle, unmanagedRect)
           win32err = Marshal.GetLastWin32Error()
           If Not (result) Then
               Throw New Win32Exception(win32err)
           End If

           result = NativeMethods.MoveWindow(process.MainWindowHandle,
                                             position.X, position.Y,
                                             managedRect.Width, managedRect.Height,
                                             repaint:=True)
           win32err = Marshal.GetLastWin32Error()
           If Not (result) Then
               Throw New Win32Exception(win32err)
           End If

           Return result

       End If

   End Function

   ''' <summary>
   ''' Set the size for the main window of the specified process.
   ''' </summary>
   ''' <param name="process">
   ''' The source <see cref="Process"/>.
   ''' </param>
   ''' <param name="size">
   ''' The new window size.
   ''' </param>
   ''' <returns>
   ''' <see langword="True"/> if successful; <see langword="False"/> otherwise.
   ''' </returns>
   Public Shared Function ResizeWindow(ByVal process As Process,
                                       ByVal size As Size) As Boolean

       If (process Is Nothing) Then
           Throw New ArgumentException(message:="No process found with the specified name.", paramName:="processName")

       Else
           Dim unmanagedRect As NativeRectangle         ' Windows Rectangle definition.
           Dim managedRect As Rectangle = unmanagedRect ' .NET Rectangle definition.

           Dim result As Boolean
           Dim win32err As Integer

           result = NativeMethods.GetWindowRect(process.MainWindowHandle, unmanagedRect)
           win32err = Marshal.GetLastWin32Error()
           If Not (result) Then
               Throw New Win32Exception(win32err)
           End If

           result = NativeMethods.MoveWindow(process.MainWindowHandle,
                                             managedRect.Left, managedRect.Top,
                                             size.Width, size.Height,
                                             repaint:=True)
           win32err = Marshal.GetLastWin32Error()
           If Not (result) Then
               Throw New Win32Exception(win32err)
           End If

           Return result

       End If

   End Function

End Class


Modo de empleo:
Código (vbnet) [Seleccionar]
Dim p As Process = Process.GetProcessesByName("notepad").FirstOrDefault()

Dim newPos As New Point(x:=0, y:=0)
Dim newSize As New Size(width:=256, height:=256)

WindowAutomationUtil.MoveWindow(p, newPos)
WindowAutomationUtil.ResizeWindow(p, newSize)





Nótese que para el análisis de ventanas con borde invisible de Windows 10 quizás quieras perfeccionar un poco más el algoritmo, según cuales sean tus necesidades. En ese caso primero debes comprobar que el sistema operativo en ejecución sea Windows 10, y posteriormente llamar a la función Win32 DwmGetWindowAttribute.

Te muestro un ejemplo, pero ojo, tómalo a modo de pseudo-código, este código no es funcional ya que no puedo compartir el resto de definiciones necesarias por falta de espacio:

Determinar si el sistema operativo es Windows 10:
Código (vbnet) [Seleccionar]

       ''' ----------------------------------------------------------------------------------------------------
       ''' <summary>
       ''' Gets a value that determines whether the current operating system is <c>Windows 10</c>.
       ''' </summary>
       ''' ----------------------------------------------------------------------------------------------------
       ''' <example> This is a code example.
       ''' <code>
       ''' If IsWin10 Then
       '''     Throw New PlatformNotSupportedException("This application cannot run under Windows 10.")
       ''' End If
       ''' </code>
       ''' </example>
       ''' ----------------------------------------------------------------------------------------------------
       Public Shared ReadOnly Property IsWin10 As Boolean
           <DebuggerStepThrough>
           Get
               Return (Environment.OSVersion.Platform = PlatformID.Win32NT) AndAlso (InternalIsWin10())
           End Get
       End Property

       ''' ----------------------------------------------------------------------------------------------------
       ''' <summary>
       ''' Determines whether the current operating system is <c>Windows 10</c>.
       ''' </summary>
       ''' ----------------------------------------------------------------------------------------------------
       ''' <remarks>
       ''' <see href="http://msdn.microsoft.com/es-es/library/windows/desktop/dn424972%28v=vs.85%29.aspx"/>
       ''' </remarks>
       ''' ----------------------------------------------------------------------------------------------------
       ''' <returns>
       ''' <see langword="True"/> if the current operating system is <c>Windows 10</c>; otherwise, <see langword="False"/>.
       ''' </returns>
       ''' ----------------------------------------------------------------------------------------------------
       <DebuggerStepThrough>
       Private Shared Function InternalIsWin10() As Boolean

           Using reg As RegistryKey = Microsoft.Win32.Registry.LocalMachine.
                                      OpenSubKey("SOFTWARE\Microsoft\Windows NT\CurrentVersion", writable:=False)

               Dim productName As String = DirectCast(reg.GetValue("ProductName", "Empty", RegistryValueOptions.None), String)
               Return productName.StartsWith("Windows 10", StringComparison.OrdinalIgnoreCase)

           End Using

       End Function


Metogología alternativa (menos universal y más tediosa por el requisito del archivo de manifiesto):

Obtener tamaño de ventana:
Código (vbnet) [Seleccionar]
   ''' <summary>
   ''' Gets the non-client area of a window.
   ''' <para></para>
   ''' This method supports a <c>Windows 10</c> window with invisible border or shadows.
   ''' </summary>
   ''' <param name="hwnd">
   ''' A handle to the window.
   ''' </param>
   ''' <returns>
   ''' The resulting non-client area of the window.
   ''' </returns>
   <DebuggerStepThrough>
   Public Shared Function GetRealWindowRect(ByVal hwnd As IntPtr) As Rectangle

       Dim rc As NativeRectangle = Rectangle.Empty

       If (IsWin10) Then
           Dim hResult As Integer
           hResult = NativeMethods.DwmGetWindowAttribute(hwnd, ElektroKit.Interop.Win32.Enums.DwmWindowAttribute.ExtendedFrameBounds, rc, Marshal.SizeOf(rc)) ' DwmWindowAttribute.ExtendedFrameBounds = 9
           If (DirectCast(hResult, ElektroKit.Interop.Win32.Enums.HResult) <> ElektroKit.Interop.Win32.Enums.HResult.S_OK) Then ' HResult.S_OK = 0
               Marshal.ThrowExceptionForHR(hResult)
           End If

       Else
           Dim result As Boolean
           Dim win32Err As Integer
           result = NativeMethods.GetWindowRect(hwnd, rc)
           win32Err = Marshal.GetLastWin32Error()
           If Not (result) Then
               Throw New Win32Exception(win32Err)
           End If

       End If

       Return rc

   End Function

   ''' ----------------------------------------------------------------------------------------------------
   ''' <summary>
   ''' Gets the non-client area of a window.
   ''' <para></para>
   ''' This method supports a <c>Windows 10</c> window with invisible border or shadows.
   ''' </summary>
   ''' <param name="window">
   ''' The source window.
   ''' </param>
   ''' <returns>
   ''' The resulting non-client area of the window.
   ''' </returns>
   <DebuggerStepThrough>
   Public Shared Function GetRealWindowRect(ByVal window As IWin32Window) As Rectangle
       Return GetRealWindowRect(window.Handle)
   End Function

   ''' <summary>
   ''' Gets the non-client area of a <see cref="Form"/> window.
   ''' <para></para>
   ''' This method supports a <c>Windows 10</c> <see cref="Form"/> window with invisible border or shadows.
   ''' </summary>
   ''' <param name="form">
   ''' The source <see cref="Form"/>.
   ''' </param>
   ''' <returns>
   ''' The resulting non-client area of the <see cref="Form"/> window.
   ''' </returns>
   <DebuggerStepThrough>
   Public Shared Function GetRealWindowRect(ByVal form As Form) As Rectangle
       Return GetRealWindowRect(DirectCast(form, IWin32Window).Handle)
   End Function


Saludos.