2017-02-03 2 views
0

Visual Basic Windows Form 크기가 응용 프로그램의 너비/높이로 설정되어 있지만 작동하지 않습니다.VB Windows 폼이 응용 프로그램의 너비/높이에 맞지 않습니다.

이 VBA에서 나를 위해 완벽하게 잘 작동하지만, 그것 추가 기능에 대해 원하는대로 작동하지 :

Dim newForm As New ExportingForm 
    newForm.ShowDialog() 

Public Class ExportingForm 

    Private Sub ExportingForm_Layout(sender As Object, e As EventArgs) Handles MyBase.Layout 

    Dim exclApp As Excel.Application = Globals.ThisAddIn.Application 

    If exclApp.WindowState = Excel.XlWindowState.xlMaximized Then 
     Me.WindowState = System.Windows.Forms.FormWindowState.Maximized 
    Else 
     Me.Size = New Drawing.Point(exclApp.Width, exclApp.Height) 
    End If 
    End Sub 

End Class 

또한 디자이너 모드에서 여기에 Windows Form에 대한 내 설정은 다음과 같습니다

IsMdiContainer False 
Location  0,0 
MaximumSize 0,0 
MinimumSize 0,0 
Padding  0,0,0,0 
Size   250,250 
StartPosition CenterParent 

은 그것은 잘 센터와 폭/높이 프로그래밍 방식으로 잘뿐만 아니라, 응용 프로그램 너비/높이 특정 시점으로 변경하고 그것을 중지 설정할 때 잘 수 있습니다. 이 문제를 해결하려면 무엇을해야합니까?

나는 또한 시도했다 :

Me.Size = New Drawing.Point(exclApp.ActiveWindow.Width, exclApp.ActiveWindow.Height) 

그리고 나는 또한 양식을 표시하기 전에 크기를 설정 시도했다 : 나는 당신이 한 작동으로 가지고있는 언어를 번역 할 수 있습니다

Dim newForm..... 
newForm.Size = New Drawing.Point(exclApp.Width, exclApp.Height) 
newForm.ShowDialog() 

을 비주얼 스튜디오와

enter image description here

+2

