Derived Treeview override not being called at all.
-
I have the following treeview class whose purpose is to draw an overlay on the icons in a node. Notice it overrides "OnDrawNode":
/// /// A method that is supplied to the OverlayTreeView class to retrieve the overlay for a particular node
///
/// The node being drawn
///
public delegate Image GetTreeIconOverlayMethod(TreeNode node);public class OverlayTreeView : TreeView
{
bool drawOverlay;
int iconHeight;
int iconWidth;public GetTreeIconOverlayMethod GetIconOverlay { get; set; } public OverlayTreeView() { } protected override void OnHandleCreated(EventArgs e) { base.OnHandleCreated(e); if (ImageList != null) { drawOverlay = true; iconHeight = ImageList.ImageSize.Height; iconWidth = ImageList.ImageSize.Width; } } protected override void OnDrawNode(DrawTreeNodeEventArgs e) { base.OnDrawNode(e); Image overlay = null; if (drawOverlay) if (GetIconOverlay != null) if (!((e.Node.ImageIndex == -1) && (e.Node.ImageKey == null))) overlay = GetIconOverlay(e.Node); if (overlay != null) { int x = e.Node.Bounds.X + iconWidth - overlay.Width; int y = e.Node.Bounds.Y + iconHeight - overlay.Height; e.Graphics.DrawImage(overlay, x, y); } }
}
The overlay is not being drawn and it seems this is because the override is not being called at all. Any breakpoint put in this method does NOT gte triggered even though a breakpoint in OnHandleCreated is. It doesn't matter where I put the breakpoint within the method. (And yes... symbols are loaded). I have no idea why this would occur...
-
I have the following treeview class whose purpose is to draw an overlay on the icons in a node. Notice it overrides "OnDrawNode":
/// /// A method that is supplied to the OverlayTreeView class to retrieve the overlay for a particular node
///
/// The node being drawn
///
public delegate Image GetTreeIconOverlayMethod(TreeNode node);public class OverlayTreeView : TreeView
{
bool drawOverlay;
int iconHeight;
int iconWidth;public GetTreeIconOverlayMethod GetIconOverlay { get; set; } public OverlayTreeView() { } protected override void OnHandleCreated(EventArgs e) { base.OnHandleCreated(e); if (ImageList != null) { drawOverlay = true; iconHeight = ImageList.ImageSize.Height; iconWidth = ImageList.ImageSize.Width; } } protected override void OnDrawNode(DrawTreeNodeEventArgs e) { base.OnDrawNode(e); Image overlay = null; if (drawOverlay) if (GetIconOverlay != null) if (!((e.Node.ImageIndex == -1) && (e.Node.ImageKey == null))) overlay = GetIconOverlay(e.Node); if (overlay != null) { int x = e.Node.Bounds.X + iconWidth - overlay.Width; int y = e.Node.Bounds.Y + iconHeight - overlay.Height; e.Graphics.DrawImage(overlay, x, y); } }
}
The overlay is not being drawn and it seems this is because the override is not being called at all. Any breakpoint put in this method does NOT gte triggered even though a breakpoint in OnHandleCreated is. It doesn't matter where I put the breakpoint within the method. (And yes... symbols are loaded). I have no idea why this would occur...
The
OnDrawNode
method is used by the base class to raise theDrawNode
event. According to the documentation[^], that event is only raised if "theDrawMode
property is set to aTreeViewDrawMode
value other thanNormal
." It's therefore safe to assume that theOnDrawNode
method won't be called ifDrawMode
is set toNormal
.
"These people looked deep within my soul and assigned me a number based on the order in which I joined." - Homer
-
The
OnDrawNode
method is used by the base class to raise theDrawNode
event. According to the documentation[^], that event is only raised if "theDrawMode
property is set to aTreeViewDrawMode
value other thanNormal
." It's therefore safe to assume that theOnDrawNode
method won't be called ifDrawMode
is set toNormal
.
"These people looked deep within my soul and assigned me a number based on the order in which I joined." - Homer
So what method would I override to add the overlay no matter what draw mode is being used? I can't find one, except perhaps OnPaint... but I would think Microsoft would have included a default drawnode method to use regardless of the draw method. Since the point of my class is to add the overlay, I wouldn't want a potential user of the class to have to specify a draw mode. (I know there are workarounds... but to me forcing us to use them doesn't make a whole lot of sense to me, especially considering the complexity of drawing a tree node).
-
So what method would I override to add the overlay no matter what draw mode is being used? I can't find one, except perhaps OnPaint... but I would think Microsoft would have included a default drawnode method to use regardless of the draw method. Since the point of my class is to add the overlay, I wouldn't want a potential user of the class to have to specify a draw mode. (I know there are workarounds... but to me forcing us to use them doesn't make a whole lot of sense to me, especially considering the complexity of drawing a tree node).
There isn't one. The method is called in response to an unmanaged
WM_
message, which will only be sent to the control if it's set to be owner-drawn. Windows Forms controls are thin wrappers around native Windows controls. They can't add functionality that the native controls don't support.
"These people looked deep within my soul and assigned me a number based on the order in which I joined." - Homer
-
There isn't one. The method is called in response to an unmanaged
WM_
message, which will only be sent to the control if it's set to be owner-drawn. Windows Forms controls are thin wrappers around native Windows controls. They can't add functionality that the native controls don't support.
"These people looked deep within my soul and assigned me a number based on the order in which I joined." - Homer
Alright. Thanks
-
I have the following treeview class whose purpose is to draw an overlay on the icons in a node. Notice it overrides "OnDrawNode":
/// /// A method that is supplied to the OverlayTreeView class to retrieve the overlay for a particular node
///
/// The node being drawn
///
public delegate Image GetTreeIconOverlayMethod(TreeNode node);public class OverlayTreeView : TreeView
{
bool drawOverlay;
int iconHeight;
int iconWidth;public GetTreeIconOverlayMethod GetIconOverlay { get; set; } public OverlayTreeView() { } protected override void OnHandleCreated(EventArgs e) { base.OnHandleCreated(e); if (ImageList != null) { drawOverlay = true; iconHeight = ImageList.ImageSize.Height; iconWidth = ImageList.ImageSize.Width; } } protected override void OnDrawNode(DrawTreeNodeEventArgs e) { base.OnDrawNode(e); Image overlay = null; if (drawOverlay) if (GetIconOverlay != null) if (!((e.Node.ImageIndex == -1) && (e.Node.ImageKey == null))) overlay = GetIconOverlay(e.Node); if (overlay != null) { int x = e.Node.Bounds.X + iconWidth - overlay.Width; int y = e.Node.Bounds.Y + iconHeight - overlay.Height; e.Graphics.DrawImage(overlay, x, y); } }
}
The overlay is not being drawn and it seems this is because the override is not being called at all. Any breakpoint put in this method does NOT gte triggered even though a breakpoint in OnHandleCreated is. It doesn't matter where I put the breakpoint within the method. (And yes... symbols are loaded). I have no idea why this would occur...
Works for me: Override 'OnCreateControl and set the 'TreeViewDrawMode Property ... with either 'DrawMode == 'OwnerDrawText or 'OwnerDrawAll: 'OnDrawNode will be called.
protected override void OnCreateControl()
{{if (DrawMode != TreeViewDrawMode.OwnerDrawText) { DrawMode = TreeViewDrawMode.OwnerDrawText; } base.OnCreateControl();
}
«The mind is not a vessel to be filled but a fire to be kindled» Plutarch
-
There isn't one. The method is called in response to an unmanaged
WM_
message, which will only be sent to the control if it's set to be owner-drawn. Windows Forms controls are thin wrappers around native Windows controls. They can't add functionality that the native controls don't support.
"These people looked deep within my soul and assigned me a number based on the order in which I joined." - Homer
Richard Deeming wrote:
There isn't one.
See my answer below for a solution.
«The mind is not a vessel to be filled but a fire to be kindled» Plutarch