Code:
/ Dotnetfx_Win7_3.5.1 / Dotnetfx_Win7_3.5.1 / 3.5.1 / DEVDIV / depot / DevDiv / releases / Orcas / NetFXw7 / wpf / src / WinFormsIntegration / System / Windows / Integration / ElementHost.cs / 1 / ElementHost.cs
using System.Collections.Generic; using System.ComponentModel; using System.ComponentModel.Design.Serialization; using System.Diagnostics; using System.Runtime.InteropServices; using System.Diagnostics.CodeAnalysis; using System.Globalization; using System.Windows.Documents; using System.Windows.Interop; using System.Windows.Markup; using System.Windows.Media; using System.Security.Permissions; using MS.Win32; using SD = System.Drawing; using SWF = System.Windows.Forms; using SW = System.Windows; using SWC = System.Windows.Controls; using SWM = System.Windows.Media; using SWMI = System.Windows.Media.Imaging; using SWI = System.Windows.Input; namespace System.Windows.Forms.Integration { ////// A Windows Forms control that can be used to host a Windows Presentation /// Foundation element. /// [System.ComponentModel.DesignerCategory("code")] [ContentProperty("Child")] [DefaultEvent("ChildChanged")] [Designer("WindowsFormsIntegration.Design.ElementHostDesigner, WindowsFormsIntegration.Design, Version=1.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")] [DesignerSerializer("WindowsFormsIntegration.Design.ElementHostCodeDomSerializer, WindowsFormsIntegration.Design, Version=1.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a", "System.ComponentModel.Design.Serialization.CodeDomSerializer, System.Design, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")] public class ElementHost : Control { private HwndSource _hwndSource; ////// The decorator is used to provide an Adorner layer which is needed to show UI highlights /// for focus etc. In the pure-Avalon case, this would be handled by Window /// private AdornerDecorator _decorator; private AvalonAdapter _hostContainerInternal; private bool _backColorTransparent; private SW.UIElement _child; private bool _processingWmInputLangChanged; // Flag to prevent re-entrancy when processing WM_INPUTLANGCHANGED #region Constructors ////// Initializes a new instance of the ElementHost class. /// ////// Overridden to plug the Avalon control into WinForm's layout engines. /// [PermissionSet(SecurityAction.Demand, Name = "FullTrust")] public ElementHost() : base() { this._hostContainerInternal = new AvalonAdapter(this); this._decorator = new AdornerDecorator(); _decorator.Child = this._hostContainerInternal; SetStyle(SWF.ControlStyles.SupportsTransparentBackColor, true); SetStyle(SWF.ControlStyles.UserPaint, true); SetStyle(SWF.ControlStyles.AllPaintingInWmPaint, true); System.Windows.Input.FocusManager.SetIsFocusScope(this._decorator, true); //For keyboarding, this listens for WM_CHAR events not handled, so that mnemonics //that are pressed without the ALT key can be handled. SWI.InputManager.Current.PostProcessInput += InputManager_PostProcessInput; this.SetAutoSizeMode(AutoSizeMode.GrowAndShrink); StartPropertyMapping(); SizeChanged += new EventHandler(CallUpdateBackground); LocationChanged += new EventHandler(CallUpdateBackground); } #endregion #region Layout ////// Overrides the base class implementation of GetPreferredSize to provide /// correct layout behavior for the hosted Windows Presentation Foundation elements. /// public override SD.Size GetPreferredSize(SD.Size proposedSize) { if (Disposing) { return base.GetPreferredSize(proposedSize); } proposedSize = HostUtils.IntersectSizes(HostUtils.ConvertZeroOrOneToUnbounded(proposedSize), HostUtils.ConvertZeroToUnbounded(MaximumSize)); proposedSize = HostUtils.UnionSizes(proposedSize, MinimumSize); // Apply the child's scaling, if any Vector scale = (Child == null ? new Vector(1d, 1d) : HostUtils.GetScale(Child)); Size constraints = Convert.ToSystemWindowsSize(proposedSize, scale); // At this point, an unbounded value is represented by Int32.MaxValue: WPF wants double.PositiveInfinity. if (constraints.Width == Int32.MaxValue) { constraints.Width = Double.PositiveInfinity; } if (constraints.Height == Int32.MaxValue) { constraints.Height = Double.PositiveInfinity; } // Request that control recompute desired size with new constraints. _decorator.Measure(constraints); SD.Size prefSize = Convert.ToSystemDrawingSize(_decorator.DesiredSize, scale); // WindowsForms guarantees results will be bounded by control Min/MaxSize prefSize = HostUtils.IntersectSizes(prefSize, HostUtils.ConvertZeroToUnbounded(MaximumSize)); prefSize = HostUtils.UnionSizes(prefSize, MinimumSize); Debug.WriteLineIf(_traceLayout.TraceInfo, String.Format(CultureInfo.CurrentCulture, "AvalonAdapter({0}): MeasureOverride (constraint={1},result={2})", this.Name, proposedSize, prefSize)); return prefSize; } ////// Gets the default size of the control. /// protected override System.Drawing.Size DefaultSize { get { return new SD.Size(200, 100); } } ////// Gets or sets a value indicating whether the control is /// automatically resized to display its entire contents. /// [Browsable(true), EditorBrowsable(EditorBrowsableState.Always)] public override bool AutoSize { get { return base.AutoSize; } set { base.AutoSize = value; } } #endregion Layout #region Containership ////// Gets the parent container of the hosted Windows Presentation Foundation element. /// [Browsable(false)] [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public SWC.Panel HostContainer { get { return HostContainerInternal; } } internal HwndSource HwndSource { get { return _hwndSource; } } ////// Indicates that the Child property has been changed. /// public event EventHandlerChildChanged; /// /// Gets or sets the UIElement hosted by the ElementHost control. /// [Browsable(false)] [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public SW.UIElement Child { get { return _child; } set { UIElement oldValue = Child; #pragma warning disable 1634, 1691 #pragma warning disable 56526 _child = value; #pragma warning restore 1634, 1691, 56526 HostContainerInternal.Children.Clear(); if (_child != null) { HostContainerInternal.Children.Add(_child); _propertyMap.ApplyAll(); InitializeChildProperties(); } OnChildChanged(oldValue); } } protected override bool CanEnableIme { get { if (this.Child == null) { return false; } return base.CanEnableIme; } } ////// If focus on HwndSource, we need to return true here. /// public override bool Focused { get { if( IsHandleCreated ) { // observe that the EH.Child may be null and still it has an HwndSource. IntPtr focusHandle = UnsafeNativeMethods.GetFocus(); return (focusHandle == this.Handle || (this.HwndSource != null && focusHandle == this.HwndSource.Handle)); } return false; } } protected override SWF.ImeMode ImeModeBase { get { return this.CanEnableIme ? base.ImeModeBase : ImeMode.Disable; } set { base.ImeModeBase = value; // When the ImeMode is set to ImeMode.NoControl, Winforms stops raising the ImeModeChanged event // on the control, we need to notify the property mapper explicitly. if (value == SWF.ImeMode.NoControl) { this.OnPropertyChangedImeMode(this, EventArgs.Empty); } } } private void OnChildChanged(UIElement oldChild) { if (this.Child != null) { SyncHwndSrcImeStatus(); } if (ChildChanged != null) { ChildChanged(this, new ChildChangedEventArgs(oldChild)); } } ////// Raises the Leave event. /// /// protected override void OnLeave(EventArgs e) { System.Windows.Input.FocusManager.SetFocusedElement(_decorator, null); base.OnLeave(e); } ////// Raises the GotFocus event. /// /// protected override void OnGotFocus(EventArgs e) { base.OnGotFocus(e); SyncHwndSrcImeStatus(); _decorator.Focus(); } private void InitializeChildProperties() { FrameworkElement childFrameworkElement = Child as FrameworkElement; if (childFrameworkElement != null) { childFrameworkElement.SizeChanged += new SizeChangedEventHandler(childFrameworkElement_SizeChanged); childFrameworkElement.Height = double.NaN; childFrameworkElement.Width = double.NaN; childFrameworkElement.Margin = new Thickness(0d); childFrameworkElement.VerticalAlignment = SW.VerticalAlignment.Stretch; childFrameworkElement.HorizontalAlignment = SW.HorizontalAlignment.Stretch; DesignerProperties.SetIsInDesignMode(childFrameworkElement, this.DesignMode); Vector scale = HostUtils.GetScale(childFrameworkElement); SD.Size maxElementSize = Convert.ToSystemDrawingSize(new Size(childFrameworkElement.MaxWidth, childFrameworkElement.MaxHeight), scale); SD.Size priorMaxSize = HostUtils.ConvertZeroToUnbounded(MaximumSize); int maxWidth = Math.Min(priorMaxSize.Width, maxElementSize.Width); int maxHeight = Math.Min(priorMaxSize.Height, maxElementSize.Height); MaximumSize = HostUtils.ConvertUnboundedToZero(new SD.Size(maxWidth, maxHeight)); } } ////// Raises the VisibleChanged event. /// /// protected override void OnVisibleChanged(EventArgs e) { base.OnVisibleChanged(e); UpdateBackground(); } void CallUpdateBackground(object sender, EventArgs e) { UpdateBackground(); } void UpdateBackground() { OnPropertyChanged("BackgroundImage", BackgroundImage); //Update the background } void childFrameworkElement_SizeChanged(object sender, SizeChangedEventArgs e) { if (AutoSize) { PerformLayout(); } } internal AvalonAdapter HostContainerInternal { get { return _hostContainerInternal; } } #endregion Containership #region Rendering ////// Gets or sets a value indicating whether the hosted element has a transparent background. /// [DefaultValue(false)] public bool BackColorTransparent { get { return _backColorTransparent; } set { _backColorTransparent = value; UpdateBackground(); } } ////// Hide GDI painting because the HwndTarget is going to just bitblt the root /// visual on top of everything. /// [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] protected override void OnPaint(SWF.PaintEventArgs e) { base.OnPaint(e); } ////// Paint our parent's background into an offscreen HBITMAP. /// We then draw this as our background in the hosted Avalon /// control's Render() method to support WinForms->Avalon transparency. /// [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] protected override void OnPaintBackground(SWF.PaintEventArgs pevent) { base.OnPaintBackground(pevent); _decorator.InvalidateVisual(); } internal void InvokePaintBackgroundAndPaint(SWF.Control control, SWF.PaintEventArgs args) { this.InvokePaintBackground(control, args); this.InvokePaint(control, args); } ////// Renders the control using the provided Graphics object. /// /// protected override void OnPrint(PaintEventArgs e) { SWMI.RenderTargetBitmap renderBitmap = HostUtils.GetBitmapForFrameworkElement(_decorator); if (renderBitmap != null) { using (SD.Bitmap bitmap = HostUtils.GetBitmapFromRenderTargetBitmap(this, renderBitmap, new Point(0, 0))) { e.Graphics.DrawImage(bitmap, SD.Point.Empty); } } } #endregion rendering #region Keyboarding ////// Activates the hosted element. /// protected override void Select(bool directed, bool forward) { if (directed == true) { SWI.TraversalRequest request = new SWI.TraversalRequest(forward ? SWI.FocusNavigationDirection.First : SWI.FocusNavigationDirection.Last); //Currently ignore TabInto's return value (_hwndSource as IKeyboardInputSink).TabInto(request); } else { if (Child != null) { Child.Focus(); } } base.Select(directed, forward); } ////// Processes a command key, ensuring that the hosted element has an /// opportunity to handle the command before normal Windows Forms processing. /// ////// This will try see if the pressed key is an Avalon accelerator, if so it returns TRUE, /// which tells WinForms to stop trying to process this key. /// [SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.UnmanagedCode)] protected override bool ProcessCmdKey(ref System.Windows.Forms.Message msg, System.Windows.Forms.Keys keyData) { MSG msg2 = Convert.ToSystemWindowsInteropMSG(msg); SWI.ModifierKeys modifiers = Convert.ToSystemWindowsInputModifierKeys(keyData); if ((_hwndSource as IKeyboardInputSink).TranslateAccelerator(ref msg2, modifiers)) { return true; } return base.ProcessCmdKey(ref msg, keyData); } ////// Processes a mnemonic character, ensuring that the hosted element has an opportunity to handle the mnemonic before /// normal Windows Forms processing. /// ////// This will try see if the pressed key is an Avalon accelerator, if so it tries /// to process the key, which may move focus to the Avalon control. /// [UIPermission(SecurityAction.LinkDemand, Window = UIPermissionWindow.AllWindows)] protected override bool ProcessMnemonic(char charCode) { string upperKey = Char.ToUpper(charCode, CultureInfo.CurrentCulture).ToString(); if (SWI.AccessKeyManager.IsKeyRegistered(_hwndSource, upperKey)) { // ProcessKey doesn't return enough information for us to handle // mnemonic cycling reliably. I.e. we can't tell the difference // between a key which wasn't processed (returns false) from the // case where there is just one element with this key registered // (also returns false). SWI.AccessKeyManager.ProcessKey(_hwndSource, upperKey, false); return true; } else { return base.ProcessMnemonic(charCode); } } ////// Ensures that all WM_CHAR key messages are forwarded to the hosted element. /// ////// Grab all WM_CHAR messages as text input to ensure they're sent to /// Avalon. If Avalon doesn't handle the message, we will call /// ProcessDialogChar later on. /// protected override bool IsInputChar(char charCode) { return true; } ////// Catch WM_CHAR messages which weren't handled by Avalon /// (including mnemonics which were typed without the "Alt" key) /// private void InputManager_PostProcessInput(object sender, SWI.ProcessInputEventArgs e) { IKeyboardInputSink ikis = _hwndSource as IKeyboardInputSink; if (ikis == null || !ikis.HasFocusWithin()) { return; } if (!e.StagingItem.Input.Handled && e.StagingItem.Input.RoutedEvent == SWI.TextCompositionManager.TextInputEvent) { SWI.TextCompositionEventArgs te = (SWI.TextCompositionEventArgs)e.StagingItem.Input; string text = te.Text; if (string.IsNullOrEmpty(text)) { text = te.SystemText; } if (!string.IsNullOrEmpty(text)) { e.StagingItem.Input.Handled = this.ProcessDialogChar(text[0]); } } } ////// Enables a window to receive keyboard messages correctly when it is opened modelessly from Windows Forms. /// /// The System.Windows.Window which will be opened modelessly. [PermissionSet(SecurityAction.Demand, Name = "FullTrust")] public static void EnableModelessKeyboardInterop(SW.Window window) { ApplicationInterop.EnableModelessKeyboardInterop(window); } #endregion Keyboarding #region Window Handling & Misc ////// Raises the HandleCreated event. /// protected override void OnHandleCreated(EventArgs e) { if (_hwndSource != null) { DisposeHWndSource(); } SWF.CreateParams cp = this.CreateParams; HwndSourceParameters HWSParam = new HwndSourceParameters(this.Text, cp.Width, cp.Height); HWSParam.WindowClassStyle = cp.ClassStyle; HWSParam.WindowStyle = cp.Style; HWSParam.ExtendedWindowStyle = cp.ExStyle; HWSParam.ParentWindow = Handle; HWSParam.HwndSourceHook = HwndSourceHook; _hwndSource = new HwndSource(HWSParam); _hwndSource.RootVisual = _decorator; //For keyboarding: Set the IKeyboardInputSite so that keyboard interop works... (_hwndSource as IKeyboardInputSink).KeyboardInputSite = (HostContainerInternal as IKeyboardInputSite); base.OnHandleCreated(e); } ////// Hook for the HwndSource.WndProc. /// private IntPtr HwndSourceHook(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled) { switch (msg) { case NativeMethods.WM_SETFOCUS: if (wParam != Handle) { // wParam != Handle means focus was lost by a window different from this (EH). // The message was sent directly to the HwndSource (by direct mouse input). // We need to notify Winforms so it can set the active control and in turn // notify Control.ActiveXImpl in case we are hosted in an unmanaged app. // EH will set focus back to the WPF control from its OnGotFocus method. this.Focus(); } break; case NativeMethods.WM_KILLFOCUS: if (!this.Focused) { UnsafeNativeMethods.SendMessage(new HandleRef(this, this.Handle), msg, wParam, lParam); } break; case NativeMethods.WM_INPUTLANGCHANGE: OnHwndSrcWmInputLangChange(msg, wParam, lParam, ref handled); break; case NativeMethods.WM_IME_NOTIFY: OnHwndSrcWmImeNotify(msg, wParam, lParam, ref handled); break; } return IntPtr.Zero; // This value depends on the message being processed, see MSDN for the particular message. } private void SetHWndSourceWindowPos() { if (_hwndSource != null) { SafeNativeMethods.SetWindowPos(_hwndSource.Handle, NativeMethods.HWND_TOP, 0, 0, this.Width, this.Height, 0); } } ////// Synchronizes the HwndSource context status to the ElementHost's /// internal bool SyncHwndSrcImeStatus() { Debug.WriteLineIf(HostUtils.ImeMode.Level >= TraceLevel.Info, "Inside SyncHwndSrcImeStatus(), this = " + this); Debug.Indent(); bool handled = false; if (this.HwndSource != null) { ImeMode ehImeMode = this.ImeMode != ImeMode.NoControl ? this.ImeMode : SWF.Control.PropagatingImeMode; ImeMode hsImeMode = SWF.ImeContext.GetImeMode(this.HwndSource.Handle); SetChildElementsIsImeEnabled(this.Child, ehImeMode != ImeMode.Disable); if (ehImeMode != hsImeMode) { SWF.ImeContext.SetImeStatus(ehImeMode, this.HwndSource.Handle); } handled = true; } Debug.Unindent(); return handled; } ////// Maps the ImeMode property. This is needed to synchronize the EH IME context with TFS used in WPF. /// private static void SetChildElementsIsImeEnabled(SW.DependencyObject element, bool isEnabled) { if (element == null) { return; } if (element is SW.IInputElement) { Debug.WriteLineIf(HostUtils.ImeMode.Level >= TraceLevel.Verbose, "SetChildElementsIsImeEnabled, element = " + element); SWI.InputMethod.SetIsInputMethodEnabled(element, isEnabled); } // Ideally, setting the top control context mode should suffice as with any other mapped property on EH // but there is no InputMethodEnabledChanged event for clients to listen to to update child elements. // we need to traverse the visual tree and do it ourselves. int childCount = VisualTreeHelper.GetChildrenCount(element); for (int childIndex = 0; childIndex < childCount; childIndex++) { SetChildElementsIsImeEnabled(VisualTreeHelper.GetChild(element, childIndex), isEnabled); } } ////// Handles HwndSrc WM_INPUTLANGCHANGED. /// private void OnHwndSrcWmInputLangChange(int msg, IntPtr wParam, IntPtr lParam, ref bool handled) { Debug.WriteLineIf(HostUtils.ImeMode.Level >= TraceLevel.Info, "Inside OnHwndSrcWmInputLangChange(), this = " + this); Debug.Indent(); if (!_processingWmInputLangChanged) { _processingWmInputLangChanged = true; try { // IME is being attached, notify the ElementHost to update its handle context, it in turn will pass // the message to the HwndSource to update its context too. OnHwndSourceMsgNotifyElementHost(msg, wParam, lParam); handled = true; } finally { _processingWmInputLangChanged = false; } } Debug.Unindent(); } ////// Handles HwndSrc WM_IME_NOTIFY. /// private void OnHwndSrcWmImeNotify(int msg, IntPtr wParam, IntPtr lParam, ref bool handled) { Debug.WriteLineIf(HostUtils.ImeMode.Level >= TraceLevel.Info, "Inside OnHwndSrcWmImeNotify(), this = " + this); Debug.Indent(); handled = false; if (SWF.ImeModeConversion.IsCurrentConversionTableSupported) // { if (wParam == (IntPtr)NativeMethods.IMN_SETCONVERSIONMODE || wParam == (IntPtr)NativeMethods.IMN_SETOPENSTATUS) { // IME context mode has been changed by interaction or a different IME has been attached, // notify EH to update its ImeMode property if needed. ImeMode hsImeMode = SWF.ImeContext.GetImeMode(this.HwndSource.Handle); ImeMode ehImeMode = this.ImeMode; if (hsImeMode != ehImeMode) { OnHwndSourceMsgNotifyElementHost(msg, wParam, lParam); } handled = true; } } Debug.Unindent(); } ////// Passes a msg sent to the HwndSource into the ElementHost for preprocessing. /// private void OnHwndSourceMsgNotifyElementHost(int msg, IntPtr wParam, IntPtr lParam) { Debug.WriteLineIf(HostUtils.ImeMode.Level >= TraceLevel.Verbose, "Inside OnHwndSourceMsgNotifyElementHost()"); Debug.Indent(); UnsafeNativeMethods.SendMessage(new HandleRef(this, this.Handle), msg, wParam, lParam); Debug.Unindent(); } ////// Processes Windows messages. /// /// [SecurityPermission(SecurityAction.InheritanceDemand, Flags = SecurityPermissionFlag.UnmanagedCode), SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.UnmanagedCode)] protected override void WndProc(ref Message m) { switch (m.Msg) { case NativeMethods.WM_MOVE: case NativeMethods.WM_SIZE: case NativeMethods.WM_WINDOWPOSCHANGED: case NativeMethods.WM_WINDOWPOSCHANGING: base.WndProc(ref m); SetHWndSourceWindowPos(); break; case NativeMethods.WM_PARENTNOTIFY: case NativeMethods.WM_REFLECT + NativeMethods.WM_PARENTNOTIFY: base.WndProc(ref m); if (HostUtils.LOWORD(m.WParam) == NativeMethods.WM_CREATE) { this.BeginInvoke(new MethodInvoker(SetHWndSourceWindowPos)); } break; case NativeMethods.WM_SETREDRAW: if (!DesignMode && m.WParam == IntPtr.Zero) { base.WndProc(ref m); } break; case NativeMethods.WM_KILLFOCUS: // if focus is being set on the HwndSource then we should prevent LostFocus by // handling this message. if (this.HwndSource == null || this.HwndSource.Handle != m.WParam) { base.WndProc(ref m); } break; default: base.WndProc(ref m); break; } } ////// Scales the parent container and the Windows Forms control. /// /// /// protected override void ScaleCore(float dx, float dy) { TransformGroup layoutTransforms = new TransformGroup(); layoutTransforms.Children.Add(_decorator.LayoutTransform); layoutTransforms.Children.Add(new ScaleTransform(dx, dy)); _decorator.LayoutTransform = layoutTransforms; base.ScaleCore(dx, dy); } ///protected override void Dispose(bool disposing) { if (disposing) { try { if (_hostContainerInternal != null) { _hostContainerInternal.Dispose(); _hostContainerInternal = null; } } finally { try { if (_hwndSource != null) { DisposeHWndSource(); } } finally { SWI.InputManager.Current.PostProcessInput -= InputManager_PostProcessInput; IDisposable disposableChild = Child as IDisposable; if (disposableChild != null) { disposableChild.Dispose(); } } } } base.Dispose(disposing); } private void DisposeHWndSource() { //For keyboarding: As per comment in the Avalon code, this is set to null before disposal (_hwndSource as IKeyboardInputSink).KeyboardInputSite = null; _hwndSource.Dispose(); _hwndSource = null; } #endregion Window Handling & Misc #region Property Mapping /// /// This initializes the default property mapping for the element host. /// First: it creates a new PropertyMap to store all the mappings, this /// is exposed to the user as the PropertyMap property. /// Second: it forwards all property Changed events that we want to listen to /// towards the OnPropertyChanged method. /// Third: it registers several default translators, all of which are handled by /// the ElementHostPropertyTranslator deligate. /// private void StartPropertyMapping() { _propertyMap = new ElementHostPropertyMap(this); //This forwards property change notification to OnPropertyChanged, since //there is no generic way to handle listening to property value changes. this.BackColorChanged += this.OnPropertyChangedBackColor; this.BackgroundImageChanged += this.OnPropertyChangedBackgroundImage; this.BackgroundImageLayoutChanged += this.OnPropertyChangedBackgroundImageLayout; this.CursorChanged += this.OnPropertyChangedCursor; this.EnabledChanged += this.OnPropertyChangedEnabled; this.FontChanged += this.OnPropertyChangedFont; this.ForeColorChanged += this.OnPropertyChangedForeColor; this.RightToLeftChanged += this.OnPropertyChangedRightToLeft; this.VisibleChanged += this.OnPropertyChangedVisible; //We forward these property changes, but don't do anything with them. this.AutoSizeChanged += this.OnPropertyChangedAutoSize; this.BindingContextChanged += this.OnPropertyChangedBindingContext; this.CausesValidationChanged += this.OnPropertyChangedCausesValidation; this.ContextMenuChanged += this.OnPropertyChangedContextMenu; this.ContextMenuStripChanged += this.OnPropertyChangedContextMenuStrip; this.DockChanged += this.OnPropertyChangedDock; this.LocationChanged += this.OnPropertyChangedLocation; this.MarginChanged += this.OnPropertyChangedMargin; this.PaddingChanged += this.OnPropertyChangedPadding; this.ParentChanged += this.OnPropertyChangedParent; this.RegionChanged += this.OnPropertyChangedRegion; this.SizeChanged += this.OnPropertyChangedSize; this.TabIndexChanged += this.OnPropertyChangedTabIndex; this.TabStopChanged += this.OnPropertyChangedTabStop; this.TextChanged += this.OnPropertyChangedText; this.ImeModeChanged += this.OnPropertyChangedImeMode; } ////// These delegates just map property changed events to OnPropertyChanged. These are /// necessary in the WinForms model since there is no common path for property change /// notification. (Avalon has an OnPropertyChanged method.) /// private void OnPropertyChangedBackColor(object sender, System.EventArgs e) { OnPropertyChanged("BackColor", this.BackColor); } private void OnPropertyChangedBackgroundImage(object sender, System.EventArgs e) { OnPropertyChanged("BackgroundImage", this.BackgroundImage); } private void OnPropertyChangedBackgroundImageLayout(object sender, System.EventArgs e) { OnPropertyChanged("BackgroundImageLayout", this.BackgroundImageLayout); } private void OnPropertyChangedCursor(object sender, System.EventArgs e) { OnPropertyChanged("Cursor", this.Cursor); } private void OnPropertyChangedEnabled(object sender, System.EventArgs e) { OnPropertyChanged("Enabled", this.Enabled); } private void OnPropertyChangedFont(object sender, System.EventArgs e) { OnPropertyChanged("Font", this.Font); } private void OnPropertyChangedForeColor(object sender, System.EventArgs e) { OnPropertyChanged("ForeColor", this.ForeColor); } private void OnPropertyChangedRightToLeft(object sender, System.EventArgs e) { OnPropertyChanged("RightToLeft", this.RightToLeft); } private void OnPropertyChangedTabStop(object sender, System.EventArgs e) { OnPropertyChanged("TabStop", this.TabStop); } private void OnPropertyChangedVisible(object sender, System.EventArgs e) { OnPropertyChanged("Visible", this.Visible); } // These properties don't have default mappings, but are added in case anyone wants to add them private void OnPropertyChangedAutoSize(object sender, System.EventArgs e) { OnPropertyChanged("AutoSize", this.AutoSize); } private void OnPropertyChangedPadding(object sender, System.EventArgs e) { OnPropertyChanged("Padding", this.Padding); } private void OnPropertyChangedBindingContext(object sender, System.EventArgs e) { OnPropertyChanged("BindingContext", this.BindingContext); } private void OnPropertyChangedCausesValidation(object sender, System.EventArgs e) { OnPropertyChanged("CausesValidation", this.CausesValidation); } private void OnPropertyChangedContextMenu(object sender, System.EventArgs e) { OnPropertyChanged("ContextMenu", this.ContextMenu); } private void OnPropertyChangedContextMenuStrip(object sender, System.EventArgs e) { OnPropertyChanged("ContextMenuStrip", this.ContextMenuStrip); } private void OnPropertyChangedDock(object sender, System.EventArgs e) { OnPropertyChanged("Dock", this.Dock); } private void OnPropertyChangedLocation(object sender, System.EventArgs e) { OnPropertyChanged("Location", this.Location); } private void OnPropertyChangedMargin(object sender, System.EventArgs e) { OnPropertyChanged("Margin", this.Margin); } private void OnPropertyChangedParent(object sender, System.EventArgs e) { OnPropertyChanged("Parent", this.Parent); } private void OnPropertyChangedRegion(object sender, System.EventArgs e) { OnPropertyChanged("Region", this.Region); } private void OnPropertyChangedSize(object sender, System.EventArgs e) { OnPropertyChanged("Size", this.Size); } private void OnPropertyChangedTabIndex(object sender, System.EventArgs e) { OnPropertyChanged("TabIndex", this.TabIndex); } private void OnPropertyChangedText(object sender, System.EventArgs e) { OnPropertyChanged("Text", this.Text); } private void OnPropertyChangedImeMode(object sender, System.EventArgs e) { OnPropertyChanged("ImeMode", this.ImeMode); } ////// Notifies the property map that a property has changed. /// /// the name of the property which has changed and requires translation /// the new value of the property ////// Putting an InheritanceDemand as a defense-in-depth measure, /// as this provides a hook to the property system that we don't /// want exposed under PartialTrust. /// [UIPermissionAttribute(SecurityAction.InheritanceDemand, Window = UIPermissionWindow.AllWindows)] public virtual void OnPropertyChanged(string propertyName, object value) { if (PropertyMap != null) { PropertyMap.OnPropertyChanged(this, propertyName, value); } } ////// Gets the property map, which determines how setting properties on the /// ElementHost control affects the hosted Windows Presentation Foundation element. /// [Browsable(false)] public PropertyMap PropertyMap { get { return _propertyMap; } } private ElementHostPropertyMap _propertyMap; #endregion Property Mapping #region Hidden Events ////// Occurs when the value of the BindingContext property changes. /// [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] public new event EventHandler BindingContextChanged { add { base.BindingContextChanged += value; } remove { base.BindingContextChanged -= value; } } ////// Occurs when the control is clicked. /// [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] public new event EventHandler Click { add { base.Click += value; } remove { base.Click -= value; } } ////// Occurs when the value of the ClientSize property changes. /// [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] public new event EventHandler ClientSizeChanged { add { base.ClientSizeChanged += value; } remove { base.ClientSizeChanged -= value; } } ////// Occurs when a new control is added to the Control.ControlCollection. /// [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] public new event ControlEventHandler ControlAdded { add { base.ControlAdded += value; } remove { base.ControlAdded -= value; } } ////// Occurs when a control is removed from the Control.ControlCollection. /// [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] public new event ControlEventHandler ControlRemoved { add { base.ControlRemoved += value; } remove { base.ControlRemoved -= value; } } ////// Occurs when the value of the Cursor property changes. /// [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] public new event EventHandler CursorChanged { add { base.CursorChanged += value; } remove { base.CursorChanged -= value; } } ////// Occurs when the control is double-clicked. /// [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] public new event EventHandler DoubleClick { add { base.DoubleClick += value; } remove { base.DoubleClick -= value; } } ////// Occurs when a drag-and-drop operation is completed. /// [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] public new event DragEventHandler DragDrop { add { base.DragDrop += value; } remove { base.DragDrop -= value; } } ////// Occurs when an object is dragged into the control's bounds. /// [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] public new event DragEventHandler DragEnter { add { base.DragEnter += value; } remove { base.DragEnter -= value; } } ////// Occurs when an object is dragged out of the control's bounds. /// [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] public new event EventHandler DragLeave { add { base.DragLeave += value; } remove { base.DragLeave -= value; } } ////// Occurs when an object is dragged over the control's bounds. /// [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] public new event DragEventHandler DragOver { add { base.DragOver += value; } remove { base.DragOver -= value; } } ////// Occurs when the control is entered. /// [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] public new event EventHandler Enter { add { base.Enter += value; } remove { base.Enter -= value; } } ////// Occurs when the Font property value changes. /// [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] public new event EventHandler FontChanged { add { base.FontChanged += value; } remove { base.FontChanged -= value; } } ////// Occurs when the ForeColor property value changes. /// [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] public new event EventHandler ForeColorChanged { add { base.ForeColorChanged += value; } remove { base.ForeColorChanged -= value; } } ////// Occurs during a drag operation. /// [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] public new event GiveFeedbackEventHandler GiveFeedback { add { base.GiveFeedback += value; } remove { base.GiveFeedback -= value; } } ////// Occurs when the control receives focus. /// [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] public new event EventHandler GotFocus { add { base.GotFocus += value; } remove { base.GotFocus -= value; } } ////// Occurs when a control's display requires redrawing. /// [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] public new event InvalidateEventHandler Invalidated { add { base.Invalidated += value; } remove { base.Invalidated -= value; } } ////// Occurs when a key is pressed while the control has focus. /// [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] public new event KeyEventHandler KeyDown { add { base.KeyDown += value; } remove { base.KeyDown -= value; } } ////// Occurs when a key is pressed while the control has focus. /// [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] public new event KeyPressEventHandler KeyPress { add { base.KeyPress += value; } remove { base.KeyPress -= value; } } ////// Occurs when a key is released while the control has focus. /// [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] public new event KeyEventHandler KeyUp { add { base.KeyUp += value; } remove { base.KeyUp -= value; } } ////// Occurs when a control should reposition its child controls. /// [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] public new event LayoutEventHandler Layout { add { base.Layout += value; } remove { base.Layout -= value; } } ////// Occurs when the input focus leaves the control. /// [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] public new event EventHandler Leave { add { base.Leave += value; } remove { base.Leave -= value; } } ////// Occurs when the control loses focus. /// [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] public new event EventHandler LostFocus { add { base.LostFocus += value; } remove { base.LostFocus -= value; } } ////// Occurs when the control loses mouse capture. /// [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] public new event EventHandler MouseCaptureChanged { add { base.MouseCaptureChanged += value; } remove { base.MouseCaptureChanged -= value; } } ////// Occurs when the control is clicked by the mouse. /// [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] public new event MouseEventHandler MouseClick { add { base.MouseClick += value; } remove { base.MouseClick -= value; } } ////// Occurs when the control is double clicked by the mouse. /// [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] public new event MouseEventHandler MouseDoubleClick { add { base.MouseDoubleClick += value; } remove { base.MouseDoubleClick -= value; } } ////// Occurs when the mouse pointer is over the control and a mouse button is pressed. /// [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] public new event MouseEventHandler MouseDown { add { base.MouseDown += value; } remove { base.MouseDown -= value; } } ////// Occurs when the mouse pointer enters the control. /// [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] public new event EventHandler MouseEnter { add { base.MouseEnter += value; } remove { base.MouseEnter -= value; } } ////// Occurs when the mouse pointer rests on the control. /// [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] public new event EventHandler MouseHover { add { base.MouseHover += value; } remove { base.MouseHover -= value; } } ////// Occurs when the mouse pointer leaves the control. ( /// [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] public new event EventHandler MouseLeave { add { base.MouseLeave += value; } remove { base.MouseLeave -= value; } } ////// Occurs when the mouse pointer is moved over the control. /// [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] public new event MouseEventHandler MouseMove { add { base.MouseMove += value; } remove { base.MouseMove -= value; } } ////// Occurs when the mouse pointer is over the control and a mouse button is released. /// [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] public new event MouseEventHandler MouseUp { add { base.MouseUp += value; } remove { base.MouseUp -= value; } } ////// Occurs when the mouse wheel moves while the control has focus. /// [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] public new event MouseEventHandler MouseWheel { add { base.MouseWheel += value; } remove { base.MouseWheel -= value; } } ////// Occurs when the control's padding changes. /// [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] public new event EventHandler PaddingChanged { add { base.PaddingChanged += value; } remove { base.PaddingChanged -= value; } } ////// Occurs when the control is redrawn. /// [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] public new event PaintEventHandler Paint { add { base.Paint += value; } remove { base.Paint -= value; } } ////// Occurs before the KeyDown event when a key is pressed while focus is on this control. /// [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] public new event PreviewKeyDownEventHandler PreviewKeyDown { add { base.PreviewKeyDown += value; } remove { base.PreviewKeyDown -= value; } } ////// Occurs during a drag-and-drop operation and enables the drag source to determine /// whether the drag-and-drop operation should be canceled. /// [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] public new event QueryContinueDragEventHandler QueryContinueDrag { add { base.QueryContinueDrag += value; } remove { base.QueryContinueDrag -= value; } } ////// Occurs when the control is resized. /// [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] public new event EventHandler Resize { add { base.Resize += value; } remove { base.Resize -= value; } } ////// Occurs when the RightToLeft property value changes. /// [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] public new event EventHandler RightToLeftChanged { add { base.RightToLeftChanged += value; } remove { base.RightToLeftChanged -= value; } } ////// Occurs when the Size property value changes. /// [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] public new event EventHandler SizeChanged { add { base.SizeChanged += value; } remove { base.SizeChanged -= value; } } ////// Occurs when the Text property value changes. /// [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] public new event EventHandler TextChanged { add { base.TextChanged += value; } remove { base.TextChanged -= value; } } #endregion #region DEBUG #if DEBUG private static readonly TraceSwitch _traceLayout = new TraceSwitch("ElementHostLayout", "Tracks ElementHost layout information."); #else private static readonly TraceSwitch _traceLayout = null; #endif #endregion DEBUG } #region AvalonAdapter internal class AvalonAdapter : SWC.DockPanel, IDisposable, IKeyboardInputSite { private ElementHost _hostControl; [SuppressMessage("Microsoft.Performance", "CA1810:InitializeReferenceTypeStaticFieldsInline")] static AvalonAdapter() { //These properties define how tabbing occurs in the DockPanel. To be most like //WinForms these are set to use Continue mode as the default. // SWI.KeyboardNavigation.DirectionalNavigationProperty.OverrideMetadata( typeof(AvalonAdapter), new FrameworkPropertyMetadata(SWI.KeyboardNavigationMode.Continue)); SWI.KeyboardNavigation.TabNavigationProperty.OverrideMetadata( typeof(AvalonAdapter), new FrameworkPropertyMetadata(SWI.KeyboardNavigationMode.Continue)); } ////// Creates the Avalon control we use to host /// other WinForms control in Avalon. /// public AvalonAdapter(ElementHost hostControl) { _hostControl = hostControl; } ////// unsink our events /// public void Dispose() { _hostControl = null; } // used to force invalidation of the avalon control's client area. public static readonly DependencyProperty ForceInvalidateProperty = DependencyProperty.Register( "ForceInvalidate", typeof(bool), typeof(AvalonAdapter), new FrameworkPropertyMetadata( false, FrameworkPropertyMetadataOptions.AffectsRender)); private static object OnGetForceInvalidate(DependencyObject d) { return ((AvalonAdapter)d).ForceInvalidate; } ////// This property is toggled by ElementHost to force the hosted /// Avalon control to redraw itself /// public bool ForceInvalidate { get { return (bool)GetValue(ForceInvalidateProperty); } set { SetValue(ForceInvalidateProperty, value); } } ////// This is a transparency optimization. It looks up the SWF visual heirarchy to /// find the first opaque control. It then uses this color as the background for /// OnRender. This doesn't work all the time, but is much faster than the bitmap /// conversion. /// /// The current control ///The first opaque color found, or Color.Empty if none is found private static SD.Color FindSolidColorParent(Control whichControl) { Control control = whichControl; while (control.Parent != null) { control = control.Parent; if (control.BackColor != SD.Color.Empty && control.BackColor.A == 255) { return control.BackColor; } } return SD.Color.Empty; } #region IKeyboardInputSite public void Unregister() { } public bool OnNoMoreTabStops(SWI.TraversalRequest request) { //Tabbing out of hosted elements //Select the next control bool forward = true; Debug.Assert(request != null, "request was null!"); if (request != null) { switch (request.FocusNavigationDirection) { case System.Windows.Input.FocusNavigationDirection.Down: case System.Windows.Input.FocusNavigationDirection.Right: case System.Windows.Input.FocusNavigationDirection.Next: forward = true; break; case System.Windows.Input.FocusNavigationDirection.Up: case System.Windows.Input.FocusNavigationDirection.Left: case System.Windows.Input.FocusNavigationDirection.Previous: forward = false; break; case System.Windows.Input.FocusNavigationDirection.First: case System.Windows.Input.FocusNavigationDirection.Last: break; default: Debug.Assert(false, "Unknown FocusNavigationDirection"); break; } } if (_hostControl != null) { // Get _hostControl's top-most parent. Control topMostParent = _hostControl; while (topMostParent.Parent != null) { topMostParent = topMostParent.Parent; } return topMostParent.SelectNextControl(_hostControl, forward, true, true, true); } return false; } public IKeyboardInputSink Sink { get { return (_hostControl.HwndSource as IKeyboardInputSink); } } #endregion IKeyboardInputSite protected override System.Windows.Automation.Peers.AutomationPeer OnCreateAutomationPeer() { return new ElementHostAutomationPeer(this); } } #endregion AvalonAdapter } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. // Copyright (c) Microsoft Corporation. All rights reserved. using System.Collections.Generic; using System.ComponentModel; using System.ComponentModel.Design.Serialization; using System.Diagnostics; using System.Runtime.InteropServices; using System.Diagnostics.CodeAnalysis; using System.Globalization; using System.Windows.Documents; using System.Windows.Interop; using System.Windows.Markup; using System.Windows.Media; using System.Security.Permissions; using MS.Win32; using SD = System.Drawing; using SWF = System.Windows.Forms; using SW = System.Windows; using SWC = System.Windows.Controls; using SWM = System.Windows.Media; using SWMI = System.Windows.Media.Imaging; using SWI = System.Windows.Input; namespace System.Windows.Forms.Integration { ////// A Windows Forms control that can be used to host a Windows Presentation /// Foundation element. /// [System.ComponentModel.DesignerCategory("code")] [ContentProperty("Child")] [DefaultEvent("ChildChanged")] [Designer("WindowsFormsIntegration.Design.ElementHostDesigner, WindowsFormsIntegration.Design, Version=1.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")] [DesignerSerializer("WindowsFormsIntegration.Design.ElementHostCodeDomSerializer, WindowsFormsIntegration.Design, Version=1.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a", "System.ComponentModel.Design.Serialization.CodeDomSerializer, System.Design, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")] public class ElementHost : Control { private HwndSource _hwndSource; ////// The decorator is used to provide an Adorner layer which is needed to show UI highlights /// for focus etc. In the pure-Avalon case, this would be handled by Window /// private AdornerDecorator _decorator; private AvalonAdapter _hostContainerInternal; private bool _backColorTransparent; private SW.UIElement _child; private bool _processingWmInputLangChanged; // Flag to prevent re-entrancy when processing WM_INPUTLANGCHANGED #region Constructors ////// Initializes a new instance of the ElementHost class. /// ////// Overridden to plug the Avalon control into WinForm's layout engines. /// [PermissionSet(SecurityAction.Demand, Name = "FullTrust")] public ElementHost() : base() { this._hostContainerInternal = new AvalonAdapter(this); this._decorator = new AdornerDecorator(); _decorator.Child = this._hostContainerInternal; SetStyle(SWF.ControlStyles.SupportsTransparentBackColor, true); SetStyle(SWF.ControlStyles.UserPaint, true); SetStyle(SWF.ControlStyles.AllPaintingInWmPaint, true); System.Windows.Input.FocusManager.SetIsFocusScope(this._decorator, true); //For keyboarding, this listens for WM_CHAR events not handled, so that mnemonics //that are pressed without the ALT key can be handled. SWI.InputManager.Current.PostProcessInput += InputManager_PostProcessInput; this.SetAutoSizeMode(AutoSizeMode.GrowAndShrink); StartPropertyMapping(); SizeChanged += new EventHandler(CallUpdateBackground); LocationChanged += new EventHandler(CallUpdateBackground); } #endregion #region Layout ////// Overrides the base class implementation of GetPreferredSize to provide /// correct layout behavior for the hosted Windows Presentation Foundation elements. /// public override SD.Size GetPreferredSize(SD.Size proposedSize) { if (Disposing) { return base.GetPreferredSize(proposedSize); } proposedSize = HostUtils.IntersectSizes(HostUtils.ConvertZeroOrOneToUnbounded(proposedSize), HostUtils.ConvertZeroToUnbounded(MaximumSize)); proposedSize = HostUtils.UnionSizes(proposedSize, MinimumSize); // Apply the child's scaling, if any Vector scale = (Child == null ? new Vector(1d, 1d) : HostUtils.GetScale(Child)); Size constraints = Convert.ToSystemWindowsSize(proposedSize, scale); // At this point, an unbounded value is represented by Int32.MaxValue: WPF wants double.PositiveInfinity. if (constraints.Width == Int32.MaxValue) { constraints.Width = Double.PositiveInfinity; } if (constraints.Height == Int32.MaxValue) { constraints.Height = Double.PositiveInfinity; } // Request that control recompute desired size with new constraints. _decorator.Measure(constraints); SD.Size prefSize = Convert.ToSystemDrawingSize(_decorator.DesiredSize, scale); // WindowsForms guarantees results will be bounded by control Min/MaxSize prefSize = HostUtils.IntersectSizes(prefSize, HostUtils.ConvertZeroToUnbounded(MaximumSize)); prefSize = HostUtils.UnionSizes(prefSize, MinimumSize); Debug.WriteLineIf(_traceLayout.TraceInfo, String.Format(CultureInfo.CurrentCulture, "AvalonAdapter({0}): MeasureOverride (constraint={1},result={2})", this.Name, proposedSize, prefSize)); return prefSize; } ////// Gets the default size of the control. /// protected override System.Drawing.Size DefaultSize { get { return new SD.Size(200, 100); } } ////// Gets or sets a value indicating whether the control is /// automatically resized to display its entire contents. /// [Browsable(true), EditorBrowsable(EditorBrowsableState.Always)] public override bool AutoSize { get { return base.AutoSize; } set { base.AutoSize = value; } } #endregion Layout #region Containership ////// Gets the parent container of the hosted Windows Presentation Foundation element. /// [Browsable(false)] [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public SWC.Panel HostContainer { get { return HostContainerInternal; } } internal HwndSource HwndSource { get { return _hwndSource; } } ////// Indicates that the Child property has been changed. /// public event EventHandlerChildChanged; /// /// Gets or sets the UIElement hosted by the ElementHost control. /// [Browsable(false)] [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public SW.UIElement Child { get { return _child; } set { UIElement oldValue = Child; #pragma warning disable 1634, 1691 #pragma warning disable 56526 _child = value; #pragma warning restore 1634, 1691, 56526 HostContainerInternal.Children.Clear(); if (_child != null) { HostContainerInternal.Children.Add(_child); _propertyMap.ApplyAll(); InitializeChildProperties(); } OnChildChanged(oldValue); } } protected override bool CanEnableIme { get { if (this.Child == null) { return false; } return base.CanEnableIme; } } ////// If focus on HwndSource, we need to return true here. /// public override bool Focused { get { if( IsHandleCreated ) { // observe that the EH.Child may be null and still it has an HwndSource. IntPtr focusHandle = UnsafeNativeMethods.GetFocus(); return (focusHandle == this.Handle || (this.HwndSource != null && focusHandle == this.HwndSource.Handle)); } return false; } } protected override SWF.ImeMode ImeModeBase { get { return this.CanEnableIme ? base.ImeModeBase : ImeMode.Disable; } set { base.ImeModeBase = value; // When the ImeMode is set to ImeMode.NoControl, Winforms stops raising the ImeModeChanged event // on the control, we need to notify the property mapper explicitly. if (value == SWF.ImeMode.NoControl) { this.OnPropertyChangedImeMode(this, EventArgs.Empty); } } } private void OnChildChanged(UIElement oldChild) { if (this.Child != null) { SyncHwndSrcImeStatus(); } if (ChildChanged != null) { ChildChanged(this, new ChildChangedEventArgs(oldChild)); } } ////// Raises the Leave event. /// /// protected override void OnLeave(EventArgs e) { System.Windows.Input.FocusManager.SetFocusedElement(_decorator, null); base.OnLeave(e); } ////// Raises the GotFocus event. /// /// protected override void OnGotFocus(EventArgs e) { base.OnGotFocus(e); SyncHwndSrcImeStatus(); _decorator.Focus(); } private void InitializeChildProperties() { FrameworkElement childFrameworkElement = Child as FrameworkElement; if (childFrameworkElement != null) { childFrameworkElement.SizeChanged += new SizeChangedEventHandler(childFrameworkElement_SizeChanged); childFrameworkElement.Height = double.NaN; childFrameworkElement.Width = double.NaN; childFrameworkElement.Margin = new Thickness(0d); childFrameworkElement.VerticalAlignment = SW.VerticalAlignment.Stretch; childFrameworkElement.HorizontalAlignment = SW.HorizontalAlignment.Stretch; DesignerProperties.SetIsInDesignMode(childFrameworkElement, this.DesignMode); Vector scale = HostUtils.GetScale(childFrameworkElement); SD.Size maxElementSize = Convert.ToSystemDrawingSize(new Size(childFrameworkElement.MaxWidth, childFrameworkElement.MaxHeight), scale); SD.Size priorMaxSize = HostUtils.ConvertZeroToUnbounded(MaximumSize); int maxWidth = Math.Min(priorMaxSize.Width, maxElementSize.Width); int maxHeight = Math.Min(priorMaxSize.Height, maxElementSize.Height); MaximumSize = HostUtils.ConvertUnboundedToZero(new SD.Size(maxWidth, maxHeight)); } } ////// Raises the VisibleChanged event. /// /// protected override void OnVisibleChanged(EventArgs e) { base.OnVisibleChanged(e); UpdateBackground(); } void CallUpdateBackground(object sender, EventArgs e) { UpdateBackground(); } void UpdateBackground() { OnPropertyChanged("BackgroundImage", BackgroundImage); //Update the background } void childFrameworkElement_SizeChanged(object sender, SizeChangedEventArgs e) { if (AutoSize) { PerformLayout(); } } internal AvalonAdapter HostContainerInternal { get { return _hostContainerInternal; } } #endregion Containership #region Rendering ////// Gets or sets a value indicating whether the hosted element has a transparent background. /// [DefaultValue(false)] public bool BackColorTransparent { get { return _backColorTransparent; } set { _backColorTransparent = value; UpdateBackground(); } } ////// Hide GDI painting because the HwndTarget is going to just bitblt the root /// visual on top of everything. /// [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] protected override void OnPaint(SWF.PaintEventArgs e) { base.OnPaint(e); } ////// Paint our parent's background into an offscreen HBITMAP. /// We then draw this as our background in the hosted Avalon /// control's Render() method to support WinForms->Avalon transparency. /// [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] protected override void OnPaintBackground(SWF.PaintEventArgs pevent) { base.OnPaintBackground(pevent); _decorator.InvalidateVisual(); } internal void InvokePaintBackgroundAndPaint(SWF.Control control, SWF.PaintEventArgs args) { this.InvokePaintBackground(control, args); this.InvokePaint(control, args); } ////// Renders the control using the provided Graphics object. /// /// protected override void OnPrint(PaintEventArgs e) { SWMI.RenderTargetBitmap renderBitmap = HostUtils.GetBitmapForFrameworkElement(_decorator); if (renderBitmap != null) { using (SD.Bitmap bitmap = HostUtils.GetBitmapFromRenderTargetBitmap(this, renderBitmap, new Point(0, 0))) { e.Graphics.DrawImage(bitmap, SD.Point.Empty); } } } #endregion rendering #region Keyboarding ////// Activates the hosted element. /// protected override void Select(bool directed, bool forward) { if (directed == true) { SWI.TraversalRequest request = new SWI.TraversalRequest(forward ? SWI.FocusNavigationDirection.First : SWI.FocusNavigationDirection.Last); //Currently ignore TabInto's return value (_hwndSource as IKeyboardInputSink).TabInto(request); } else { if (Child != null) { Child.Focus(); } } base.Select(directed, forward); } ////// Processes a command key, ensuring that the hosted element has an /// opportunity to handle the command before normal Windows Forms processing. /// ////// This will try see if the pressed key is an Avalon accelerator, if so it returns TRUE, /// which tells WinForms to stop trying to process this key. /// [SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.UnmanagedCode)] protected override bool ProcessCmdKey(ref System.Windows.Forms.Message msg, System.Windows.Forms.Keys keyData) { MSG msg2 = Convert.ToSystemWindowsInteropMSG(msg); SWI.ModifierKeys modifiers = Convert.ToSystemWindowsInputModifierKeys(keyData); if ((_hwndSource as IKeyboardInputSink).TranslateAccelerator(ref msg2, modifiers)) { return true; } return base.ProcessCmdKey(ref msg, keyData); } ////// Processes a mnemonic character, ensuring that the hosted element has an opportunity to handle the mnemonic before /// normal Windows Forms processing. /// ////// This will try see if the pressed key is an Avalon accelerator, if so it tries /// to process the key, which may move focus to the Avalon control. /// [UIPermission(SecurityAction.LinkDemand, Window = UIPermissionWindow.AllWindows)] protected override bool ProcessMnemonic(char charCode) { string upperKey = Char.ToUpper(charCode, CultureInfo.CurrentCulture).ToString(); if (SWI.AccessKeyManager.IsKeyRegistered(_hwndSource, upperKey)) { // ProcessKey doesn't return enough information for us to handle // mnemonic cycling reliably. I.e. we can't tell the difference // between a key which wasn't processed (returns false) from the // case where there is just one element with this key registered // (also returns false). SWI.AccessKeyManager.ProcessKey(_hwndSource, upperKey, false); return true; } else { return base.ProcessMnemonic(charCode); } } ////// Ensures that all WM_CHAR key messages are forwarded to the hosted element. /// ////// Grab all WM_CHAR messages as text input to ensure they're sent to /// Avalon. If Avalon doesn't handle the message, we will call /// ProcessDialogChar later on. /// protected override bool IsInputChar(char charCode) { return true; } ////// Catch WM_CHAR messages which weren't handled by Avalon /// (including mnemonics which were typed without the "Alt" key) /// private void InputManager_PostProcessInput(object sender, SWI.ProcessInputEventArgs e) { IKeyboardInputSink ikis = _hwndSource as IKeyboardInputSink; if (ikis == null || !ikis.HasFocusWithin()) { return; } if (!e.StagingItem.Input.Handled && e.StagingItem.Input.RoutedEvent == SWI.TextCompositionManager.TextInputEvent) { SWI.TextCompositionEventArgs te = (SWI.TextCompositionEventArgs)e.StagingItem.Input; string text = te.Text; if (string.IsNullOrEmpty(text)) { text = te.SystemText; } if (!string.IsNullOrEmpty(text)) { e.StagingItem.Input.Handled = this.ProcessDialogChar(text[0]); } } } ////// Enables a window to receive keyboard messages correctly when it is opened modelessly from Windows Forms. /// /// The System.Windows.Window which will be opened modelessly. [PermissionSet(SecurityAction.Demand, Name = "FullTrust")] public static void EnableModelessKeyboardInterop(SW.Window window) { ApplicationInterop.EnableModelessKeyboardInterop(window); } #endregion Keyboarding #region Window Handling & Misc ////// Raises the HandleCreated event. /// protected override void OnHandleCreated(EventArgs e) { if (_hwndSource != null) { DisposeHWndSource(); } SWF.CreateParams cp = this.CreateParams; HwndSourceParameters HWSParam = new HwndSourceParameters(this.Text, cp.Width, cp.Height); HWSParam.WindowClassStyle = cp.ClassStyle; HWSParam.WindowStyle = cp.Style; HWSParam.ExtendedWindowStyle = cp.ExStyle; HWSParam.ParentWindow = Handle; HWSParam.HwndSourceHook = HwndSourceHook; _hwndSource = new HwndSource(HWSParam); _hwndSource.RootVisual = _decorator; //For keyboarding: Set the IKeyboardInputSite so that keyboard interop works... (_hwndSource as IKeyboardInputSink).KeyboardInputSite = (HostContainerInternal as IKeyboardInputSite); base.OnHandleCreated(e); } ////// Hook for the HwndSource.WndProc. /// private IntPtr HwndSourceHook(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled) { switch (msg) { case NativeMethods.WM_SETFOCUS: if (wParam != Handle) { // wParam != Handle means focus was lost by a window different from this (EH). // The message was sent directly to the HwndSource (by direct mouse input). // We need to notify Winforms so it can set the active control and in turn // notify Control.ActiveXImpl in case we are hosted in an unmanaged app. // EH will set focus back to the WPF control from its OnGotFocus method. this.Focus(); } break; case NativeMethods.WM_KILLFOCUS: if (!this.Focused) { UnsafeNativeMethods.SendMessage(new HandleRef(this, this.Handle), msg, wParam, lParam); } break; case NativeMethods.WM_INPUTLANGCHANGE: OnHwndSrcWmInputLangChange(msg, wParam, lParam, ref handled); break; case NativeMethods.WM_IME_NOTIFY: OnHwndSrcWmImeNotify(msg, wParam, lParam, ref handled); break; } return IntPtr.Zero; // This value depends on the message being processed, see MSDN for the particular message. } private void SetHWndSourceWindowPos() { if (_hwndSource != null) { SafeNativeMethods.SetWindowPos(_hwndSource.Handle, NativeMethods.HWND_TOP, 0, 0, this.Width, this.Height, 0); } } ////// Synchronizes the HwndSource context status to the ElementHost's /// internal bool SyncHwndSrcImeStatus() { Debug.WriteLineIf(HostUtils.ImeMode.Level >= TraceLevel.Info, "Inside SyncHwndSrcImeStatus(), this = " + this); Debug.Indent(); bool handled = false; if (this.HwndSource != null) { ImeMode ehImeMode = this.ImeMode != ImeMode.NoControl ? this.ImeMode : SWF.Control.PropagatingImeMode; ImeMode hsImeMode = SWF.ImeContext.GetImeMode(this.HwndSource.Handle); SetChildElementsIsImeEnabled(this.Child, ehImeMode != ImeMode.Disable); if (ehImeMode != hsImeMode) { SWF.ImeContext.SetImeStatus(ehImeMode, this.HwndSource.Handle); } handled = true; } Debug.Unindent(); return handled; } ////// Maps the ImeMode property. This is needed to synchronize the EH IME context with TFS used in WPF. /// private static void SetChildElementsIsImeEnabled(SW.DependencyObject element, bool isEnabled) { if (element == null) { return; } if (element is SW.IInputElement) { Debug.WriteLineIf(HostUtils.ImeMode.Level >= TraceLevel.Verbose, "SetChildElementsIsImeEnabled, element = " + element); SWI.InputMethod.SetIsInputMethodEnabled(element, isEnabled); } // Ideally, setting the top control context mode should suffice as with any other mapped property on EH // but there is no InputMethodEnabledChanged event for clients to listen to to update child elements. // we need to traverse the visual tree and do it ourselves. int childCount = VisualTreeHelper.GetChildrenCount(element); for (int childIndex = 0; childIndex < childCount; childIndex++) { SetChildElementsIsImeEnabled(VisualTreeHelper.GetChild(element, childIndex), isEnabled); } } ////// Handles HwndSrc WM_INPUTLANGCHANGED. /// private void OnHwndSrcWmInputLangChange(int msg, IntPtr wParam, IntPtr lParam, ref bool handled) { Debug.WriteLineIf(HostUtils.ImeMode.Level >= TraceLevel.Info, "Inside OnHwndSrcWmInputLangChange(), this = " + this); Debug.Indent(); if (!_processingWmInputLangChanged) { _processingWmInputLangChanged = true; try { // IME is being attached, notify the ElementHost to update its handle context, it in turn will pass // the message to the HwndSource to update its context too. OnHwndSourceMsgNotifyElementHost(msg, wParam, lParam); handled = true; } finally { _processingWmInputLangChanged = false; } } Debug.Unindent(); } ////// Handles HwndSrc WM_IME_NOTIFY. /// private void OnHwndSrcWmImeNotify(int msg, IntPtr wParam, IntPtr lParam, ref bool handled) { Debug.WriteLineIf(HostUtils.ImeMode.Level >= TraceLevel.Info, "Inside OnHwndSrcWmImeNotify(), this = " + this); Debug.Indent(); handled = false; if (SWF.ImeModeConversion.IsCurrentConversionTableSupported) // { if (wParam == (IntPtr)NativeMethods.IMN_SETCONVERSIONMODE || wParam == (IntPtr)NativeMethods.IMN_SETOPENSTATUS) { // IME context mode has been changed by interaction or a different IME has been attached, // notify EH to update its ImeMode property if needed. ImeMode hsImeMode = SWF.ImeContext.GetImeMode(this.HwndSource.Handle); ImeMode ehImeMode = this.ImeMode; if (hsImeMode != ehImeMode) { OnHwndSourceMsgNotifyElementHost(msg, wParam, lParam); } handled = true; } } Debug.Unindent(); } ////// Passes a msg sent to the HwndSource into the ElementHost for preprocessing. /// private void OnHwndSourceMsgNotifyElementHost(int msg, IntPtr wParam, IntPtr lParam) { Debug.WriteLineIf(HostUtils.ImeMode.Level >= TraceLevel.Verbose, "Inside OnHwndSourceMsgNotifyElementHost()"); Debug.Indent(); UnsafeNativeMethods.SendMessage(new HandleRef(this, this.Handle), msg, wParam, lParam); Debug.Unindent(); } ////// Processes Windows messages. /// /// [SecurityPermission(SecurityAction.InheritanceDemand, Flags = SecurityPermissionFlag.UnmanagedCode), SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.UnmanagedCode)] protected override void WndProc(ref Message m) { switch (m.Msg) { case NativeMethods.WM_MOVE: case NativeMethods.WM_SIZE: case NativeMethods.WM_WINDOWPOSCHANGED: case NativeMethods.WM_WINDOWPOSCHANGING: base.WndProc(ref m); SetHWndSourceWindowPos(); break; case NativeMethods.WM_PARENTNOTIFY: case NativeMethods.WM_REFLECT + NativeMethods.WM_PARENTNOTIFY: base.WndProc(ref m); if (HostUtils.LOWORD(m.WParam) == NativeMethods.WM_CREATE) { this.BeginInvoke(new MethodInvoker(SetHWndSourceWindowPos)); } break; case NativeMethods.WM_SETREDRAW: if (!DesignMode && m.WParam == IntPtr.Zero) { base.WndProc(ref m); } break; case NativeMethods.WM_KILLFOCUS: // if focus is being set on the HwndSource then we should prevent LostFocus by // handling this message. if (this.HwndSource == null || this.HwndSource.Handle != m.WParam) { base.WndProc(ref m); } break; default: base.WndProc(ref m); break; } } ////// Scales the parent container and the Windows Forms control. /// /// /// protected override void ScaleCore(float dx, float dy) { TransformGroup layoutTransforms = new TransformGroup(); layoutTransforms.Children.Add(_decorator.LayoutTransform); layoutTransforms.Children.Add(new ScaleTransform(dx, dy)); _decorator.LayoutTransform = layoutTransforms; base.ScaleCore(dx, dy); } ///protected override void Dispose(bool disposing) { if (disposing) { try { if (_hostContainerInternal != null) { _hostContainerInternal.Dispose(); _hostContainerInternal = null; } } finally { try { if (_hwndSource != null) { DisposeHWndSource(); } } finally { SWI.InputManager.Current.PostProcessInput -= InputManager_PostProcessInput; IDisposable disposableChild = Child as IDisposable; if (disposableChild != null) { disposableChild.Dispose(); } } } } base.Dispose(disposing); } private void DisposeHWndSource() { //For keyboarding: As per comment in the Avalon code, this is set to null before disposal (_hwndSource as IKeyboardInputSink).KeyboardInputSite = null; _hwndSource.Dispose(); _hwndSource = null; } #endregion Window Handling & Misc #region Property Mapping /// /// This initializes the default property mapping for the element host. /// First: it creates a new PropertyMap to store all the mappings, this /// is exposed to the user as the PropertyMap property. /// Second: it forwards all property Changed events that we want to listen to /// towards the OnPropertyChanged method. /// Third: it registers several default translators, all of which are handled by /// the ElementHostPropertyTranslator deligate. /// private void StartPropertyMapping() { _propertyMap = new ElementHostPropertyMap(this); //This forwards property change notification to OnPropertyChanged, since //there is no generic way to handle listening to property value changes. this.BackColorChanged += this.OnPropertyChangedBackColor; this.BackgroundImageChanged += this.OnPropertyChangedBackgroundImage; this.BackgroundImageLayoutChanged += this.OnPropertyChangedBackgroundImageLayout; this.CursorChanged += this.OnPropertyChangedCursor; this.EnabledChanged += this.OnPropertyChangedEnabled; this.FontChanged += this.OnPropertyChangedFont; this.ForeColorChanged += this.OnPropertyChangedForeColor; this.RightToLeftChanged += this.OnPropertyChangedRightToLeft; this.VisibleChanged += this.OnPropertyChangedVisible; //We forward these property changes, but don't do anything with them. this.AutoSizeChanged += this.OnPropertyChangedAutoSize; this.BindingContextChanged += this.OnPropertyChangedBindingContext; this.CausesValidationChanged += this.OnPropertyChangedCausesValidation; this.ContextMenuChanged += this.OnPropertyChangedContextMenu; this.ContextMenuStripChanged += this.OnPropertyChangedContextMenuStrip; this.DockChanged += this.OnPropertyChangedDock; this.LocationChanged += this.OnPropertyChangedLocation; this.MarginChanged += this.OnPropertyChangedMargin; this.PaddingChanged += this.OnPropertyChangedPadding; this.ParentChanged += this.OnPropertyChangedParent; this.RegionChanged += this.OnPropertyChangedRegion; this.SizeChanged += this.OnPropertyChangedSize; this.TabIndexChanged += this.OnPropertyChangedTabIndex; this.TabStopChanged += this.OnPropertyChangedTabStop; this.TextChanged += this.OnPropertyChangedText; this.ImeModeChanged += this.OnPropertyChangedImeMode; } ////// These delegates just map property changed events to OnPropertyChanged. These are /// necessary in the WinForms model since there is no common path for property change /// notification. (Avalon has an OnPropertyChanged method.) /// private void OnPropertyChangedBackColor(object sender, System.EventArgs e) { OnPropertyChanged("BackColor", this.BackColor); } private void OnPropertyChangedBackgroundImage(object sender, System.EventArgs e) { OnPropertyChanged("BackgroundImage", this.BackgroundImage); } private void OnPropertyChangedBackgroundImageLayout(object sender, System.EventArgs e) { OnPropertyChanged("BackgroundImageLayout", this.BackgroundImageLayout); } private void OnPropertyChangedCursor(object sender, System.EventArgs e) { OnPropertyChanged("Cursor", this.Cursor); } private void OnPropertyChangedEnabled(object sender, System.EventArgs e) { OnPropertyChanged("Enabled", this.Enabled); } private void OnPropertyChangedFont(object sender, System.EventArgs e) { OnPropertyChanged("Font", this.Font); } private void OnPropertyChangedForeColor(object sender, System.EventArgs e) { OnPropertyChanged("ForeColor", this.ForeColor); } private void OnPropertyChangedRightToLeft(object sender, System.EventArgs e) { OnPropertyChanged("RightToLeft", this.RightToLeft); } private void OnPropertyChangedTabStop(object sender, System.EventArgs e) { OnPropertyChanged("TabStop", this.TabStop); } private void OnPropertyChangedVisible(object sender, System.EventArgs e) { OnPropertyChanged("Visible", this.Visible); } // These properties don't have default mappings, but are added in case anyone wants to add them private void OnPropertyChangedAutoSize(object sender, System.EventArgs e) { OnPropertyChanged("AutoSize", this.AutoSize); } private void OnPropertyChangedPadding(object sender, System.EventArgs e) { OnPropertyChanged("Padding", this.Padding); } private void OnPropertyChangedBindingContext(object sender, System.EventArgs e) { OnPropertyChanged("BindingContext", this.BindingContext); } private void OnPropertyChangedCausesValidation(object sender, System.EventArgs e) { OnPropertyChanged("CausesValidation", this.CausesValidation); } private void OnPropertyChangedContextMenu(object sender, System.EventArgs e) { OnPropertyChanged("ContextMenu", this.ContextMenu); } private void OnPropertyChangedContextMenuStrip(object sender, System.EventArgs e) { OnPropertyChanged("ContextMenuStrip", this.ContextMenuStrip); } private void OnPropertyChangedDock(object sender, System.EventArgs e) { OnPropertyChanged("Dock", this.Dock); } private void OnPropertyChangedLocation(object sender, System.EventArgs e) { OnPropertyChanged("Location", this.Location); } private void OnPropertyChangedMargin(object sender, System.EventArgs e) { OnPropertyChanged("Margin", this.Margin); } private void OnPropertyChangedParent(object sender, System.EventArgs e) { OnPropertyChanged("Parent", this.Parent); } private void OnPropertyChangedRegion(object sender, System.EventArgs e) { OnPropertyChanged("Region", this.Region); } private void OnPropertyChangedSize(object sender, System.EventArgs e) { OnPropertyChanged("Size", this.Size); } private void OnPropertyChangedTabIndex(object sender, System.EventArgs e) { OnPropertyChanged("TabIndex", this.TabIndex); } private void OnPropertyChangedText(object sender, System.EventArgs e) { OnPropertyChanged("Text", this.Text); } private void OnPropertyChangedImeMode(object sender, System.EventArgs e) { OnPropertyChanged("ImeMode", this.ImeMode); } ////// Notifies the property map that a property has changed. /// /// the name of the property which has changed and requires translation /// the new value of the property ////// Putting an InheritanceDemand as a defense-in-depth measure, /// as this provides a hook to the property system that we don't /// want exposed under PartialTrust. /// [UIPermissionAttribute(SecurityAction.InheritanceDemand, Window = UIPermissionWindow.AllWindows)] public virtual void OnPropertyChanged(string propertyName, object value) { if (PropertyMap != null) { PropertyMap.OnPropertyChanged(this, propertyName, value); } } ////// Gets the property map, which determines how setting properties on the /// ElementHost control affects the hosted Windows Presentation Foundation element. /// [Browsable(false)] public PropertyMap PropertyMap { get { return _propertyMap; } } private ElementHostPropertyMap _propertyMap; #endregion Property Mapping #region Hidden Events ////// Occurs when the value of the BindingContext property changes. /// [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] public new event EventHandler BindingContextChanged { add { base.BindingContextChanged += value; } remove { base.BindingContextChanged -= value; } } ////// Occurs when the control is clicked. /// [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] public new event EventHandler Click { add { base.Click += value; } remove { base.Click -= value; } } ////// Occurs when the value of the ClientSize property changes. /// [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] public new event EventHandler ClientSizeChanged { add { base.ClientSizeChanged += value; } remove { base.ClientSizeChanged -= value; } } ////// Occurs when a new control is added to the Control.ControlCollection. /// [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] public new event ControlEventHandler ControlAdded { add { base.ControlAdded += value; } remove { base.ControlAdded -= value; } } ////// Occurs when a control is removed from the Control.ControlCollection. /// [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] public new event ControlEventHandler ControlRemoved { add { base.ControlRemoved += value; } remove { base.ControlRemoved -= value; } } ////// Occurs when the value of the Cursor property changes. /// [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] public new event EventHandler CursorChanged { add { base.CursorChanged += value; } remove { base.CursorChanged -= value; } } ////// Occurs when the control is double-clicked. /// [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] public new event EventHandler DoubleClick { add { base.DoubleClick += value; } remove { base.DoubleClick -= value; } } ////// Occurs when a drag-and-drop operation is completed. /// [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] public new event DragEventHandler DragDrop { add { base.DragDrop += value; } remove { base.DragDrop -= value; } } ////// Occurs when an object is dragged into the control's bounds. /// [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] public new event DragEventHandler DragEnter { add { base.DragEnter += value; } remove { base.DragEnter -= value; } } ////// Occurs when an object is dragged out of the control's bounds. /// [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] public new event EventHandler DragLeave { add { base.DragLeave += value; } remove { base.DragLeave -= value; } } ////// Occurs when an object is dragged over the control's bounds. /// [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] public new event DragEventHandler DragOver { add { base.DragOver += value; } remove { base.DragOver -= value; } } ////// Occurs when the control is entered. /// [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] public new event EventHandler Enter { add { base.Enter += value; } remove { base.Enter -= value; } } ////// Occurs when the Font property value changes. /// [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] public new event EventHandler FontChanged { add { base.FontChanged += value; } remove { base.FontChanged -= value; } } ////// Occurs when the ForeColor property value changes. /// [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] public new event EventHandler ForeColorChanged { add { base.ForeColorChanged += value; } remove { base.ForeColorChanged -= value; } } ////// Occurs during a drag operation. /// [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] public new event GiveFeedbackEventHandler GiveFeedback { add { base.GiveFeedback += value; } remove { base.GiveFeedback -= value; } } ////// Occurs when the control receives focus. /// [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] public new event EventHandler GotFocus { add { base.GotFocus += value; } remove { base.GotFocus -= value; } } ////// Occurs when a control's display requires redrawing. /// [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] public new event InvalidateEventHandler Invalidated { add { base.Invalidated += value; } remove { base.Invalidated -= value; } } ////// Occurs when a key is pressed while the control has focus. /// [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] public new event KeyEventHandler KeyDown { add { base.KeyDown += value; } remove { base.KeyDown -= value; } } ////// Occurs when a key is pressed while the control has focus. /// [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] public new event KeyPressEventHandler KeyPress { add { base.KeyPress += value; } remove { base.KeyPress -= value; } } ////// Occurs when a key is released while the control has focus. /// [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] public new event KeyEventHandler KeyUp { add { base.KeyUp += value; } remove { base.KeyUp -= value; } } ////// Occurs when a control should reposition its child controls. /// [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] public new event LayoutEventHandler Layout { add { base.Layout += value; } remove { base.Layout -= value; } } ////// Occurs when the input focus leaves the control. /// [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] public new event EventHandler Leave { add { base.Leave += value; } remove { base.Leave -= value; } } ////// Occurs when the control loses focus. /// [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] public new event EventHandler LostFocus { add { base.LostFocus += value; } remove { base.LostFocus -= value; } } ////// Occurs when the control loses mouse capture. /// [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] public new event EventHandler MouseCaptureChanged { add { base.MouseCaptureChanged += value; } remove { base.MouseCaptureChanged -= value; } } ////// Occurs when the control is clicked by the mouse. /// [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] public new event MouseEventHandler MouseClick { add { base.MouseClick += value; } remove { base.MouseClick -= value; } } ////// Occurs when the control is double clicked by the mouse. /// [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] public new event MouseEventHandler MouseDoubleClick { add { base.MouseDoubleClick += value; } remove { base.MouseDoubleClick -= value; } } ////// Occurs when the mouse pointer is over the control and a mouse button is pressed. /// [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] public new event MouseEventHandler MouseDown { add { base.MouseDown += value; } remove { base.MouseDown -= value; } } ////// Occurs when the mouse pointer enters the control. /// [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] public new event EventHandler MouseEnter { add { base.MouseEnter += value; } remove { base.MouseEnter -= value; } } ////// Occurs when the mouse pointer rests on the control. /// [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] public new event EventHandler MouseHover { add { base.MouseHover += value; } remove { base.MouseHover -= value; } } ////// Occurs when the mouse pointer leaves the control. ( /// [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] public new event EventHandler MouseLeave { add { base.MouseLeave += value; } remove { base.MouseLeave -= value; } } ////// Occurs when the mouse pointer is moved over the control. /// [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] public new event MouseEventHandler MouseMove { add { base.MouseMove += value; } remove { base.MouseMove -= value; } } ////// Occurs when the mouse pointer is over the control and a mouse button is released. /// [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] public new event MouseEventHandler MouseUp { add { base.MouseUp += value; } remove { base.MouseUp -= value; } } ////// Occurs when the mouse wheel moves while the control has focus. /// [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] public new event MouseEventHandler MouseWheel { add { base.MouseWheel += value; } remove { base.MouseWheel -= value; } } ////// Occurs when the control's padding changes. /// [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] public new event EventHandler PaddingChanged { add { base.PaddingChanged += value; } remove { base.PaddingChanged -= value; } } ////// Occurs when the control is redrawn. /// [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] public new event PaintEventHandler Paint { add { base.Paint += value; } remove { base.Paint -= value; } } ////// Occurs before the KeyDown event when a key is pressed while focus is on this control. /// [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] public new event PreviewKeyDownEventHandler PreviewKeyDown { add { base.PreviewKeyDown += value; } remove { base.PreviewKeyDown -= value; } } ////// Occurs during a drag-and-drop operation and enables the drag source to determine /// whether the drag-and-drop operation should be canceled. /// [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] public new event QueryContinueDragEventHandler QueryContinueDrag { add { base.QueryContinueDrag += value; } remove { base.QueryContinueDrag -= value; } } ////// Occurs when the control is resized. /// [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] public new event EventHandler Resize { add { base.Resize += value; } remove { base.Resize -= value; } } ////// Occurs when the RightToLeft property value changes. /// [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] public new event EventHandler RightToLeftChanged { add { base.RightToLeftChanged += value; } remove { base.RightToLeftChanged -= value; } } ////// Occurs when the Size property value changes. /// [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] public new event EventHandler SizeChanged { add { base.SizeChanged += value; } remove { base.SizeChanged -= value; } } ////// Occurs when the Text property value changes. /// [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] public new event EventHandler TextChanged { add { base.TextChanged += value; } remove { base.TextChanged -= value; } } #endregion #region DEBUG #if DEBUG private static readonly TraceSwitch _traceLayout = new TraceSwitch("ElementHostLayout", "Tracks ElementHost layout information."); #else private static readonly TraceSwitch _traceLayout = null; #endif #endregion DEBUG } #region AvalonAdapter internal class AvalonAdapter : SWC.DockPanel, IDisposable, IKeyboardInputSite { private ElementHost _hostControl; [SuppressMessage("Microsoft.Performance", "CA1810:InitializeReferenceTypeStaticFieldsInline")] static AvalonAdapter() { //These properties define how tabbing occurs in the DockPanel. To be most like //WinForms these are set to use Continue mode as the default. // SWI.KeyboardNavigation.DirectionalNavigationProperty.OverrideMetadata( typeof(AvalonAdapter), new FrameworkPropertyMetadata(SWI.KeyboardNavigationMode.Continue)); SWI.KeyboardNavigation.TabNavigationProperty.OverrideMetadata( typeof(AvalonAdapter), new FrameworkPropertyMetadata(SWI.KeyboardNavigationMode.Continue)); } ////// Creates the Avalon control we use to host /// other WinForms control in Avalon. /// public AvalonAdapter(ElementHost hostControl) { _hostControl = hostControl; } ////// unsink our events /// public void Dispose() { _hostControl = null; } // used to force invalidation of the avalon control's client area. public static readonly DependencyProperty ForceInvalidateProperty = DependencyProperty.Register( "ForceInvalidate", typeof(bool), typeof(AvalonAdapter), new FrameworkPropertyMetadata( false, FrameworkPropertyMetadataOptions.AffectsRender)); private static object OnGetForceInvalidate(DependencyObject d) { return ((AvalonAdapter)d).ForceInvalidate; } ////// This property is toggled by ElementHost to force the hosted /// Avalon control to redraw itself /// public bool ForceInvalidate { get { return (bool)GetValue(ForceInvalidateProperty); } set { SetValue(ForceInvalidateProperty, value); } } ////// This is a transparency optimization. It looks up the SWF visual heirarchy to /// find the first opaque control. It then uses this color as the background for /// OnRender. This doesn't work all the time, but is much faster than the bitmap /// conversion. /// /// The current control ///The first opaque color found, or Color.Empty if none is found private static SD.Color FindSolidColorParent(Control whichControl) { Control control = whichControl; while (control.Parent != null) { control = control.Parent; if (control.BackColor != SD.Color.Empty && control.BackColor.A == 255) { return control.BackColor; } } return SD.Color.Empty; } #region IKeyboardInputSite public void Unregister() { } public bool OnNoMoreTabStops(SWI.TraversalRequest request) { //Tabbing out of hosted elements //Select the next control bool forward = true; Debug.Assert(request != null, "request was null!"); if (request != null) { switch (request.FocusNavigationDirection) { case System.Windows.Input.FocusNavigationDirection.Down: case System.Windows.Input.FocusNavigationDirection.Right: case System.Windows.Input.FocusNavigationDirection.Next: forward = true; break; case System.Windows.Input.FocusNavigationDirection.Up: case System.Windows.Input.FocusNavigationDirection.Left: case System.Windows.Input.FocusNavigationDirection.Previous: forward = false; break; case System.Windows.Input.FocusNavigationDirection.First: case System.Windows.Input.FocusNavigationDirection.Last: break; default: Debug.Assert(false, "Unknown FocusNavigationDirection"); break; } } if (_hostControl != null) { // Get _hostControl's top-most parent. Control topMostParent = _hostControl; while (topMostParent.Parent != null) { topMostParent = topMostParent.Parent; } return topMostParent.SelectNextControl(_hostControl, forward, true, true, true); } return false; } public IKeyboardInputSink Sink { get { return (_hostControl.HwndSource as IKeyboardInputSink); } } #endregion IKeyboardInputSite protected override System.Windows.Automation.Peers.AutomationPeer OnCreateAutomationPeer() { return new ElementHostAutomationPeer(this); } } #endregion AvalonAdapter } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. // Copyright (c) Microsoft Corporation. All rights reserved.
Link Menu

This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- RegisteredScript.cs
- IdnElement.cs
- DefaultHttpHandler.cs
- EntityCommandCompilationException.cs
- DataGridViewRowConverter.cs
- TrimSurroundingWhitespaceAttribute.cs
- UnwrappedTypesXmlSerializerManager.cs
- RequiredArgumentAttribute.cs
- AutomationAttributeInfo.cs
- DeflateStreamAsyncResult.cs
- Invariant.cs
- MessageBuffer.cs
- Base64Encoding.cs
- ErrorFormatterPage.cs
- XPathEmptyIterator.cs
- MTConfigUtil.cs
- MarkerProperties.cs
- PeerInvitationResponse.cs
- DiagnosticSection.cs
- SqlGatherConsumedAliases.cs
- AudioLevelUpdatedEventArgs.cs
- PrimitiveXmlSerializers.cs
- PathGradientBrush.cs
- ConversionValidationRule.cs
- Transactions.cs
- BigInt.cs
- BitmapEffectInputData.cs
- ToolStripPanelCell.cs
- DataGridCheckBoxColumn.cs
- BamlLocalizer.cs
- AssemblyFilter.cs
- FocusChangedEventArgs.cs
- NullReferenceException.cs
- ListViewUpdateEventArgs.cs
- KeyEvent.cs
- OLEDB_Enum.cs
- XmlSerializerNamespaces.cs
- ColumnHeader.cs
- DataServiceExpressionVisitor.cs
- ApplicationBuildProvider.cs
- SetState.cs
- DataBindingCollection.cs
- XamlTypeMapper.cs
- ShadowGlyph.cs
- ParameterBuilder.cs
- HttpCachePolicy.cs
- BitmapEffectGroup.cs
- DesignerActionGlyph.cs
- PartialCachingControl.cs
- Base64Decoder.cs
- PkcsMisc.cs
- ListViewSortEventArgs.cs
- EventLogPermissionEntry.cs
- OutOfMemoryException.cs
- InputLanguage.cs
- Package.cs
- ScriptMethodAttribute.cs
- Thumb.cs
- OnOperation.cs
- Gdiplus.cs
- AsyncStreamReader.cs
- RequestNavigateEventArgs.cs
- SqlDataSourceStatusEventArgs.cs
- InfoCardRSAOAEPKeyExchangeDeformatter.cs
- Convert.cs
- GeneralTransform3DCollection.cs
- PersistChildrenAttribute.cs
- TextureBrush.cs
- SystemWebSectionGroup.cs
- QueryOpcode.cs
- DataGridViewButtonColumn.cs
- DocumentCollection.cs
- QilReference.cs
- HostSecurityManager.cs
- SqlTypeSystemProvider.cs
- MutexSecurity.cs
- _SafeNetHandles.cs
- FontClient.cs
- ManagementPath.cs
- Marshal.cs
- ZipIOCentralDirectoryDigitalSignature.cs
- RegexReplacement.cs
- InvalidComObjectException.cs
- MethodCallConverter.cs
- SecurityHelper.cs
- IntranetCredentialPolicy.cs
- TitleStyle.cs
- IndependentAnimationStorage.cs
- TextBox.cs
- TypedColumnHandler.cs
- dataprotectionpermission.cs
- Activator.cs
- _CommandStream.cs
- MergeFailedEvent.cs
- AuthorizationRuleCollection.cs
- WasHttpHandlersInstallComponent.cs
- NegotiationTokenAuthenticator.cs
- NamedElement.cs
- EntryPointNotFoundException.cs
- ProfileSection.cs