tags:

views:

643

answers:

3
+1  Q: 

Help "?" button

How can add this button to the title bar in WPF, by it being so used in a lot of applications I thought it would be built in or something, but looks like it isn't. Anyway let me know if you know anything about this.

Thanks.

Edit:

Isn't there anything equivalent to this?

Basically, to have the ? icon in win forms, all you need to do is this:

public Form1()
{
    InitializeComponent();

    this.HelpButton = true;
    this.MaximizeBox = false;
    this.MinimizeBox = false;
}

Doesn't WPF have anything like that?

A: 

No help buttons come out of the box with WPF. Should'nt be a push to roll your own however.

Jason Watts
To the title bar? Seems like you'd need to change the Window chrome, which is documented, but not trivial.
micahtan
And not a best practice, either. Instead, I see WPF apps which mock up their own title bars, also not ideal.
Drew Hoskins
@Drew: Yeah, that's the only solution I've seen so far and it doesn't seem very good to me. Specially because we already have tons of dialog boxes and it wouldn't be good to go to each and mock up the title bar.
Carlo
A: 

If you intend to add button to the non-client area, take a look at this article.

Magnus Johansson
+4  A: 

It's simple, just inset this code into your Window class.

This code uses interop to remove the WS_MINIMIZEBOX and WS_MAXIMIZEBOX styles and add the WS_EX_CONTEXTHELP extended style (the question mark will only show up if you remove the minimize and maximize buttons).

EDIT: added click detection on the help button, this is done by hooking into the WndProc using HwndSource.AddHook and listening for a WM_SYSCOMMAND message with wParam of SC_CONTEXTHELP.

When a click is detected this code will show a message box, changing this into an event, routed event or even a command (for MVVM apps) is left as an exercise for the reader.

private const uint WS_EX_CONTEXTHELP = 0x00000400;
private const uint WS_MINIMIZEBOX = 0x00020000;
private const uint WS_MAXIMIZEBOX = 0x00010000;
private const int GWL_STYLE = -16;
private const int GWL_EXSTYLE = -20;
private const int SWP_NOSIZE = 0x0001;
private const int SWP_NOMOVE = 0x0002;
private const int SWP_NOZORDER = 0x0004;
private const int SWP_FRAMECHANGED = 0x0020;
private const int WM_SYSCOMMAND = 0x0112;
private const int SC_CONTEXTHELP  = 0xF180;


[DllImport("user32.dll")]
private static extern uint GetWindowLong(IntPtr hwnd, int index);

[DllImport("user32.dll")]
private static extern int SetWindowLong(IntPtr hwnd, int index, uint newStyle);

[DllImport("user32.dll")]
private static extern bool SetWindowPos(IntPtr hwnd, IntPtr hwndInsertAfter, int x, int y, int width, int height, uint flags);


protected override void OnSourceInitialized(EventArgs e)
{
    base.OnSourceInitialized(e);
    IntPtr hwnd = new System.Windows.Interop.WindowInteropHelper(this).Handle;
    uint styles = GetWindowLong(hwnd, GWL_STYLE);
    styles &= 0xFFFFFFFF ^ (WS_MINIMIZEBOX | WS_MAXIMIZEBOX);
    SetWindowLong(hwnd, GWL_STYLE, styles);
    styles = GetWindowLong(hwnd, GWL_EXSTYLE);
    styles |= WS_EX_CONTEXTHELP;
    SetWindowLong(hwnd, GWL_EXSTYLE, styles);
    SetWindowPos(hwnd, IntPtr.Zero, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED);   
    ((HwndSource)PresentationSource.FromVisual(this)).AddHook(HelpHook);
}

private IntPtr HelpHook(IntPtr hwnd,
        int msg,
        IntPtr wParam,
        IntPtr lParam,
        ref bool handled)
{
    if (msg == WM_SYSCOMMAND &&
            ((int)wParam & 0xFFF0) == SC_CONTEXTHELP)
    {
        MessageBox.Show("help");
        handled = true;
    }
    return IntPtr.Zero;
}
Nir
this works, one more question: How do I add a OnClick handler to the "?" button?
Carlo
I've added the code to detect clicks on the help button, hope this helps
Nir
Worked like a charm. Thanks!
Carlo
Fantastic! I would up you more than one if I could... However, I cant really say that I agree that it is as "simple" as you say ;-)Thanks!
Victor