2014-01-10 3 views
2

하는 Constructor에 대해 경고하고이 유일한 생성자 :코드 분석 나는 시스템 전체 단축키 작업을 수행하는 클래스를 작성했습니다

:

''' <summary> 
''' Creates a new system-wide hotkey. 
''' </summary> 
''' <param name="Modifier">The keys that must be pressed in combination with the specified key.</param> 
''' <param name="Key">The key used for the hotkey.</param> 
''' <exception cref="IsRegisteredException"></exception> 
<DebuggerStepperBoundary()> 
Public Sub New(ByVal Modifier As HotkeyModifier, ByVal Key As Keys) 

    Me.CreateHandle(New CreateParams) 

    Me.PressEventArgs.ID = GetHashCode() 
    Me.PressEventArgs.Key = Key 
    Me.PressEventArgs.Modifier = Modifier 

    If Not NativeMethods.RegisterHotKey(Me.Handle, 
             Me.PressEventArgs.ID, 
             Me.PressEventArgs.Modifier, 
             Me.PressEventArgs.Key) Then 

     Throw New IsRegisteredException 

    End If 

End Sub 

그리고 프로젝트에 코드 분석이 말한다

CA2214 생성자의 GlobalHotkey.New (GlobalHotkey.HotkeyModifier, Keys)에서 재정의 가능한 메서드를 호출하지 마십시오. 에는 해당 클래스에서 정의한 가상 메서드 에 대한 호출을 발생시키는 호출 체인이 포함되어 있습니다. 의도하지 않은 결과에 대해 다음 호출 스택을 검토

GlobalHotkey..ctor (GlobalHotkey + HotkeyModifier, 키) NativeWindow.CreateHandle (CreateParams을) : 무효 Object.GetHashCode() : INT32 컬러 .NET GlobalHorkey.vb 213

PS : 라인 213은 이것이다 :

나는이 충돌을 피하기 위해해야 ​​할 일은
Public Sub New(ByVal Modifier As HotkeyModifier, ByVal Key As Keys) 

? NativeMethods 클래스로 UPDATE

... :

<DllImport("user32.dll", SetLastError:=True)> 
    Public Shared Function RegisterHotKey(
        ByVal hWnd As IntPtr, 
        ByVal id As Integer, 
        ByVal fsModifiers As UInteger, 
        ByVal vk As UInteger 
    ) As <MarshalAs(UnmanagedType.Bool)> Boolean 
    End Function 

업데이트 2

이 전체 클래스입니다 :

#Region " Usage Examples " 

'Public Class Form1 

' ''' <summary> 
' ''' Stores the system-wide hotkey object. 
' ''' </summary> 
' Private WithEvents Hotkey As GlobalHotkey = Nothing 

' ''' <summary> 
' ''' Initializes a new instance of the <see cref="Form1"/> class. 
' ''' </summary> 
' Public Sub New() 

'  InitializeComponent() 

'  ' Registers a new global hotkey on the system. (Alt + Ctrl + A) 
'  Hotkey = New GlobalHotkey(GlobalHotkey.HotkeyModifier.Alt Or GlobalHotkey.HotkeyModifier.Ctrl, Keys.A) 

'  ' Replaces the current registered hotkey with a new global hotkey on the system. (Alt + Escape) 
'  Hotkey = New GlobalHotkey([Enum].Parse(GetType(GlobalHotkey.HotkeyModifier), "Alt", True), 
'         [Enum].Parse(GetType(Keys), "Escape", True)) 

' End Sub 

' ''' <summary> 
' ''' Handles the Press event of the HotKey control. 
' ''' </summary> 
' Private Sub HotKey_Press(ByVal sender As Object, ByVal e As GlobalHotkey.HotKeyEventArgs) _ 
' Handles Hotkey.Press 

'  MsgBox(e.ID) 
'  MsgBox(e.Key.ToString) 
'  MsgBox(e.Modifier.ToString) 

' End Sub 

'End Class 

#End Region 

#Region " Imports " 

Imports System.Runtime.InteropServices 

#End Region 

#Region " Global Hotkey " 

