Как мне изменить название ColorDialog?

Я раскручиваю ColorDialog компонент в WinForms, позволяющий пользователю выбрать цвет фона и цвет переднего плана конкретного пользовательского элемента управления. Оба параметра конфигурации находятся на одной странице диалогового окна конфигурации, поэтому я хочу установить заголовок диалогового окна цвета на "Цвет фона", когда диалоговое окно вызывается для изменения фона диаграммы, и на "Цвет сетки" для изменения цвета сетки. Это обеспечит полезный UX, где пользователь сможет посмотреть на заголовок диаграммы, если он не уверен, что он решил изменить цвет фона или сетки.

К сожалению, в документах, похоже, не упоминается какой-либо способ манипулирования ColorDialog название Можно ли сделать это изменение? Если так, то как?

4 ответа

Решение

К сожалению, изменение заголовка диалогового окна выбора цвета невозможно. Возможное решение состоит в том, чтобы найти или создать элемент управления для выбора цвета для размещения в выделенной форме, которой, конечно же, можно назначить соответствующий заголовок. Или вы можете выбрать стиль выбора цвета Office в виде поля со списком.

РЕДАКТИРОВАТЬ

Вдохновленный ответом Роба, я нашел следующее решение. Он включает в себя наследование от ColorDialog, отрыв HWND от метода HookProc и вызов SetWindowText через P/Invoke:

public class MyColorDialog : ColorDialog
{
    [DllImport("user32.dll")]
    static extern bool SetWindowText(IntPtr hWnd, string lpString);

    private string title = string.Empty;
    private bool titleSet = false;

    public string Title
    {
        get { return title; }
        set
        {
            if (value != null && value != title)
            {
                title = value;
                titleSet = false;
            }
        }
    }

    protected override IntPtr HookProc(IntPtr hWnd, int msg, IntPtr wparam, IntPtr lparam)
    {
        if (!titleSet)
        {
            SetWindowText(hWnd, title);
            titleSet = true;
        }

        return base.HookProc(hWnd, msg, wparam, lparam);
    }
}

Я публикую это как справку о том, как я это сделал. Я использовал WM_INITDIALOG (как указано в моем комментарии к ответу Тормода)

/// <summary>
/// The standard ColorDialog dialog box with a title property.
/// </summary>
public class ColorDialogWithTitle : ColorDialog
{
    private const int InitDialogMessage = 0x0110; // WM_INITDIALOG

    /// <summary>
    /// Initializes a new instance of the ColorDialogWithTitle class.
    /// </summary>
    public ColorDialogWithTitle() :
        base()
    {
        this.Title = Resources.ColorDialogWithTitle_DefaultTitle;

        return;
    }

    /// <summary>
    /// Gets or sets the title that will be displayed on the dialog when it's shown.
    /// </summary>
    [Browsable(true)]
    [Category("Appearance")]
    [Description("The title that will be displayed on the dialog when it's shown.")]
    public string Title
    {
        get;
        set;
    }

    /// <summary>
    /// The hook into the dialog's WndProc that we can leverage to set the
    /// window's text.
    /// </summary>
    /// <param name="hWnd">The handle to the dialog box window.</param>
    /// <param name="msg">The message being received.</param>
    /// <param name="wparam">Additional information about the message.</param>
    /// <param name="lparam">More additional information about the message.</param>
    /// <returns>
    /// A zero value if the default dialog box procedure processes the
    /// message, a non-zero value if the default dialog box procedure 
    /// ignores the message.
    /// </returns>
    [SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.UnmanagedCode)]
    protected override IntPtr HookProc(IntPtr hWnd, int msg, IntPtr wparam, IntPtr lparam)
    {
        if (msg == InitDialogMessage)
        {
            // We'll ignore failure cases for now.  The default text isn't 
            // so bad and this isn't library code.
            SafeNativeMethods.SetWindowText(hWnd, this.Title);
        }

        return base.HookProc(hWnd, msg, wparam, lparam);
    }
}

Предполагая, что ColorDialog предоставляет свой hWnd (у меня на этом компьютере нет Visual Studio для проверки), вы можете использовать Win32 SetWindowText API. Подпись PInvoke можно найти на PInvoke.net.

Я публикую это на случай, если другие столкнутся с этим в ближайшие годы.

Использование функции SetWindowText() в событии OnShow() работает нормально. Я не уверен, какая версия Delphi представила TColorDialog.OnShow, но она восходит по крайней мере к XE2.

procedure TForm1.ColorDialog1Show(Sender: TObject);
  begin
  SetWindowText(ColorDialog1.Handle, MyTitle);
  end;

В своих целях я использую глобальную переменную для MyTitle и назначаю соответствующий текст перед вызовом ColorDialog1.Execute.

Другие вопросы по тегам