2

I am populating a WinForms TreeView control and setting the font attributes of each node differently as they are loaded.

The nodes also allow inline editing (changing the text by pressing F2, or clicking once selected like folder names in Windows Explorer).

When the node goes into edit mode though, the font used when editing reverts to the default font of the TreeView control, not that specific node's font.

Is it possible to set the font of the edit control used when editing each node, to match the font used for displaying that TreeView node? (If so, how?)

Cody Gray - on strike
  • 239,200
  • 50
  • 490
  • 574
Stuart Helwig
  • 9,318
  • 8
  • 51
  • 67

1 Answers1

4

As you said, an examination of the TreeNode source reveals that the node is using an Edit Control (from Windows UI Controls, not .NET Forms) when it goes into edit mode. I don't see anything in the class that will set the font in edit mode, so I think you will need to post messages directly to the Edit Control. Use TVM_GETEDITCONTROL to get a handle to it, and WM_SETFONT to set the font. You will probably want Font.ToHfont(), as well.

Edit: here's an example of how you can invoke SendMessage to accomplish the font change.

[DllImport("user32.dll")]
internal static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);

internal const int WM_SETFONT = 0x0030;
internal const int TVM_GETEDITCONTROL = 0x110F;

private void treeView1_BeforeLabelEdit(object sender, NodeLabelEditEventArgs e)
{
    TreeNode nodeEditing = e.Node;
    IntPtr editControlHandle = SendMessage(treeView1.Handle, (uint)TVM_GETEDITCONTROL, IntPtr.Zero, IntPtr.Zero);
    if (editControlHandle != IntPtr.Zero)
    {
        SendMessage(editControlHandle, (uint)WM_SETFONT, nodeEditing.NodeFont.ToHfont(), New IntPtr(1));
    }
}
Cody Gray - on strike
  • 239,200
  • 50
  • 490
  • 574
Kimberly
  • 2,657
  • 2
  • 16
  • 24
  • Brilliant. Works like a charm. I just came back to add the code I wrote on the back of your initial answer (as a sample)...and you'd already done it! Great stuff! – Stuart Helwig Apr 20 '11 at 02:39
  • @Stuart Wow, thanks. I'm glad you like it so much! Some people would be disappointed by a p/invoke solution. – Kimberly Apr 20 '11 at 02:54
  • I concur, a brilliant solution. I haven't seen you around the WinForms tag much, but I certainly hope to see answers like this more often! One minor nitpick, though: the `wParam` and `lParam` parameters should almost always be declared as `IntPtr`s, rather than `int`. They're handles in unmanaged code, not integers. This is particularly important for the `WM_SETFONT` message where the `wParam` represents an `HFONT`. Getting details like this right with P/Invoke signatures is the key to writing code that works properly complied for 64-bit platforms. – Cody Gray - on strike Apr 20 '11 at 04:56
  • @Cody Gray That's more an operative detail than a 'minor nitpick'! Thank you for pointing it out and making the change. I copied the signature from a Compact Framework usage. I knew to change the assembly name, but I've never noticed before that the parameter types are different (I rarely use p/invoke in the full Framework). I should have realized when I had to cast HFont to int to make it compile... Anyway, I learned something today, so thanks again. – Kimberly Apr 20 '11 at 21:42
  • Ah, and I know nothing about the Compact Framework. I suppose it's all 32-bit, making the distinction between integers and pointers irrelevant there? Anyway, that's the reason I'm suspicious of definitions found online at places like pinvoke.net. They are wonderful resources, but too often you find mistakes like this. I'm in the habit of checking the declarations myself against the WinAPI documentation for exactly that reason. – Cody Gray - on strike Apr 21 '11 at 07:19