''' <summary> 
''' Class to perform system-wide hotkey operations. 
''' </summary> 
Class GlobalHotkey 
    Inherits NativeWindow 
    Implements IDisposable 

#Region " API " 

    ''' <summary> 
    ''' Native API Methods. 
    ''' </summary> 
    Public Class NativeMethods 

     ''' <summary> 
     ''' Defines a system-wide hotkey. 
     ''' </summary> 
     ''' <param name="hWnd">The hWND.</param> 
     ''' <param name="id">The identifier of the hotkey. 
     ''' If the hWnd parameter is NULL, then the hotkey is associated with the current thread rather than with a particular window. 
     ''' If a hotkey already exists with the same hWnd and id parameters.</param> 
     ''' <param name="fsModifiers">The keys that must be pressed in combination with the key specified by the uVirtKey parameter 
     ''' in order to generate the WM_HOTKEY message. 
     ''' The fsModifiers parameter can be a combination of the following values.</param> 
     ''' <param name="vk">The virtual-key code of the hotkey.</param> 
     ''' <returns> 
     ''' <c>true</c> if the function succeeds, otherwise <c>false</c> 
     ''' </returns> 
     <DllImport("user32.dll", SetLastError:=True)> 
     Public Shared Function RegisterHotKey(
         ByVal hWnd As IntPtr, 
         ByVal id As Integer, 
         ByVal fsModifiers As UInteger, 
         ByVal vk As UInteger 
     ) As <MarshalAs(UnmanagedType.Bool)> Boolean 
     End Function 

     ''' <summary> 
     ''' Unregisters a hotkey previously registered. 
     ''' </summary> 
     ''' <param name="hWnd">The hWND.</param> 
     ''' <param name="id">The identifier of the hotkey to be unregistered.</param> 
     ''' <returns> 
     ''' <c>true</c> if the function succeeds, otherwise <c>false</c> 
     ''' </returns> 
     <DllImport("user32.dll", SetLastError:=True)> 
     Public Shared Function UnregisterHotKey(
         ByVal hWnd As IntPtr, 
         ByVal id As Integer 
     ) As <MarshalAs(UnmanagedType.Bool)> Boolean 
     End Function 

    End Class 

#End Region 

