protected override void WndProc(ref Message m) {
            switch (m.Msg) {
                case NativeMethods.WM_COMMAND + NativeMethods.WM_REFLECT:
                    WmReflectCommand(ref m);
                    break;

                case NativeMethods.WM_NOTIFY:
                case NativeMethods.WM_NOTIFY + NativeMethods.WM_REFLECT:
                    NativeMethods.NMHDR note = (NativeMethods.NMHDR) m.GetLParam(typeof(NativeMethods.NMHDR));
                    switch (note.code) {
                        case NativeMethods.TTN_NEEDTEXTA:
                            // MSDN:
                            // Setting the max width has the added benefit of enabling multiline
                            // tool tips!
                            //
                            // [....]: temporarily commenting out this code to fix Pri0 bug 152233
                            // UnsafeNativeMethods.SendMessage(new HandleRef(note, note.hwndFrom), NativeMethods.TTM_SETMAXTIPWIDTH, 0, SystemInformation.MaxWindowTrackSize.Width);
                            WmNotifyNeedTextA(ref m);
                            m.Result = (IntPtr)1;
                            return;

                        case NativeMethods.TTN_NEEDTEXTW:
                            // On Win 98/IE 5,we still get W messages.  If we ignore them, it will send the A version.
                            if (Marshal.SystemDefaultCharSize == 2) {
                                // MSDN:
                                // Setting the max width has the added benefit of enabling multiline
                                // tool tips!
                                //
                                // [....]: temporarily commenting out this code to fix Pri0 bug 152233
                                // UnsafeNativeMethods.SendMessage(new HandleRef(note, note.hwndFrom), NativeMethods.TTM_SETMAXTIPWIDTH, 0, SystemInformation.MaxWindowTrackSize.Width);
                                WmNotifyNeedText(ref m);
                                m.Result = (IntPtr)1;
                                return;
                            }
                            break;
                        case NativeMethods.TTN_SHOW:
                            // VSWhidbey 177016: Prevent the tooltip from displaying in the upper left corner of the
                            // desktop when the control is nowhere near that location.
                            NativeMethods.WINDOWPLACEMENT wndPlacement = new NativeMethods.WINDOWPLACEMENT();
                            int nRet = UnsafeNativeMethods.GetWindowPlacement(new HandleRef(null, note.hwndFrom), ref wndPlacement);

                            // Is this tooltip going to be positioned in the upper left corner of the display,
                            // but nowhere near the toolbar button?
                            if (wndPlacement.rcNormalPosition_left == 0 &&
                                wndPlacement.rcNormalPosition_top == 0 &&
                                this.hotItem != -1) {

                                // Assume that we're going to vertically center the tooltip on the right edge of the current
                                // hot item.

                                // Where is the right edge of the current hot item?
                                int buttonRight = 0;
                                for(int idx = 0; idx <= this.hotItem; idx++) {
                                    // How wide is the item at this index? (It could be a separator, and therefore a different width.)
                                    buttonRight += buttonsCollection[idx].GetButtonWidth();
                                }

                                // Where can we place this tooltip so that it will be completely visible on the current display?
                                int tooltipWidth = wndPlacement.rcNormalPosition_right - wndPlacement.rcNormalPosition_left;
                                int tooltipHeight = wndPlacement.rcNormalPosition_bottom - wndPlacement.rcNormalPosition_top;

                                // We'll need screen coordinates of this position for setting the tooltip's position
                                int x = this.Location.X + buttonRight + 1;
                                int y = this.Location.Y + (this.ButtonSize.Height / 2);
                                NativeMethods.POINT leftTop = new NativeMethods.POINT(x, y);
                                UnsafeNativeMethods.ClientToScreen(new HandleRef(this, this.Handle), leftTop);

                                // Will the tooltip bleed off the top?
                                if (leftTop.y < SystemInformation.WorkingArea.Y) {
                                    // Reposition the tooltip to be displayed below the button
                                    leftTop.y += (this.ButtonSize.Height / 2) + 1;
                                }

                                // Will the tooltip bleed off the bottom?
                                if (leftTop.y + tooltipHeight > SystemInformation.WorkingArea.Height) {
                                    // Reposition the tooltip to be displayed above the button
                                    leftTop.y -= ((this.ButtonSize.Height / 2) + tooltipHeight + 1);
                                }

                                // Will the tooltip bleed off the right edge?
                                if (leftTop.x + tooltipWidth > SystemInformation.WorkingArea.Right) {
                                    // Move the tooltip far enough left that it will display in the working area
                                    leftTop.x -= (this.ButtonSize.Width + tooltipWidth + 2);
                                }

                                SafeNativeMethods.SetWindowPos(new HandleRef(null, note.hwndFrom), NativeMethods.NullHandleRef, leftTop.x, leftTop.y, 0, 0, NativeMethods.SWP_NOSIZE | NativeMethods.SWP_NOZORDER | NativeMethods.SWP_NOACTIVATE);
                                m.Result = (IntPtr)1;
                                return;
                            }
                            break;

                        case NativeMethods.TBN_HOTITEMCHANGE:
                            WmNotifyHotItemChange(ref m);
                            break;


                        case NativeMethods.TBN_QUERYINSERT:
                            m.Result = (IntPtr)1;
                            break;

                        case NativeMethods.TBN_DROPDOWN:
                            WmNotifyDropDown(ref m);
                            break;
                    }
                    break;

            }
            base.WndProc(ref m);
        }