[Excel.Application.Width] (https://msdn.microsoft.com/en-us/library/office/ff840678.aspx) 및 [Excel.Application.Height] (https://msdn.microsoft. com/ko-us/library/office/ff195524.aspx)는 점으로 측정됩니다. [Form.Size] (https://msdn.microsoft.com/en-us/library/25w4thew(v=vs.110)).aspx)는 픽셀 단위로 측정됩니다. 당신은 [둘 사이의 변환해야] (http://stackoverflow.com/questions/139655/convert-pixels-to-points). – Comintern

+0

고마워요. @Comintern MSDN에서 보았을 때조차도 그 사실을 언급하지 않았습니다. 링크 감사를 드리겠습니다. – soulshined

답변

2

수정 사항

이론적으로 원래 제시 한 방법이 효과가 있지만 Excel PointsToScreenPixels 메서드에는 문제가 있습니다. 기능에 대한 인터넷 검색은 결과가 신뢰할 수 없다는 것을 나타냅니다. 따라서 Win32 API 함수 인 GetWindowRect를 사용하여 Excel 응용 프로그램의 위치와 크기를 검색하는 것이 좋습니다. API 함수 정의는 http://www.pinvoke.net/index.aspx에서 가져온 것입니다.

Imports Excel = Microsoft.Office.Interop.Excel 
Imports System.Runtime.InteropServices 

Public Class Form1 

    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click 
     test() 
    End Sub 

    Sub test() 
     Dim meDPI As PointF = GetDPI(Me.Handle) 

     Dim app As New Excel.Application 
     app.Visible = True 

     Dim appHwnd As IntPtr = New IntPtr(app.Hwnd) 

     ' setting Excel's size and position -- just for test verification purposes 
     SetWindowPos(appHwnd, IntPtr.Zero, 10, 10, 500, 300, SetWindowPosFlags.DoNotActivate) 

     Dim rc As RECT 
     GetWindowRect(appHwnd, rc) ' retrieve Excel's size and position into rc 

     app.UserControl = True ' return control to the user 
     Console.WriteLine("Excel located at X: {0}, Y: {1}, Width: {2}, Height: {3}", rc.Left, rc.Top, rc.Width, rc.Height) 
     Me.Location = rc.Location 
     Me.Size = rc.Size 
     Me.Activate() ' bring this form to the front 
     Me.Opacity = 0.5 ' allow to view thru to Excel 
    End Sub 

    Public Shared Function GetDPI(hwnd As IntPtr) As PointF 
     Dim ret As PointF 
     Using g As Graphics = Graphics.FromHwnd(hwnd) 
      ret.X = g.DpiX 
      ret.Y = g.DpiY 
     End Using 
     Return ret 
    End Function 

    <DllImport("user32.dll")> _ 
    Private Shared Function GetWindowRect(ByVal hWnd As IntPtr, ByRef lpRect As RECT) As Boolean 
    End Function 

    <StructLayout(LayoutKind.Sequential)> _ 
    Public Structure RECT 
     Private _Left As Integer, _Top As Integer, _Right As Integer, _Bottom As Integer 

     Public Sub New(ByVal Rectangle As Rectangle) 
       Me.New(Rectangle.Left, Rectangle.Top, Rectangle.Right, Rectangle.Bottom) 
     End Sub 
     Public Sub New(ByVal Left As Integer, ByVal Top As Integer, ByVal Right As Integer, ByVal Bottom As Integer) 
       _Left = Left 
       _Top = Top 
       _Right = Right 
       _Bottom = Bottom 
     End Sub 

     Public Property X As Integer 
       Get 
       Return _Left 
       End Get 
       Set(ByVal value As Integer) 
       _Right = _Right - _Left + value 
       _Left = value 
       End Set 
     End Property 
     Public Property Y As Integer 
       Get 
       Return _Top 
       End Get 
       Set(ByVal value As Integer) 
       _Bottom = _Bottom - _Top + value 
       _Top = value 
       End Set 
     End Property 
     Public Property Left As Integer 
       Get 
       Return _Left 
       End Get 
       Set(ByVal value As Integer) 
       _Left = value 
       End Set 
     End Property 
     Public Property Top As Integer 
       Get 
       Return _Top 
       End Get 
       Set(ByVal value As Integer) 
       _Top = value 
       End Set 
     End Property 
     Public Property Right As Integer 
       Get 
       Return _Right 
       End Get 
       Set(ByVal value As Integer) 
       _Right = value 
       End Set 
     End Property 
     Public Property Bottom As Integer 
       Get 
       Return _Bottom 
       End Get 
       Set(ByVal value As Integer) 
       _Bottom = value 
       End Set 
     End Property 
     Public Property Height() As Integer 
       Get 
       Return _Bottom - _Top 
       End Get 
       Set(ByVal value As Integer) 
       _Bottom = value + _Top 
       End Set 
     End Property 
     Public Property Width() As Integer 
       Get 
       Return _Right - _Left 
       End Get 
       Set(ByVal value As Integer) 
       _Right = value + _Left 
       End Set 
     End Property 
     Public Property Location() As Point 
       Get 
       Return New Point(Left, Top) 
       End Get 
       Set(ByVal value As Point) 
       _Right = _Right - _Left + value.X 
       _Bottom = _Bottom - _Top + value.Y 
       _Left = value.X 
       _Top = value.Y 
       End Set 
     End Property 
     Public Property Size() As Size 
       Get 
       Return New Size(Width, Height) 
       End Get 
       Set(ByVal value As Size) 
       _Right = value.Width + _Left 
       _Bottom = value.Height + _Top 
       End Set 
     End Property 

     Public Shared Widening Operator CType(ByVal Rectangle As RECT) As Rectangle 
       Return New Rectangle(Rectangle.Left, Rectangle.Top, Rectangle.Width, Rectangle.Height) 
     End Operator 
     Public Shared Widening Operator CType(ByVal Rectangle As Rectangle) As RECT 
       Return New RECT(Rectangle.Left, Rectangle.Top, Rectangle.Right, Rectangle.Bottom) 
     End Operator 
     Public Shared Operator =(ByVal Rectangle1 As RECT, ByVal Rectangle2 As RECT) As Boolean 
       Return Rectangle1.Equals(Rectangle2) 
     End Operator 
     Public Shared Operator <>(ByVal Rectangle1 As RECT, ByVal Rectangle2 As RECT) As Boolean 
       Return Not Rectangle1.Equals(Rectangle2) 
     End Operator 

     Public Overrides Function ToString() As String 
       Return "{Left: " & _Left & "; " & "Top: " & _Top & "; Right: " & _Right & "; Bottom: " & _Bottom & "}" 
     End Function 

     Public Overloads Function Equals(ByVal Rectangle As RECT) As Boolean 
       Return Rectangle.Left = _Left AndAlso Rectangle.Top = _Top AndAlso Rectangle.Right = _Right AndAlso Rectangle.Bottom = _Bottom 
     End Function 
     Public Overloads Overrides Function Equals(ByVal [Object] As Object) As Boolean 
       If TypeOf [Object] Is RECT Then 
       Return Equals(DirectCast([Object], RECT)) 
       ElseIf TypeOf [Object] Is Rectangle Then 
       Return Equals(New RECT(DirectCast([Object], Rectangle))) 
       End If 

       Return False 
     End Function 
    End Structure 

    <DllImport("user32.dll", SetLastError:=True)> _ 
    Private Shared Function SetWindowPos(ByVal hWnd As IntPtr, ByVal hWndInsertAfter As IntPtr, ByVal X As Integer, ByVal Y As Integer, ByVal cx As Integer, ByVal cy As Integer, ByVal uFlags As SetWindowPosFlags) As Boolean 
    End Function 
    <Flags> _ 
    Private Enum SetWindowPosFlags As UInteger 
     ''' <summary>If the calling thread and the thread that owns the window are attached to different input queues, 
     ''' the system posts the request to the thread that owns the window. This prevents the calling thread from 
     ''' blocking its execution while other threads process the request.</summary> 
     ''' <remarks>SWP_ASYNCWINDOWPOS</remarks> 
     ASynchronousWindowPosition = &H4000 
     ''' <summary>Prevents generation of the WM_SYNCPAINT message.</summary> 
     ''' <remarks>SWP_DEFERERASE</remarks> 
     DeferErase = &H2000 
     ''' <summary>Draws a frame (defined in the window's class description) around the window.</summary> 
     ''' <remarks>SWP_DRAWFRAME</remarks> 
     DrawFrame = &H20 
     ''' <summary>Applies new frame styles set using the SetWindowLong function. Sends a WM_NCCALCSIZE message to 
     ''' the window, even if the window's size is not being changed. If this flag is not specified, WM_NCCALCSIZE 
     ''' is sent only when the window's size is being changed.</summary> 
     ''' <remarks>SWP_FRAMECHANGED</remarks> 
     FrameChanged = &H20 
     ''' <summary>Hides the window.</summary> 
     ''' <remarks>SWP_HIDEWINDOW</remarks> 
     HideWindow = &H80 
     ''' <summary>Does not activate the window. If this flag is not set, the window is activated and moved to the 
     ''' top of either the topmost or non-topmost group (depending on the setting of the hWndInsertAfter 
     ''' parameter).</summary> 
     ''' <remarks>SWP_NOACTIVATE</remarks> 
     DoNotActivate = &H10 
     ''' <summary>Discards the entire contents of the client area. If this flag is not specified, the valid 
     ''' contents of the client area are saved and copied back into the client area after the window is sized or 
     ''' repositioned.</summary> 
     ''' <remarks>SWP_NOCOPYBITS</remarks> 
     DoNotCopyBits = &H100 
     ''' <summary>Retains the current position (ignores X and Y parameters).</summary> 
     ''' <remarks>SWP_NOMOVE</remarks> 
     IgnoreMove = &H2 
     ''' <summary>Does not change the owner window's position in the Z order.</summary> 
     ''' <remarks>SWP_NOOWNERZORDER</remarks> 
     DoNotChangeOwnerZOrder = &H200 
     ''' <summary>Does not redraw changes. If this flag is set, no repainting of any kind occurs. 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 the window being moved. When this flag is set, the application must 
     ''' explicitly invalidate or redraw any parts of the window and parent window that need redrawing.</summary> 
     ''' <remarks>SWP_NOREDRAW</remarks> 
     DoNotRedraw = &H8 
     ''' <summary>Same as the SWP_NOOWNERZORDER flag.</summary> 
     ''' <remarks>SWP_NOREPOSITION</remarks> 
     DoNotReposition = &H200 
     ''' <summary>Prevents the window from receiving the WM_WINDOWPOSCHANGING message.</summary> 
     ''' <remarks>SWP_NOSENDCHANGING</remarks> 
     DoNotSendChangingEvent = &H400 
     ''' <summary>Retains the current size (ignores the cx and cy parameters).</summary> 
     ''' <remarks>SWP_NOSIZE</remarks> 
     IgnoreResize = &H1 
     ''' <summary>Retains the current Z order (ignores the hWndInsertAfter parameter).</summary> 
     ''' <remarks>SWP_NOZORDER</remarks> 
     IgnoreZOrder = &H4 
     ''' <summary>Displays the window.</summary> 
     ''' <remarks>SWP_SHOWWINDOW</remarks> 
     ShowWindow = &H40 
    End Enum 

End Class 

위의 코드를 테스트에 있다는 점 유의 하시길 바랍니다의 WinForm 응용 프로그램은 그 app.Manifest 파일에 다음과 같은 필요에 의해 DPI 인식로 선언된다.

<application xmlns="urn:schemas-microsoft-com:asm.v3"> 
    <windowsSettings> 
     <dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true</dpiAware> 
    </windowsSettings> 
    </application> 

Application.Height PropertyApplication.Width Property

이 점하지 픽셀로 측정되어 사용하지 마십시오. Window.PointsToScreenPixelsX MethodWindow.PointsToScreenPixelsY 메서드를 사용하여 너비와 높이를 픽셀 단위로 계산하여 양식 크기를 설정할 수 있습니다.

width = exclApp.ActiveWindow.PointsToScreenPixelsX(exclApp.Width)

height = exclApp.ActiveWindow.PointsToScreenPixelsY(exclApp.Height)

당신은 또한 윈도우의 확장 양식을 방지하기 위해 인식 DPI와 같은 추가 기능을 선언해야합니다 경우 나도 몰라

.

참고 : Excel에서 테스트 할 때 기본으로, ActiveWindow 만 값을 산출합니다.

+0

'Window (1)'에 대해 유효성을 검사하는 경우, 이것은 당연하지 않습니다. PointsToPixels, 당신은 'exclApp.Width' 대신에 Points를 사용해야합니다. 그렇지 않으면 잘못된 결과가 나옵니다. 또한 매개 변수 앞에 마침표가 없어야합니다. 그렇지 않으면 올바른 대답입니다. 감사합니다 – soulshined

+0

희망 당신은, 나는 미래의 질문을 찾는 사람들을위한 혼란을 방지하기 위해 편집. 듀얼 모니터 이상의 사용자는 DPI 인식이 좋을 것이라고 생각합니다. 좀 더 감사해야만합니다. – soulshined

+0

@soulshined, 방금 Excel에서 테스트했습니다. 창은 ActiveWindow 여야합니다. 그렇지 않으면 함수는 0을 반환합니다. 또한 변환 된 값의 소스는 적절한 값인 한 중요하지 않습니다. 'exclApp.Windows (1) .Width'는'exclApp.Width'와 같지 않습니다. 나는 그 포스트를 편집 할 것이다. – TnTinMn