public SelectedIndexEnumerator(VirtualTreeControl owner) { myOwner = owner; myCurrentRange = -2; // -2 to distinguish initial state from ending state (where these will equal VirtualTreeConstant.NullIndex) myCurrentSelection = -2; }
/// <summary> /// Create a new DoubleClickEventArgs in response to a double click event in the VirtualTreeControl /// </summary> /// <param name="parent">The control that was double clicked</param> /// <param name="button">The mouse button that was clicked</param> /// <param name="x">The x (horizontal) coordinate of the click</param> /// <param name="y">The y (vertical) coordinate of the click</param> public DoubleClickEventArgs(VirtualTreeControl parent, MouseButtons button, int x, int y) { myX = x; myY = y; myParent = parent; myButton = button; }
/// <summary> /// Signals the system that an accessibility event occurred. /// The notification will be sent for the specified view only. /// </summary> /// <param name="accessibilityEvent">One of the predefined EVENT_OBJECT_* or EVENT_SYSTEM_* constants.</param> /// <param name="row">row index for item.</param> /// <param name="column">column index for item.</param> /// <param name="treeControl">The VirtualTreeControl that contains the object that generated the event.</param> public static void Notify(int accessibilityEvent, int row, int column, VirtualTreeControl treeControl) { Debug.Assert(ShouldNotify(accessibilityEvent, treeControl)); if ((treeControl == null) || (row < 0) || (column < 0)) { return; } // Add the accessibleObject to the circular array and generate an ID for it. var accessibleObjectId = Instance.InternalAddObject(treeControl, row, column); // Create a HandleRef object for the hwnd. // (A HandleRef structure wraps a managed object holding a // handle to a resource that is passed to unmanaged code. // Wrapping a handle with HandleRef guarantees that the managed // object is not garbage collected until the platform invoke call completes.) var viewHandleRef = new HandleRef(treeControl, treeControl.Handle); // Notify the system of the event. NativeMethods.NotifyWinEvent( accessibilityEvent, // Specifies the event that occurred viewHandleRef, // Handle to the window that contains the object that generated the event. accessibleObjectId, // Generated object ID that uniquely identifies the accessibleObject (for use by WM_GETOBJECT). NativeMethods.CHILDID_SELF); // CHILDID_SELF means the event was generated by the object itself, not a child object. }
/// <summary> /// Call to test if the Notify method needs to be called. ShouldNotify should /// always be called before Notify. /// </summary> /// <param name="accessibilityEvent">One of the predefined EVENT_OBJECT_* or EVENT_SYSTEM_* constants.</param> /// <param name="treeControl">The tree control that generated the event</param> /// <returns>true if Notify should be called</returns> public static bool ShouldNotify(int accessibilityEvent, VirtualTreeControl treeControl) { if (treeControl.GetStateFlag(VTCStateFlags.ReturnedAccessibilityObject)) { // IsWinEventHookInstalled not available on W2k return(NativeMethods.WinXPOrHigher ? (0 != NativeMethods.IsWinEventHookInstalled(accessibilityEvent)) : true); } return(false); }
public AccessibleObjectEntry(int index) { // empty entry _index = index; _entryReuseCounter = 0; _treeControl = null; _row = 0; _column = 0; }
public void SetObjectData(VirtualTreeControl treeControl, int row, int column) { _treeControl = treeControl; _row = row; _column = column; if (_entryReuseCounter >= Int16.MaxValue) { _entryReuseCounter = 0; } else { _entryReuseCounter++; } }
private int InternalAddObject(VirtualTreeControl treeControl, int row, int column) { array[nextIndex].SetObjectData(treeControl, row, column); var id = array[nextIndex].Id; if (nextIndex >= array.GetUpperBound(0)) { nextIndex = array.GetLowerBound(0); } else { nextIndex++; } return(id); }
/// <summary> /// Create a new VirtualTreeHeaderControl to associate with a specific VirtualTreeControl. Should /// only be called directly by VirtualTreeControl.CreateHeaderControl, or indirectly by an override /// of that function and a constructor from a derived class. /// </summary> /// <param name="associatedControl"></param> public VirtualTreeHeaderControl(VirtualTreeControl associatedControl) : this() { myAssociatedControl = associatedControl; }
public void SetObjectData(VirtualTreeControl treeControl, int row, int column) { _treeControl = treeControl; _row = row; _column = column; if (_entryReuseCounter >= Int16.MaxValue) { _entryReuseCounter = 0; } else { _entryReuseCounter++; } }
private int InternalAddObject(VirtualTreeControl treeControl, int row, int column) { array[nextIndex].SetObjectData(treeControl, row, column); var id = array[nextIndex].Id; if (nextIndex >= array.GetUpperBound(0)) { nextIndex = array.GetLowerBound(0); } else { nextIndex++; } return id; }
public AccTreeRoot(VirtualTreeControl ctl) : base(ctl) { myCtl = ctl; }
// row and column here are the row and column of the parent item. // The local column (relative to the parent branch) can be retrieved from the VirtualTreeItemInfo. public AccColumn( VirtualTreeControl ctl, int row, int displayColumn, int nativeColumn, AccItemSettings settings, ref VirtualTreeItemInfo info) { // Blank row is calculated explicitly, ignore it if it is passed in settings = (AccItemSettings)((int)settings & ~(int)(AccItemSettings.BlankRow)); myCtl = ctl; var tree = ctl.Tree; var lastRowAdjust = 0; if (info.Column == 0) { // Looking at a complex column myChildCount = info.Branch.VisibleItemCount; lastRowAdjust = -1; } else { // This is a wrapper around a single-celled column. It can // only have one item in it. Flag with a -1 to distinguish it // from a complex column myChildCount = -1; } // Expand column to include blanks to the bottom and right var expansion = tree.GetBlankExpansion( row + lastRowAdjust + tree.GetDescendantItemCount(row, nativeColumn, true, myChildCount != -1), displayColumn, myCtl.myColumnPermutation); myRow = row; myRowHeight = expansion.BottomRow - row + 1; displayColumn = expansion.AnchorColumn; var colPerm = ctl.myColumnPermutation; if (displayColumn == VirtualTreeConstant.NullIndex) { settings |= AccItemSettings.BlankRow; displayColumn = 0; myColumnWidth = expansion.Width; } else { nativeColumn = (colPerm != null) ? colPerm.GetNativeColumn(displayColumn) : displayColumn; myColumnWidth = expansion.RightColumn - displayColumn + 1; } myDisplayColumn = displayColumn; myNativeColumn = nativeColumn; mySettings = settings; }
public AccSimpleCell( VirtualTreeControl ctl, int row, int displayColumn, int nativeColumn, AccItemSettings settings, ref VirtualTreeItemInfo info) : base(ctl, row, displayColumn, nativeColumn, settings, ref info) { value = info.Branch.GetAccessibleValue(info.Row, info.Column); }
public AccPrimaryItem( VirtualTreeControl ctl, int row, int displayColumn, int nativeColumn, AccItemSettings settings, ref VirtualTreeItemInfo info) : base(ctl, row, displayColumn, nativeColumn, settings, ref info) { if (ctl.MultiColumnTree != null) { var mcBranch = info.Branch as IMultiColumnBranch; if (mcBranch != null) { // If Column is not 0, then we're looking at an expandable cell. Expandable // cells cannot have multiple columns. if (info.Column == 0) { var childColumnCount = (0 == (info.Branch.Features & BranchFeatures.JaggedColumns)) ? mcBranch.ColumnCount : mcBranch.GetJaggedColumnCount(info.Row); myNativeChildColumns = myDisplayedChildColumns = childColumnCount - 1; var colPerm = ctl.myColumnPermutation; if (colPerm != null) { // We have to ask on a per-column basis if the given column is // currently displayed. var columnBound = nativeColumn + childColumnCount; childColumnCount = 0; for (var i = nativeColumn + 1; i < columnBound; ++i) { if (colPerm.GetPermutedColumn(i) != -1) { ++childColumnCount; } } myDisplayedChildColumns = childColumnCount; } } } } if (ctl.Tree.IsExpanded(myRow, myNativeColumn)) { myChildItems = ctl.Tree.GetExpandedBranch(myRow, myNativeColumn).Branch.VisibleItemCount; } }
/// <summary> /// Construct the base class of an accessibility item for this object /// </summary> /// <param name="ctl">The parent control</param> /// <param name="row">The current row</param> /// <param name="displayColumn">The display column.</param> /// <param name="nativeColumn">The native column.</param> /// <param name="settings">Miscellaneous settings for the object</param> /// <param name="info">The info for this cell. Gives the info for column 0 for a blank row.</param> public AccItem( VirtualTreeControl ctl, int row, int displayColumn, int nativeColumn, AccItemSettings settings, ref VirtualTreeItemInfo info) { // Blank row is calculated explicitly, ignore it if it is passed in settings = (AccItemSettings)((int)settings & ~(int)(AccItemSettings.BlankRow)); var tree = ctl.Tree; // Get information about the branch and tree state at this // position in the tree. Debug.Assert(!info.Blank); // Adjust row and column before creating here to take care of blanks if (displayColumn < 0) { displayColumn = 0; } if (nativeColumn < 0) { nativeColumn = 0; } if (ctl.MultiColumnTree != null) { // Adjust the passed in row and column so that it is on a non-blank item, // and find out how far the blank range extends from that anchor point. // Note that even a single-column branch can have blank columns to the // right (or left, with permutations), so we always need to do GetBlankExpansion. var expansion = tree.GetBlankExpansion(row, displayColumn, ctl.myColumnPermutation); row = expansion.TopRow; myRowHeight = expansion.Height; if (expansion.AnchorColumn != -1) { displayColumn = expansion.AnchorColumn; myColumnWidth = expansion.RightColumn - displayColumn + 1; // Ignore blanks to the left, don't use Width } else { settings |= AccItemSettings.BlankRow; myColumnWidth = expansion.Width; } } else { myRowHeight = myColumnWidth = 1; } // Cache the information we need myCtl = ctl; ctl.GetAccessibilityTextFields( row, displayColumn, ref info, out myName, out myValue, out myDescription, out myHelpFile, out myHelpId, out myState, out myCheckBoxContent); myRow = row; myDisplayColumn = displayColumn; myNativeColumn = nativeColumn; mySettings = settings; myLevel = info.Level; if (info.Expandable) { if (info.Expanded) { myState |= AccessibleStates.Expanded; } else { myState |= AccessibleStates.Collapsed; } } if (0 != (settings & AccItemSettings.HiddenItem)) { myState |= AccessibleStates.Invisible; } else if (Rectangle.Empty == myCtl.GetAccessibilityLocation(myRow, myDisplayColumn, myRowHeight, myColumnWidth)) { myState |= (AccessibleStates.Invisible | AccessibleStates.Offscreen); } ctl.SetAccessibilityState(row, displayColumn, settings, ref myState); }
/// <summary> /// Helper routine to figure out if a given column object is a simple cell or a complex item. /// </summary> public static bool IsSimpleItem(VirtualTreeControl ctl, int baseRow, int nativeBaseColumn, int localColumn) { if (localColumn == 0) { return false; // items in the first column are never simple } var simpleCell = true; var tree = ctl.Tree; var info = tree.GetItemInfo(baseRow, nativeBaseColumn, false); var mcBranch = info.Branch as IMultiColumnBranch; if (mcBranch != null) { var nativeColumn = nativeBaseColumn + localColumn; var style = mcBranch.ColumnStyles(localColumn); var colInfo = new VirtualTreeItemInfo(); switch (style) { case SubItemCellStyles.Expandable: // Use a simple cell unless the item is expandable. An item // in an expandable column cannot have subitems, so // we will not need a column object for this purpose. simpleCell = !info.Branch.IsExpandable(info.Row, localColumn); break; case SubItemCellStyles.Mixed: case SubItemCellStyles.Complex: colInfo = tree.GetItemInfo(baseRow, nativeColumn, true); if (colInfo.Column == 0) { var columns = (0 == (info.Branch.Features & BranchFeatures.JaggedColumns)) ? mcBranch.ColumnCount : mcBranch.GetJaggedColumnCount(info.Row); // The data is provided by a different branch. The item is simple only // if the branch has one unexpandable item and no sub items. if (!(colInfo.Branch.VisibleItemCount == 1 && !colInfo.Branch.IsExpandable(0, 0) && (localColumn < columns || (null != (colInfo.Branch as IMultiColumnBranch) && 0 == tree.GetSubItemCount(baseRow, nativeColumn))))) { simpleCell = false; } } else if (style == SubItemCellStyles.Mixed) { goto case SubItemCellStyles.Expandable; } break; } } return simpleCell; }
/// <summary> /// Return either a Cell or Column object, depending on the branch settings /// </summary> /// <param name="ctl">The parent control</param> /// <param name="baseRow">The row coordinate</param> /// <param name="nativeBaseColumn">The column coordinate for the owning branch</param> /// <param name="localColumn">The native column offset</param> /// <param name="returnColumn">Return an AccColumn object if this is true, otherwise return the AccPrimaryItem directly</param> /// <returns>An AccSimpleCell or AccColumn</returns> public static AccessibleObject GetColumnObject( VirtualTreeControl ctl, int baseRow, int nativeBaseColumn, int localColumn, bool returnColumn) { // Note: if this logic changes, corresponding change should be made to IsSimpleItem below. Debug.Assert(localColumn > 0); AccessibleObject retVal = null; var tree = ctl.Tree; var info = tree.GetItemInfo(baseRow, nativeBaseColumn, false); var mcBranch = info.Branch as IMultiColumnBranch; if (mcBranch != null) { var simpleCell = true; var useColInfo = false; var nativeColumn = nativeBaseColumn + localColumn; var displayColumn = nativeColumn; var colPerm = ctl.myColumnPermutation; var settings = AccItemSettings.None; if (colPerm != null) { displayColumn = colPerm.GetPermutedColumn(nativeColumn); if (displayColumn == -1) { displayColumn = 0; settings |= AccItemSettings.HiddenItem; } } var style = mcBranch.ColumnStyles(localColumn); var colInfo = new VirtualTreeItemInfo(); style = mcBranch.ColumnStyles(localColumn); switch (style) { case SubItemCellStyles.Expandable: // Use a simple cell unless the item is expandable. An item // in an expandable column cannot have subitems, so // we will not need a column object for this purpose. simpleCell = !info.Branch.IsExpandable(info.Row, localColumn); break; case SubItemCellStyles.Mixed: case SubItemCellStyles.Complex: colInfo = tree.GetItemInfo(baseRow, nativeColumn, true); if (colInfo.Column == 0) { var columns = (0 == (info.Branch.Features & BranchFeatures.JaggedColumns)) ? mcBranch.ColumnCount : mcBranch.GetJaggedColumnCount(info.Row); // The data is provided by a different branch. The item is simple only // if the branch has one unexpandable item and no sub items. if (!(colInfo.Branch.VisibleItemCount == 1 && !colInfo.Branch.IsExpandable(0, 0) && (localColumn < columns || (null != (colInfo.Branch as IMultiColumnBranch) && 0 == tree.GetSubItemCount(baseRow, nativeColumn))))) { simpleCell = false; } useColInfo = true; } else if (style == SubItemCellStyles.Mixed) { goto case SubItemCellStyles.Expandable; } break; } if (simpleCell) { if (useColInfo) { retVal = new AccSimpleCell(ctl, baseRow, displayColumn, nativeColumn, settings, ref colInfo); } else { var cellInfo = tree.GetItemInfo(baseRow, nativeColumn, true); if (!cellInfo.Blank) { retVal = new AccSimpleCell(ctl, baseRow, displayColumn, nativeColumn, settings, ref cellInfo); } } } else if (returnColumn) { if (useColInfo) { retVal = new AccColumn(ctl, baseRow, displayColumn, nativeColumn, settings, ref colInfo); } else { var cellInfo = tree.GetItemInfo(baseRow, nativeBaseColumn + localColumn, true); retVal = new AccColumn(ctl, baseRow, displayColumn, nativeColumn, settings, ref cellInfo); } } else { if (useColInfo) { retVal = new AccPrimaryItem(ctl, baseRow, displayColumn, nativeColumn, settings, ref colInfo); } else { var cellInfo = tree.GetItemInfo(baseRow, nativeBaseColumn + localColumn, true); retVal = new AccPrimaryItem(ctl, baseRow, displayColumn, nativeColumn, settings, ref cellInfo); } } } return retVal; }
/// <summary> /// Create a new DoubleClickEventArgs in response to a double click event in the VirtualTreeControl /// </summary> /// <param name="parent">The control that was double clicked</param> /// <param name="button">The mouse button that was clicked</param> /// <param name="x">The x (horizontal) coordinate of the click</param> /// <param name="y">The y (vertical) coordinate of the click</param> public DoubleClickEventArgs(VirtualTreeControl parent, MouseButtons button, int x, int y) { myX = x; myY = y; myParent = parent; myButton = button; }
/// <summary> /// Call to test if the Notify method needs to be called. ShouldNotify should /// always be called before Notify. /// </summary> /// <param name="accessibilityEvent">One of the predefined EVENT_OBJECT_* or EVENT_SYSTEM_* constants.</param> /// <param name="treeControl">The tree control that generated the event</param> /// <returns>true if Notify should be called</returns> public static bool ShouldNotify(int accessibilityEvent, VirtualTreeControl treeControl) { if (treeControl.GetStateFlag(VTCStateFlags.ReturnedAccessibilityObject)) { // IsWinEventHookInstalled not available on W2k return NativeMethods.WinXPOrHigher ? (0 != NativeMethods.IsWinEventHookInstalled(accessibilityEvent)) : true; } return false; }
public ListBoxStateTrackerClass(VirtualTreeControl ctl) { Inner = new ListBoxStateTracker(ctl); }
internal static string GetAccessibleObjectName(VirtualTreeControl parent) { var treeControl = parent; if (treeControl != null) { var headers = treeControl.GetColumnHeaders(); // Fix for 332947 - Exception thrown when trying to in-place edit a resource name with JAWS running // v-matbir 7/28/04 if (headers != null) { var currentColumn = treeControl.CurrentColumn; Debug.Assert(currentColumn >= 0 && currentColumn < headers.Length, "column index out of range"); if (currentColumn >= 0 && currentColumn < headers.Length) { return headers[currentColumn].Text; } } } return string.Empty; }
/// <summary> /// Create a new inplace edit control /// </summary> public VirtualTreeInPlaceEditControl() { myInPlaceHelper = VirtualTreeControl.CreateInPlaceControlHelper(this); BorderStyle = BorderStyle.FixedSingle; TextAlign = HorizontalAlignment.Left; }
internal ListBoxStateTracker(VirtualTreeControl ctl) { startTop = ctl.TopIndex; restoreSelection = null; restoreAnchorIndex = -1; restoreColumn = startColumn = ctl.CurrentColumn; var hWnd = ctl.Handle; if (ctl.GetStyleFlag(VTCStyleFlags.MultiSelect) && ctl.SelectedItemCount > 0) { restoreSelection = ctl.SelectedIndicesArray; restoreAnchorIndex = ctl.AnchorIndex; } restoreTop = startTop; // Don't use CurrentIndex here, it doesn't notice the caret/anchor subtle distinction, // so we end up making a selection where there didn't used to be one. restoreCaret = ctl.CurrentIndexCheckAnchor; caretMoved = false; restoreXPos = ctl.myXPos; startingListCount = NativeMethods.SendMessage(hWnd, NativeMethods.LB_GETCOUNT, 0, 0).ToInt32(); restoreHExtent = 0; if (restoreXPos != 0) { restoreHExtent = NativeMethods.SendMessage(hWnd, NativeMethods.LB_GETHORIZONTALEXTENT, 0, 0).ToInt32(); NativeMethods.SendMessage( hWnd, NativeMethods.WM_HSCROLL, NativeMethods.MAKELONG((int)NativeMethods.ScrollAction.ThumbPosition, 0), 0); NativeMethods.SendMessage(hWnd, NativeMethods.WM_HSCROLL, (int)NativeMethods.ScrollAction.EndScroll, 0); NativeMethods.SendMessage(hWnd, NativeMethods.LB_SETHORIZONTALEXTENT, 0, 0); } }
/// <summary> /// Signals the system that an accessibility event occurred. /// The notification will be sent for the specified view only. /// </summary> /// <param name="accessibilityEvent">One of the predefined EVENT_OBJECT_* or EVENT_SYSTEM_* constants.</param> /// <param name="row">row index for item.</param> /// <param name="column">column index for item.</param> /// <param name="treeControl">The VirtualTreeControl that contains the object that generated the event.</param> public static void Notify(int accessibilityEvent, int row, int column, VirtualTreeControl treeControl) { Debug.Assert(ShouldNotify(accessibilityEvent, treeControl)); if ((treeControl == null) || (row < 0) || (column < 0)) { return; } // Add the accessibleObject to the circular array and generate an ID for it. var accessibleObjectId = Instance.InternalAddObject(treeControl, row, column); // Create a HandleRef object for the hwnd. // (A HandleRef structure wraps a managed object holding a // handle to a resource that is passed to unmanaged code. // Wrapping a handle with HandleRef guarantees that the managed // object is not garbage collected until the platform invoke call completes.) var viewHandleRef = new HandleRef(treeControl, treeControl.Handle); // Notify the system of the event. NativeMethods.NotifyWinEvent( accessibilityEvent, // Specifies the event that occurred viewHandleRef, // Handle to the window that contains the object that generated the event. accessibleObjectId, // Generated object ID that uniquely identifies the accessibleObject (for use by WM_GETOBJECT). NativeMethods.CHILDID_SELF); // CHILDID_SELF means the event was generated by the object itself, not a child object. }
internal void Restore(VirtualTreeControl ctl) { var itemCount = ctl.ItemCount; if (itemCount == 0) { if (restoreSelection != null || restoreCaret >= 0) { // fire selection change, as we cannot restore the selection or caret. ctl.DoSelectionChanged(); } return; } var hWnd = ctl.Handle; if (restoreSelection != null) { // The old selection is still there, make sure we clear it before restoring ctl.ClearSelection(false); var upper = restoreSelection.GetUpperBound(0) + 1; for (var i = 0; i < upper; ++i) { // UNDONE: Be smarter about this and do ranges in addition to // individual items. if (restoreSelection[i] != -1 && restoreSelection[i] < itemCount) { ctl.SetSelected(restoreSelection[i], true); } } } if (startingListCount > 0) { if (restoreCaret >= 0 && restoreCaret < itemCount) { try { if (!caretMoved) { ctl.SetStateFlag(VTCStateFlags.RestoringSelection, true); } if (restoreColumn != startColumn) { ctl.SetSelectionColumn(restoreColumn, false); } if (ctl.GetStyleFlag(VTCStyleFlags.ExtendedMultiSelect)) { // Last parameter is a little strange. If there is no anchor, then the caret // should not be selected, which is the normal behavior of the routine. ctl.SetCurrentExtendedMultiSelectIndex( restoreCaret, false, true, (restoreAnchorIndex == -1) ? ModifySelectionAction.Clear : ModifySelectionAction.None); } else { ctl.CurrentIndex = restoreCaret; } } finally { if (!caretMoved) { ctl.SetStateFlag(VTCStateFlags.RestoringSelection, false); } } } ctl.TopIndex = restoreTop; if (restoreXPos != 0) { NativeMethods.SendMessage(hWnd, NativeMethods.LB_SETHORIZONTALEXTENT, restoreHExtent, 0); NativeMethods.SetScrollPos(hWnd, NativeMethods.ScrollBarType.Horizontal, restoreXPos, true); NativeMethods.SendMessage( hWnd, NativeMethods.WM_HSCROLL, NativeMethods.MAKELONG((int)NativeMethods.ScrollAction.ThumbPosition, restoreXPos), 0); NativeMethods.SendMessage(hWnd, NativeMethods.WM_HSCROLL, (int)NativeMethods.ScrollAction.EndScroll, 0); } if (restoreAnchorIndex >= 0 && restoreAnchorIndex < itemCount) { ctl.AnchorIndex = restoreAnchorIndex; } } }
public AccessibleObjectEntry(int index) { // empty entry _index = index; _entryReuseCounter = 0; _treeControl = null; _row = 0; _column = 0; }
public ToolTipControl(VirtualTreeControl parent) { myParent = parent; myLastString = String.Empty; SetStyle(ControlStyles.UserPaint, true); BackColor = SystemColors.Info; ForeColor = SystemColors.InfoText; }
public void PositionTipWindow(VirtualTreeControl ctl) { // measure the string, set up the window var tipString = Marshal.PtrToStringAuto(myStringBuffer); int stringWidth, stringHeight; using (var g = CreateGraphics()) { stringWidth = ctl.ListItemStringWidth(g, Font, tipString); stringHeight = Math.Max( StringRenderer.MeasureString(UseCompatibleTextRendering, g, tipString, Font, myFormat).Height, ctl.myTextHeight); } var textDimsInt = new Size(); textDimsInt.Width = stringWidth; textDimsInt.Height = stringHeight; var windowRect = new Rectangle(ctl.PointToScreen(myFullLabelRectangle.Location), textDimsInt); // add padding for the client rectangle windowRect.Inflate(1, 1); // move window into screen space, clip, and set the position // To determine the screen to show the tip on, we could use Screen.FromRectangle(tipRect), // Screen.FromPoint(tipRect.Location), Screen.FromPoint(current mouse position), or // Screen.FromPoint(activating mouse position). I chose the last option. var offScreenEdge = false; var screenBounds = Screen.FromPoint(myActivatingMousePos).WorkingArea; if (windowRect.Left < screenBounds.Left) { offScreenEdge = true; windowRect.X = screenBounds.X; } else if (windowRect.Right > screenBounds.Right) { offScreenEdge = true; windowRect.X = screenBounds.X + screenBounds.Width - windowRect.Width; } if (windowRect.Bottom > screenBounds.Bottom) { offScreenEdge = true; windowRect.Y = screenBounds.Y + screenBounds.Height - windowRect.Height; } NativeMethods.SetWindowPos( Handle, IntPtr.Zero, windowRect.Left, windowRect.Top, windowRect.Width, windowRect.Height, NativeMethods.SetWindowPosFlags.SWP_NOACTIVATE | NativeMethods.SetWindowPosFlags.SWP_NOZORDER); // find the point in the client rect to draw the text rect if (!offScreenEdge) { myTextRect = new RectangleF( PointToClient(ctl.PointToScreen(myFullLabelRectangle.Location)), new SizeF(textDimsInt.Width, textDimsInt.Height)); } else { var rect = NativeMethods.RECT.FromXYWH(windowRect.X, windowRect.Y, windowRect.Width, windowRect.Height); NativeMethods.SendMessage(Handle, NativeMethods.TTM_ADJUSTRECT, 0, out rect); myTextRect = new RectangleF( PointToClient(new Point(rect.left, rect.top)), new SizeF(textDimsInt.Width, textDimsInt.Height)); } }
public HeaderContainer(VirtualTreeControl associatedControl) { SetStyle(ControlStyles.ContainerControl, true); SetStyle(ControlStyles.Selectable, false); Size = new Size(0, 0); TabStop = false; Font = associatedControl.Font; myHeader = associatedControl.CreateHeaderControl(); Controls.Add(myHeader); }