Exemple #2
0
        /// <devdoc>
        ///     Updated the window state from the handle, if created.
        /// </devdoc>
        /// <internalonly/>
        //
        // This function is called from all over the place, including my personal favorite,
        // WM_ERASEBKGRND.  Seems that's one of the first messages we get when a user clicks the min/max
        // button, even before WM_WINDOWPOSCHANGED.
        private void UpdateWindowState() {
            if (IsHandleCreated) {
                FormWindowState oldState = WindowState;
                NativeMethods.WINDOWPLACEMENT wp = new NativeMethods.WINDOWPLACEMENT();
                wp.length = Marshal.SizeOf(typeof(NativeMethods.WINDOWPLACEMENT));
                UnsafeNativeMethods.GetWindowPlacement(new HandleRef(this, Handle), ref wp);

                switch (wp.showCmd) {
                    case NativeMethods.SW_NORMAL:
                    case NativeMethods.SW_RESTORE:
                    case NativeMethods.SW_SHOW:
                    case NativeMethods.SW_SHOWNA:
                    case NativeMethods.SW_SHOWNOACTIVATE:
                        if (formState[FormStateWindowState] != (int)FormWindowState.Normal) {
                            formState[FormStateWindowState] = (int)FormWindowState.Normal;
                        }
                        break;
                    case NativeMethods.SW_SHOWMAXIMIZED:
                        if (formState[FormStateMdiChildMax] == 0) {
                            formState[FormStateWindowState] = (int)FormWindowState.Maximized;
                        }
                        break;
                    case NativeMethods.SW_SHOWMINIMIZED:
                    case NativeMethods.SW_MINIMIZE:
                    case NativeMethods.SW_SHOWMINNOACTIVE:
                        if (formState[FormStateMdiChildMax] == 0) {
                            formState[FormStateWindowState] = (int)FormWindowState.Minimized;
                        }
                        break;
                    case NativeMethods.SW_HIDE:
                    default:
                        break;
                }

                // If we used to be normal and we just became minimized or maximized,
                // stash off our current bounds so we can properly restore.
                //
                if (oldState == FormWindowState.Normal && WindowState != FormWindowState.Normal) {

                    if (WindowState == FormWindowState.Minimized) {
                        SuspendLayoutForMinimize();
                    }

                    restoredWindowBounds.Size = ClientSize;
                    formStateEx[FormStateExWindowBoundsWidthIsClientSize] = 1;
                    formStateEx[FormStateExWindowBoundsHeightIsClientSize] = 1;
                    restoredWindowBoundsSpecified = BoundsSpecified.Size;
                    restoredWindowBounds.Location = Location;
                    restoredWindowBoundsSpecified |= BoundsSpecified.Location;

                    //stash off restoreBounds As well...
                    restoreBounds.Size = Size;
                    restoreBounds.Location = Location;
                }

                // If we just became normal or maximized resume
                if (oldState == FormWindowState.Minimized && WindowState != FormWindowState.Minimized) {
                    ResumeLayoutFromMinimize();
                }

                switch (WindowState) {
                    case FormWindowState.Normal:
                        SetState(STATE_SIZELOCKEDBYOS, false);
                        break;
                    case FormWindowState.Maximized:
                    case FormWindowState.Minimized:
                        SetState(STATE_SIZELOCKEDBYOS, true);
                        break;
                }

                if (oldState != WindowState) {
                    AdjustSystemMenu();
                }
            }
        }
        /// <include file='doc\MDIClient.uex' path='docs/doc[@for="MdiClient.SetBoundsCore"]/*' />
        /// <devdoc>
        ///    <para>[To be supplied.]</para>
        /// </devdoc>
        protected override void SetBoundsCore(int x, int y, int width, int height, BoundsSpecified specified) {
            ISite site = (ParentInternal == null) ? null : ParentInternal.Site;
            if (IsHandleCreated && (site == null || !site.DesignMode)) {
                Rectangle oldBounds = Bounds;
                base.SetBoundsCore(x, y, width, height, specified);
                Rectangle newBounds = Bounds;

                int yDelta = oldBounds.Height - newBounds.Height;
                if (yDelta != 0) {
                    // NOTE: This logic is to keep minimized MDI children anchored to
                    // the bottom left of the client area, normally they are anchored
                    // to the top right which just looks wierd!
                    //
                    NativeMethods.WINDOWPLACEMENT wp = new NativeMethods.WINDOWPLACEMENT();
                    wp.length = Marshal.SizeOf(typeof(NativeMethods.WINDOWPLACEMENT));

                    for (int i=0; i < Controls.Count; i++) {
                        Control ctl = Controls[i];
                        if (ctl != null && ctl is Form) {
                            Form child = (Form)ctl;
                            // VSWhidbey 93551: Only adjust the window position for visible MDI Child windows to prevent
                            // them from being re-displayed.
                            if (child.CanRecreateHandle() && child.WindowState == FormWindowState.Minimized) {
                                UnsafeNativeMethods.GetWindowPlacement(new HandleRef(child, child.Handle), ref wp);
                                wp.ptMinPosition_y -= yDelta;
                                if (wp.ptMinPosition_y == -1) {
                                    if (yDelta < 0) {
                                        wp.ptMinPosition_y = 0;
                                    }
                                    else {
                                        wp.ptMinPosition_y = -2;
                                    }
                                }
                                wp.flags = NativeMethods.WPF_SETMINPOSITION;
                                UnsafeNativeMethods.SetWindowPlacement(new HandleRef(child, child.Handle), ref wp);
                                wp.flags = 0;
                            }
                        }
                    }
                }
            }
            else {
                base.SetBoundsCore(x, y, width, height, specified);
            }
        }
