0
크기를 조정할 때 종횡비를 유지하는 WPF 창을 현재 만들고 있습니다.lParam (Resize Rectangle)을 변경할 때 AccessViolationException이 발생했습니다.
첫 번째 아이디어는 WM_SIZE 메시지를 처리하고 거기에 크기를 설정하는 것이지만, 이로 인해 성가신 깜박임이 발생했습니다. 그래서 AccessViolationExceptions을 생성 한 WM_Size의 lParam을 변경하려고했습니다. WM_SIZING에서 lParam을 조작하는 경우에도 마찬가지입니다.
AspectWindow.vb
Imports System.Runtime.InteropServices
Imports System.Windows.Interop
Public Class AspectWindow
Inherits Window
Private AspectRatio As Double
Private ResizeDirection As Direction
Enum Direction
Horizontal
Vertical
End Enum
Enum WM
WM_SIZE = &H5
WM_SIZING = &H214
WM_EXITSIZEMOVE = &H232
WM_NCCALCSIZE = &H83
End Enum
Enum WMSZ
WMSZ_BOTTOM = &H6
WMSZ_BOTTOMLEFT = &H7
WMSZ_BOTTOMRIGHT = &H8
WMSZ_LEFT = &H1
WMSZ_RIGHT = &H2
WMSZ_TOP = &H3
WMSZ_TOPLEFT = &H4
WMSZ_TOPRIGHT = &H5
End Enum
Enum WVR
WVR_VALIDRECTS = &H400
End Enum
Enum IntPtrBool
[True] = 1
[False] = 0
End Enum
<StructLayout(LayoutKind.Sequential)>
Friend Structure RECT
Public left As Long
Public top As Long
Public right As Long
Public bottom As Long
End Structure
Protected Overrides Sub OnSourceInitialized(e As EventArgs)
AspectRatio = Me.ActualWidth/Me.ActualHeight
MyBase.OnSourceInitialized(e)
Dim source As HwndSource = TryCast(HwndSource.FromVisual(Me), HwndSource)
If source IsNot Nothing Then
source.AddHook(New HwndSourceHook(AddressOf WinProc))
End If
End Sub
Private Function WinProc(hwnd As IntPtr, msg As Integer, wParam As IntPtr, lParam As IntPtr, ByRef handled As Boolean) As IntPtr
Select Case msg
Case WM.WM_SIZING
Select Case wParam
Case WMSZ.WMSZ_BOTTOM, WMSZ.WMSZ_TOP
ResizeDirection = Direction.Vertical
Exit Select
Case WMSZ.WMSZ_LEFT, WMSZ.WMSZ_RIGHT
ResizeDirection = Direction.Horizontal
Exit Select
End Select
If Not lParam = Nothing Then
Dim Rect As RECT = Marshal.PtrToStructure(Of RECT)(lParam)
If ResizeDirection = Direction.Horizontal Then
Rect.bottom = Rect.top
Else
Rect.right = Rect.top
End If
'Manipulating Resize Rectangle
Rect.top = 1
Rect.bottom = 2
Rect.left = 3
Rect.right = 4
Marshal.StructureToPtr(Of RECT)(Rect, lParam, False)
End If
Return IntPtrBool.True
End Select
Return IntPtr.Zero
End Function
End Class
이 폭탄을 매우 하드에 제대로 RECT를 선언하지 않았기 때문에 방법을 진단 할 수 있습니다. 게시 된 VB6 선언은 VB.NET에서 멤버가 정수가 아니라 Long이 아닙니다. 너무 많은 데이터를 쓰는 것에 의한 메모리 손상은 디버그하기가 대단히 어렵습니다. 괜찮은 선언을 찾으려면 pinvoke.net 웹 사이트를 사용하십시오. 또한 컴파일러가 작은 실수를 처리하는 데 도움이되도록 Option Strict를 소스 파일의 맨 위에 두는 것이 좋습니다. –