#Region " Members " 

    ''' <summary> 
    ''' The hotkey modifier used in combination with the key. 
    ''' </summary> 
    <Flags> 
    Public Enum HotkeyModifier As Integer 

     ''' <summary> 
     ''' The none 
     ''' </summary> 
     None = &H0 

     ''' <summary> 
     ''' The alt key 
     ''' </summary> 
     Alt = &H1 

     ''' <summary> 
     ''' The control key 
     ''' </summary> 
     Ctrl = &H2 

     ''' <summary> 
     ''' The shift key 
     ''' </summary> 
     Shift = &H4 

     ''' <summary> 
     ''' The win key 
     ''' </summary> 
     Win = &H8 

    End Enum 

    ''' <summary> 
    ''' Event that is raised when a hotkey is pressed. 
    ''' </summary> 
    Public Event Press As EventHandler(Of HotKeyEventArgs) 

    ''' <summary> 
    ''' Stores the Press Event Arguments. 
    ''' </summary> 
    Protected PressEventArgs As New HotKeyEventArgs 

    ''' <summary> 
    ''' Event arguments for the Press event. 
    ''' </summary> 
    Public Class HotKeyEventArgs : Inherits EventArgs 

     ''' <summary> 
     ''' The identifier of the hotkey. 
     ''' </summary> 
     ''' <value>The identifier.</value> 
     Public Property ID As Integer 

     ''' <summary> 
     ''' The key used for the hotkey. 
     ''' </summary> 
     ''' <value>The key.</value> 
     Public Property Key As Keys 

     ''' <summary> 
     ''' The key modifier used for the hotkey. 
     ''' </summary> 
     ''' <value>The modifier.</value> 
     Public Property Modifier As HotkeyModifier 

    End Class 

    ''' <summary> 
    ''' Exception that is thrown when a hotkey is already registered. 
    ''' </summary> 
    <Serializable> 
    Public Class IsRegisteredException : Inherits Exception 

     ''' <summary> 
     ''' Initializes a new instance of the <see cref="IsRegisteredException"/> class. 
     ''' </summary> 
     Sub New() 
      MyBase.New("Hotkey combination is already in use.") 
     End Sub 

    End Class 

#End Region 

#Region " Constructor " 

    ''' <summary> 
    ''' Creates a new system-wide hotkey. 
    ''' </summary> 
    ''' <param name="Modifier">The keys that must be pressed in combination with the specified key.</param> 
    ''' <param name="Key">The key used for the hotkey.</param> 
    ''' <exception cref="IsRegisteredException"></exception> 
    <DebuggerStepperBoundary()> 
    Public Sub New(ByVal Modifier As HotkeyModifier, ByVal Key As Keys) 

     Me.CreateHandle(New CreateParams) 

     Me.PressEventArgs.ID = GetHashCode() 
     Me.PressEventArgs.Key = Key 
     Me.PressEventArgs.Modifier = Modifier 

     If Not NativeMethods.RegisterHotKey(Me.Handle, 
              Me.PressEventArgs.ID, 
              Me.PressEventArgs.Modifier, 
              Me.PressEventArgs.Key) Then 

      Throw New IsRegisteredException 

     End If 

    End Sub 

#End Region 

#Region " WndProc " 

    ''' <summary> 
    ''' Invokes the default window procedure associated with this window. 
    ''' </summary> 
    ''' <param name="m"> 
    ''' A <see cref="T:System.Windows.Forms.Message" /> that is associated with the current Windows message. 
    ''' </param> 
    Protected Overrides Sub WndProc(ByRef m As Message) 

     If m.Msg = 786 Then 
      RaiseEvent Press(Me, Me.PressEventArgs) 
     Else 
      MyBase.WndProc(m) 
     End If 

    End Sub 

#End Region 

#Region " IDisposable " 

    ''' <summary> 
    ''' To detect redundant calls when disposing. 
    ''' </summary> 
    Private IsDisposed As Boolean = False 

    ''' <summary> 
    ''' Prevent calls to methods after disposing. 
    ''' </summary> 
    ''' <exception cref="System.ObjectDisposedException"></exception> 
    Private Sub DisposedCheck() 

     If Me.IsDisposed Then 
      Throw New ObjectDisposedException(Me.GetType().FullName) 
     End If 

    End Sub 

    ''' <summary> 
    ''' Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. 
    ''' </summary> 
    Public Sub Dispose() Implements IDisposable.Dispose 
     Dispose(True) 
     GC.SuppressFinalize(Me) 
    End Sub 

    ' IDisposable 
    ''' <summary> 
    ''' Releases unmanaged and - optionally - managed resources. 
    ''' </summary> 
    ''' <param name="IsDisposing"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param> 
    Protected Overridable Sub Dispose(IsDisposing As Boolean) 

     If Not Me.IsDisposed Then 

      If IsDisposing Then 
       NativeMethods.UnregisterHotKey(Me.Handle, Me.PressEventArgs.ID) 
      End If 

     End If 

     Me.IsDisposed = True 

    End Sub 

#End Region 

End Class 

#End Region 
+0

클래스를 'NotInheritable'으로 표시 할 수 있습니까? –

+0

@CodeCaster 나는 CAXXX가 식별자라는 것을 알지 못했다. 나는 지금 내 조사를하고있다. 정보를 주셔서 감사합니다. – ElektroStudios

+0

@Damien_The_Unbeliever 아니요. 왜냐하면 제가 오버라이드 가능한 메소드 (Dispose)를 가지고 있기 때문에, – ElektroStudios

답변

4

클래스가 NativeWindow, 그 CreateHandle() method is virtual에서 상속되는 메소드를 밀봉. 이것은 당신이받는 경고의 원인입니다. 당신이이 방법을 호출 할 필요가 확실하고 그렇게하는 다른 방법이 없을 경우

, 당신이 무시하고 그것을 밀봉하는 클래스를 만들 수 있다고 생각 :

public class SealedNativeWindow : NativeWindow 
{ 
    public override sealed void CreateHandle(CreateParams cp) 
    { 
     base.CreateHandle(CreateParams cp); 
    } 
} 

그런 다음에서 클래스 상속을하자 이 하나 (VB.NET으로 변환해야합니다).

아니면 그냥 ignore the warning 일 수 있습니다.

+1

고마워요, 정말 솔루션인지 아닌지 다른 해결책을 찾았습니다. 클래스를 noninhertibale로 설정하고 Dispose 메서드의 '재정의'키워드를 삭제했습니다. 다른 수정을 수행하고 싶습니다. 내가 한 일이 올바른 해결책인지 아십시오. – ElektroStudios

+2

@ Elektro 나는 또한 트릭을한다고 생각한다. 왜냐하면 이제 당신의 클래스는 상속 될 수 없으며 가상 메소드는 단지 하나의 구현만을 갖고 있기 때문이다. – CodeCaster

2

CreateHandle은 가상이며 사용자 임의의 서브 클래스가이를 오버라이드하여 객체 구성을 제어 할 수 없게합니다. 참조 : 예 : the documentation. (올바른) CodeCaster의 용액

VB 상당

Public NotOverridable Overrides Sub _ 
         CreateHandle(cp As System.Windows.Forms.CreateParams) 
    MyBase.CreateHandle(cp) 
End Sub 
+0

감사합니다.하지만 제 수업은 제어 유형을 상속받지 않습니다. – ElektroStudios

+0

@ElektroStudios 죄송합니다, 답변을 드렸을 때 전체 코드를 게시했습니다. 그러나 CodeCaster는 정확하며'NativeWindow' 메서드는 가상입니다. –