You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
188 lines
5.7 KiB
188 lines
5.7 KiB
/*************************************************************************************
|
|
|
|
Extended WPF Toolkit
|
|
|
|
Copyright (C) 2007-2013 Xceed Software Inc.
|
|
|
|
This program is provided to you under the terms of the Microsoft Public
|
|
License (Ms-PL) as published at http://wpftoolkit.codeplex.com/license
|
|
|
|
For more features, controls, and fast professional support,
|
|
pick up the Plus Edition at http://xceed.com/wpf_toolkit
|
|
|
|
Stay informed: follow @datagrid on Twitter or Like http://facebook.com/datagrids
|
|
|
|
***********************************************************************************/
|
|
|
|
/**************************************************************************\
|
|
Copyright Microsoft Corporation. All Rights Reserved.
|
|
\**************************************************************************/
|
|
|
|
namespace Standard
|
|
{
|
|
using System;
|
|
using System.Runtime.InteropServices;
|
|
using System.Windows;
|
|
using System.Windows.Threading;
|
|
using System.Collections.Generic;
|
|
using System.Diagnostics.CodeAnalysis;
|
|
|
|
internal sealed class MessageWindow : DispatcherObject, IDisposable
|
|
{
|
|
// Alias this to a static so the wrapper doesn't get GC'd
|
|
private static readonly WndProc s_WndProc = new WndProc( _WndProc );
|
|
private static readonly Dictionary<IntPtr, MessageWindow> s_windowLookup = new Dictionary<IntPtr, MessageWindow>();
|
|
|
|
private WndProc _wndProcCallback;
|
|
private string _className;
|
|
private bool _isDisposed;
|
|
|
|
public IntPtr Handle
|
|
{
|
|
get; private set;
|
|
}
|
|
|
|
[SuppressMessage( "Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands" )]
|
|
public MessageWindow( CS classStyle, WS style, WS_EX exStyle, Rect location, string name, WndProc callback )
|
|
{
|
|
// A null callback means just use DefWindowProc.
|
|
_wndProcCallback = callback;
|
|
_className = "MessageWindowClass+" + Guid.NewGuid().ToString();
|
|
|
|
var wc = new WNDCLASSEX
|
|
{
|
|
cbSize = Marshal.SizeOf( typeof( WNDCLASSEX ) ),
|
|
style = classStyle,
|
|
lpfnWndProc = s_WndProc,
|
|
hInstance = NativeMethods.GetModuleHandle( null ),
|
|
hbrBackground = NativeMethods.GetStockObject( StockObject.NULL_BRUSH ),
|
|
lpszMenuName = "",
|
|
lpszClassName = _className,
|
|
};
|
|
|
|
NativeMethods.RegisterClassEx( ref wc );
|
|
|
|
GCHandle gcHandle = default( GCHandle );
|
|
try
|
|
{
|
|
gcHandle = GCHandle.Alloc( this );
|
|
IntPtr pinnedThisPtr = ( IntPtr )gcHandle;
|
|
|
|
Handle = NativeMethods.CreateWindowEx(
|
|
exStyle,
|
|
_className,
|
|
name,
|
|
style,
|
|
( int )location.X,
|
|
( int )location.Y,
|
|
( int )location.Width,
|
|
( int )location.Height,
|
|
IntPtr.Zero,
|
|
IntPtr.Zero,
|
|
IntPtr.Zero,
|
|
pinnedThisPtr );
|
|
}
|
|
finally
|
|
{
|
|
gcHandle.Free();
|
|
}
|
|
}
|
|
|
|
~MessageWindow()
|
|
{
|
|
_Dispose( false, false );
|
|
}
|
|
|
|
public void Dispose()
|
|
{
|
|
_Dispose( true, false );
|
|
GC.SuppressFinalize( this );
|
|
}
|
|
|
|
// This isn't right if the Dispatcher has already started shutting down.
|
|
// It will wind up leaking the class ATOM...
|
|
[SuppressMessage( "Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "disposing" )]
|
|
private void _Dispose( bool disposing, bool isHwndBeingDestroyed )
|
|
{
|
|
if( _isDisposed )
|
|
{
|
|
// Block against reentrancy.
|
|
return;
|
|
}
|
|
|
|
_isDisposed = true;
|
|
|
|
IntPtr hwnd = Handle;
|
|
string className = _className;
|
|
|
|
if( isHwndBeingDestroyed )
|
|
{
|
|
Dispatcher.BeginInvoke( DispatcherPriority.Normal, ( DispatcherOperationCallback )( arg => _DestroyWindow( IntPtr.Zero, className ) ) );
|
|
}
|
|
else if( Handle != IntPtr.Zero )
|
|
{
|
|
if( CheckAccess() )
|
|
{
|
|
_DestroyWindow( hwnd, className );
|
|
}
|
|
else
|
|
{
|
|
Dispatcher.BeginInvoke( DispatcherPriority.Normal, ( DispatcherOperationCallback )( arg => _DestroyWindow( hwnd, className ) ) );
|
|
}
|
|
}
|
|
|
|
s_windowLookup.Remove( hwnd );
|
|
|
|
_className = null;
|
|
Handle = IntPtr.Zero;
|
|
}
|
|
|
|
[SuppressMessage( "Microsoft.Usage", "CA1816:CallGCSuppressFinalizeCorrectly" )]
|
|
private static IntPtr _WndProc( IntPtr hwnd, WM msg, IntPtr wParam, IntPtr lParam )
|
|
{
|
|
IntPtr ret = IntPtr.Zero;
|
|
MessageWindow hwndWrapper = null;
|
|
|
|
if( msg == WM.CREATE )
|
|
{
|
|
var createStruct = ( CREATESTRUCT )Marshal.PtrToStructure( lParam, typeof( CREATESTRUCT ) );
|
|
GCHandle gcHandle = GCHandle.FromIntPtr( createStruct.lpCreateParams );
|
|
hwndWrapper = ( MessageWindow )gcHandle.Target;
|
|
s_windowLookup.Add( hwnd, hwndWrapper );
|
|
}
|
|
else
|
|
{
|
|
if( !s_windowLookup.TryGetValue( hwnd, out hwndWrapper ) )
|
|
{
|
|
return NativeMethods.DefWindowProc( hwnd, msg, wParam, lParam );
|
|
}
|
|
}
|
|
Assert.IsNotNull( hwndWrapper );
|
|
|
|
WndProc callback = hwndWrapper._wndProcCallback;
|
|
if( callback != null )
|
|
{
|
|
ret = callback( hwnd, msg, wParam, lParam );
|
|
}
|
|
else
|
|
{
|
|
ret = NativeMethods.DefWindowProc( hwnd, msg, wParam, lParam );
|
|
}
|
|
|
|
if( msg == WM.NCDESTROY )
|
|
{
|
|
hwndWrapper._Dispose( true, true );
|
|
GC.SuppressFinalize( hwndWrapper );
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
private static object _DestroyWindow( IntPtr hwnd, string className )
|
|
{
|
|
Utility.SafeDestroyWindow( ref hwnd );
|
|
NativeMethods.UnregisterClass( className, NativeMethods.GetModuleHandle( null ) );
|
|
return null;
|
|
}
|
|
}
|
|
}
|
|
|