Exemple #4
0
        internal override void RecreateHandleCore() {
            //Debug.Assert( CanRecreateHandle(), "Recreating handle when form is not ready yet." );
            NativeMethods.WINDOWPLACEMENT wp = new NativeMethods.WINDOWPLACEMENT();
            FormStartPosition oldStartPosition = FormStartPosition.Manual;

            if (!IsMdiChild && (WindowState == FormWindowState.Minimized || WindowState == FormWindowState.Maximized)) {
                wp.length = Marshal.SizeOf(typeof(NativeMethods.WINDOWPLACEMENT));
                UnsafeNativeMethods.GetWindowPlacement(new HandleRef(this, Handle), ref wp);
            }

            if (StartPosition != FormStartPosition.Manual) {
                oldStartPosition = StartPosition;
                // Set the startup postion to manual, to stop the form from
                // changing position each time RecreateHandle() is called.
                StartPosition = FormStartPosition.Manual;
            }

            EnumThreadWindowsCallback etwcb = null;
            SafeNativeMethods.EnumThreadWindowsCallback callback = null;
            if (IsHandleCreated) {
                // First put all the owned windows into a list
                etwcb = new EnumThreadWindowsCallback();
                if (etwcb != null) {
                    callback = new SafeNativeMethods.EnumThreadWindowsCallback(etwcb.Callback);
                    UnsafeNativeMethods.EnumThreadWindows(SafeNativeMethods.GetCurrentThreadId(),
                                                          new NativeMethods.EnumThreadWindowsCallback(callback),
                                                          new HandleRef(this, this.Handle));
                    // Reset the owner of the windows in the list
                    etwcb.ResetOwners();
                }
            }

            base.RecreateHandleCore();


            if (etwcb != null) {
                // Set the owner of the windows in the list back to the new Form's handle
                etwcb.SetOwners(new HandleRef(this, this.Handle));
            }
            
            if (oldStartPosition != FormStartPosition.Manual) {
                StartPosition = oldStartPosition;
            }

            if (wp.length > 0) {
                UnsafeNativeMethods.SetWindowPlacement(new HandleRef(this, Handle), ref wp);
            }

            if (callback != null) {
                GC.KeepAlive(callback);
            }
        }
        /// <summary>
        /// Send mouse click to relative position in the client window.
        /// </summary>
        /// <param name="client">Target client.</param>
        /// <param name="button">System.Windows.Forms.MouseButtons to click.</param>
        /// <param name="x">X position of point to click relative to client window's X position.</param>
        /// <param name="y">Y position of point to click relative to client window's Y position.</param>
        /// <param name="doubleClick">True for double click, false for single click.</param>
        /// <returns>True on success.</returns>
        public static bool SendMouseClick(int client, MouseButtons button, int x, int y, bool doubleClick)
        {
            ClientInfo ci;
            if (ClientInfoCollection.GetClient(client, out ci))
            {
                NativeMethods.INPUT[] inputs = new NativeMethods.INPUT[2];
                NativeMethods.MOUSEINPUT mi = new NativeMethods.MOUSEINPUT();
                inputs[0].type = NativeMethods.INPUT_MOUSE;
                inputs[1].type = NativeMethods.INPUT_MOUSE;
                mi.dx = 0;
                mi.dy = 0;
                switch (button)
                {
                    case MouseButtons.None:
                        return false;
                    case MouseButtons.Left:
                        mi.dwFlags = NativeMethods.MOUSEEVENTF_LEFTDOWN;
                        inputs[0].mkhi.mi = mi;
                        mi.dwFlags = NativeMethods.MOUSEEVENTF_LEFTUP;
                        inputs[1].mkhi.mi = mi;
                        break;
                    case MouseButtons.Right:
                        mi.dwFlags = NativeMethods.MOUSEEVENTF_RIGHTDOWN;
                        inputs[0].mkhi.mi = mi;
                        mi.dwFlags = NativeMethods.MOUSEEVENTF_RIGHTUP;
                        inputs[1].mkhi.mi = mi;
                        break;
                    case MouseButtons.Middle:
                        mi.dwFlags = NativeMethods.MOUSEEVENTF_MIDDLEDOWN;
                        inputs[0].mkhi.mi = mi;
                        mi.dwFlags = NativeMethods.MOUSEEVENTF_MIDDLEUP;
                        inputs[1].mkhi.mi = mi;
                        break;
                    case MouseButtons.XButton1:
                        mi.mouseData = NativeMethods.XBUTTON1;
                        mi.dwFlags = NativeMethods.MOUSEEVENTF_XDOWN;
                        inputs[0].mkhi.mi = mi;
                        mi.dwFlags = NativeMethods.MOUSEEVENTF_XUP;
                        inputs[1].mkhi.mi = mi;
                        break;
                    case MouseButtons.XButton2:
                        mi.mouseData = NativeMethods.XBUTTON2;
                        mi.dwFlags = NativeMethods.MOUSEEVENTF_XDOWN;
                        inputs[0].mkhi.mi = mi;
                        mi.dwFlags = NativeMethods.MOUSEEVENTF_XUP;
                        inputs[1].mkhi.mi = mi;
                        break;
                }

                if (!ci.PrepareWindowForInput())
                {
                    ci.DetachFromWindow();
                    return false;
                }

                NativeMethods.WINDOWPLACEMENT wp = new NativeMethods.WINDOWPLACEMENT();
                if (NativeMethods.GetWindowPlacement(ci.WindowHandle, ref wp))
                {
                    /*int screenX = wp.rcNormalPosition.X + x;
                    int screenY = wp.rcNormalPosition.Y + y;
                    int absX = (screenX * 65536 / Screen.PrimaryScreen.Bounds.Width);
                    int absY = (screenY * 65536 / Screen.PrimaryScreen.Bounds.Height);
                    inputs[0].mkhi.mi.dx = absX;
                    inputs[1].mkhi.mi.dx = absX;
                    inputs[0].mkhi.mi.dy = absY;
                    inputs[1].mkhi.mi.dy = absY;*/

                    // using this method because absolute position is always off by a pixel or 2

                    if (!NativeMethods.SetCursorPos(x + wp.rcNormalPosition.X, y + wp.rcNormalPosition.Y)) return false;
                }
                else return false;

                uint success = NativeMethods.SendInput((uint)inputs.Length, inputs, Marshal.SizeOf(inputs[0]));
                if (doubleClick && success == inputs.Length)
                {
                    success = NativeMethods.SendInput((uint)inputs.Length, inputs, Marshal.SizeOf(inputs[0]));
                }
                ci.DetachFromWindow();
                return success == inputs.Length;
            }
            return false;
        }