it-swarm.com.ru

Пользовательские заголовки кнопок в окне сообщений .NET?

Есть ли простой способ отобразить окно сообщения в VB.NET с пользовательскими заголовками кнопок? Я сталкивался с Какой простой способ создать MessageBox с пользовательским текстом кнопки в Managed C++?, в архивах переполнения стека, но это для Управляемый C++ .

19
subrama6

Нет, нет способа получить доступ или перенаправить текст кнопки окна сообщений по умолчанию.

Единственный способ сделать это - написать собственный код или использовать один из множества бесплатных из Интернета:

Бесплатный MsgBoxGo!

8
PersistenceOfVision

Нет.
Вам нужно будет создать собственную форму с помощью FormBorderType = FixedDialog.
Вот небольшой урок:

Создание диалоговых окон в .NET

Джеймсом Д. Мюрреем 12 июня 2007 года, под 70-526

Сертификационный экзамен Microsoft: 70-526 (MCTS)
Цель: создавать и использовать настраиваемые диалоговые окна в приложениях Windows Forms.
Язык: Visual Basic 2005 (нажмите здесь для версии C # этой записи)

Я помню первый раз, когда мне нужно было создать диалоговое окно в приложении .NET, которое я писал на C #. Будучи давним программистом на Visual Basic, я предполагал, что это легко сделать с помощью шаблона диалогового окна, включенного в Visual Studio.NET. К моему удивлению, такой шаблон формы для C # не существовал, хотя для Visual Basic 2005 он существует. После просмотра нескольких книг и веб-страниц, заполненных информацией о программировании Windows Forms 2.0, мне стал очевиден базовый набор шагов для преобразования вручную Форма .NET в диалоговом окне Windows:

Шаг 1. Добавьте форму в ваш проект .NET и назовите ее «DialogBoxForm».

Шаг 2: опустите две кнопки в нижней правой части формы и назовите их «OKButton» и «CancelButton».

Шаг 3. Измените следующие свойства формы, чтобы настроить ее внешний вид и поведение так, чтобы они выглядели как стандартное диалоговое окно:

 Значение свойства Описание 
 -------------------------------------------------- -------------------------------------------------- -------------------------
 AcceptButton Экземпляр кнопки OK Заставляет форму возвращать значение DialogResult.OK. Используется только в модальных диалоговых окнах .
 CancelButton Экземпляр кнопки отмены Заставляет форму возвращать значение DialogResult.Cancel. Используется только в модальных диалоговых окнах .
 FormBorderStyle FixedDialog Создать форму без размера без поля управления в строке заголовка .
 HelpButton True Кнопка «Справка» отображается на панели заголовков рядом с кнопкой «Закрыть». Свойство ControlBox должно иметь значение True, чтобы эти кнопки были видны .
 MaximizeBox False Скрыть кнопку «Развернуть» в строке заголовка .
 MinimizeBox False Скрыть кнопку «Свернуть» в строке заголовка .
 ShowIcon False Значок строки заголовка не отображается в диалоговом окне .
 ShowInTaskBar False Не указывать наличие формы на панели задач Windows .
 Начальная позиция CenterParent Начальная позиция диалогового окна находится над его родительской формой .
 Размер по мере необходимости Фиксированный размер, необходимый для диалогового окна .

Эти свойства можно установить с помощью окна «Свойства» для формы или с помощью кода, размещенного в событии загрузки формы:

    Me.AcceptButton = OKButton
    Me.CancelButton = CancelButton
    Me.FormBorderStyle = Windows.Forms.FormBorderStyle.FixedDialog
    Me.HelpButton = True
    Me.MaximizeBox = False
    Me.MinimizeBox = False
    Me.ShowInTaskbar = False
    Me.ShowIcon = False
    Me.StartPosition = FormStartPosition.CenterParent

Шаг 4. Добавьте в форму следующие обработчики событий нажатия кнопки:

 Private Sub OKButton_Click (отправитель ByVal как объект, _ByVal как объект EventArgs) 
 'Пользователь нажал кнопку OK 
 Me.DialogResult = Windows.Forms.DialogResult.OK 
 End Sub 

 Закрытый подпункт CancelButton_Click (отправитель ByVal как объект, _ByVal как объект EventArgs) 
 «Пользователь нажал кнопку« Отмена »
 Me.DialogResult = Windows.Forms.DialogResult.Cancel 
 End Sub 

Шаг 5. Добавьте свойства, необходимые для перемещения данных в диалоговое окно и из него, как для любой формы:

 Частное _LoginName As String 
 Частный _LoginPassword As String 

 Открытое свойство LoginName () As String 
 Получить
 Вернуть _LoginName 
 Конец Получить 
 Set (значение ByVal As String) 
 _LoginName = значение 
 Конец Set 
 Конечная недвижимость 

 Публичная собственность LoginPassword () As String 
 Получить
 Вернуть _LoginPassword 
 Конец Получить 
 Set (значение ByVal As String) 
 _LoginPassword = значение 
 Конец Set 
 Конечная недвижимость 

Шаг 6: Показать диалоговое окно модально, вызвав ShowDialog () формы:

 Public Sub ShowDialogBox () 
 Диалоговое окно как новый DialogBoxForm 

 dialog.LoginName = "JDMurray" 
 dialog.LoginPassword = String.Empty 

 Если dialog.ShowDialog () = Windows.Forms.DialogResult.OK Тогда 
 Debug.WriteLine («Имя для входа:» и dialog.LoginName) 
 Debug.WriteLine ("Пароль:" & dialog.LoginPassword) 
 Else 
 «Пользователь нажал кнопку« Отмена »
 Конец, если 
 End Sub 
Шаг 7: Чтобы отобразить диалоговое окно без режима, вместо этого вызовите метод Show () DialogBoxForm. Вам нужно будет добавить обработчик событий в событие Close DialogBoxForm, чтобы знать, когда пользователь закрывает диалоговое окно:

Public Sub ShowDialogBox () Диалоговое окно затемнения As DialogBoxForm = New DialogBoxForm dialog.LoginName = "JDMurray" dialog.Password = String.Empty AddHandler dialog.FormClosed, AddressOf dialog_FormClosed dialog.Show () 'Метод Show () возвращает немедленно End Sub Private Sub dialog_FormClosed (ByVal sender As Object, _ ByVal e As FormClosedEventArgs) 'Этот метод вызывается, когда пользователь закрывает диалоговое окно End Sub

    Public Sub ShowDialogBox()
        Dim dialog As DialogBoxForm = New DialogBoxForm
        dialog.LoginName = "JDMurray"
        dialog.Password = String.Empty
        AddHandler dialog.FormClosed, AddressOf dialog_FormClosed
        dialog.Show()

        ' The Show() method returns immediately
    End Sub

    Private Sub dialog_FormClosed(ByVal sender As Object, _

     ByVal e As FormClosedEventArgs)
        ' This method is called when the user closes the dialog box
    End Sub
18
BradC

MessageBox использует простое окно, которое может быть запутано как любое другое окно. Это было возможно в Windows очень давно, уже более 20 лет. Тем не менее, методы становятся неясными, слишком много дружественных обёрток класса, которые скрывают родной винапи и не раскрывают все, что вы можете с ним сделать. Настолько, что программисты теперь автоматически предполагают, что это невозможно, как вы можете судить по ответам, в которых проголосовали. Это тот тип программирования, которому Петзольд научил нас в своей оригинальной книге «Программирование Windows». Заменить MessageBox пользовательской формой или окном на самом деле довольно сложно, он выполняет нетривиальную автоматическую разметку по размеру текста и поддерживает локализацию без посторонней помощи. Хотя это именно то, что вам не нравится :)

Anyhoo, окно сообщения легко найти обратно. Он принадлежит потоку пользовательского интерфейса и имеет специальное имя класса, которое делает его уникальным. EnumThreadWindows () перечисляет окна, принадлежащие потоку, GetClassName () позволяет вам проверять тип окна. Затем просто вставьте текст в кнопку с помощью SetWindowText ().

Добавьте новый класс в ваш проект и вставьте код, показанный ниже. Вызовите его с кодом, подобным этому:

Nobugz.PatchMsgBox(New String() {"Da", "Njet"})
MsgBox("gack", MsgBoxStyle.YesNo)

Вот код:

Imports System.Text
Imports System.Runtime.InteropServices

Public Class Nobugz
  Private Shared mLabels() As String    '' Desired new labels
  Private Shared mLabelIndex As Integer '' Next caption to update

  Public Shared Sub PatchMsgBox(ByVal labels() As String)
    ''--- Updates message box buttons
    mLabels = labels
    Application.OpenForms(0).BeginInvoke(New FindWindowDelegate(AddressOf FindMsgBox), GetCurrentThreadId())
  End Sub

  Private Shared Sub FindMsgBox(ByVal tid As Integer)
    ''--- Enumerate the windows owned by the UI thread
    EnumThreadWindows(tid, AddressOf EnumWindow, IntPtr.Zero)
  End Sub

  Private Shared Function EnumWindow(ByVal hWnd As IntPtr, ByVal lp As IntPtr) As Boolean
    ''--- Is this the message box?
    Dim sb As New StringBuilder(256)
    GetClassName(hWnd, sb, sb.Capacity)
    If sb.ToString() <> "#32770" Then Return True
    ''--- Got it, now find the buttons
    mLabelIndex = 0
    EnumChildWindows(hWnd, AddressOf FindButtons, IntPtr.Zero)
    Return False
  End Function

  Private Shared Function FindButtons(ByVal hWnd As IntPtr, ByVal lp As IntPtr) As Boolean
    Dim sb As New StringBuilder(256)
    GetClassName(hWnd, sb, sb.Capacity)
    If sb.ToString() = "Button" And mLabelIndex <= UBound(mLabels) Then
      ''--- Got one, update text
      SetWindowText(hWnd, mLabels(mLabelIndex))
      mLabelIndex += 1
    End If
    Return True
  End Function

  ''--- P/Invoke declarations
  Private Delegate Sub FindWindowDelegate(ByVal tid As Integer)
  Private Delegate Function EnumWindowDelegate(ByVal hWnd As IntPtr, ByVal lp As IntPtr) As Boolean
  Private Declare Auto Function EnumThreadWindows Lib "user32.dll" (ByVal tid As Integer, ByVal callback As EnumWindowDelegate, ByVal lp As IntPtr) As Boolean
  Private Declare Auto Function EnumChildWindows Lib "user32.dll" (ByVal hWnd As IntPtr, ByVal callback As EnumWindowDelegate, ByVal lp As IntPtr) As Boolean
  Private Declare Auto Function GetClassName Lib "user32.dll" (ByVal hWnd As IntPtr, ByVal name As StringBuilder, ByVal maxlen As Integer) As Integer
  Private Declare Auto Function GetCurrentThreadId Lib "kernel32.dll" () As Integer
  Private Declare Auto Function SetWindowText Lib "user32.dll" (ByVal hWnd As IntPtr, ByVal text As String) As Boolean
End Class
16
Hans Passant

Есть решение. Установив зацепку CBT, можно на лету настроить широкий спектр визуальных настроек MessageBox: шрифты сообщений и кнопок, фон диалогов, расположение диалогов, значки, заголовки кнопок, время ожидания и даже вставку дополнительных элементов управления.

Полное решение: расширенная сборка MessageBox .NET http://www.news2news.com/vfp/?solution=5

Это полнофункциональная пробная версия, обычная версия включает полный исходный код C #.

2
Anatoliy Mogylevets

Решение Даниэля Нолана, код в VB.Net

<DllImport("kernel32.dll")> _
Private Shared Function GetCurrentThreadId() As UInteger
End Function

<DllImport("user32.dll", CharSet:=CharSet.Auto)> _
Private Shared Function CallNextHookEx(ByVal idHook As Integer, ByVal nCode As Integer, ByVal wParam As IntPtr, ByVal lParam As IntPtr) As Integer
End Function

<DllImport("user32.dll", CharSet:=CharSet.Auto)> _
Private Shared Function UnhookWindowsHookEx(ByVal idHook As Integer) As Boolean
End Function

<DllImport("user32.dll", CharSet:=CharSet.Auto)> _
Private Shared Function SetWindowsHookEx(ByVal idHook As Integer, ByVal lpfn As HookProc, ByVal hInstance As IntPtr, ByVal threadId As Integer) As Integer
End Function

<DllImport("user32.dll")> _
Private Shared Function SetDlgItemText(ByVal hWnd As IntPtr, ByVal nIDDlgItem As Integer, ByVal lpString As String) As Boolean
End Function

Private Delegate Function HookProc(ByVal nCode As Integer, ByVal wParam As IntPtr, ByVal lParam As IntPtr) As Integer

Shared dlgHookProc As HookProc

Private Const WH_CBT As Long = 5
Private Const HCBT_ACTIVATE As Long = 5

Private Const ID_BUT_OK As Integer = 1
Private Const ID_BUT_CANCEL As Integer = 2
Private Const ID_BUT_ABORT As Integer = 3
Private Const ID_BUT_RETRY As Integer = 4
Private Const ID_BUT_IGNORE As Integer = 5
Private Const ID_BUT_YES As Integer = 6
Private Const ID_BUT_NO As Integer = 7

Private Const BUT_OK As String = "Save"
Private Const BUT_CANCEL As String = "Cancelar"
Private Const BUT_ABORT As String = "Stop"
Private Const BUT_RETRY As String = "Continue"
Private Const BUT_IGNORE As String = "Ignore"
Private Const BUT_YES As String = "Si"
Private Const BUT_NO As String = "No"

Private Shared _hook As Integer = 0

Private Shared Function DialogHookProc(ByVal nCode As Integer, ByVal wParam As IntPtr, ByVal lParam As IntPtr) As Integer
  If nCode < 0 Then
    Return CallNextHookEx(_hook, nCode, wParam, lParam)
  End If

  If nCode = HCBT_ACTIVATE Then
    SetDlgItemText(wParam, ID_BUT_OK, BUT_OK)
    SetDlgItemText(wParam, ID_BUT_CANCEL, BUT_CANCEL)
    SetDlgItemText(wParam, ID_BUT_ABORT, BUT_ABORT)
    SetDlgItemText(wParam, ID_BUT_RETRY, BUT_RETRY)
    SetDlgItemText(wParam, ID_BUT_IGNORE, BUT_IGNORE)
    SetDlgItemText(wParam, ID_BUT_YES, BUT_YES)
    SetDlgItemText(wParam, ID_BUT_NO, BUT_NO)
  End If

  Return CallNextHookEx(_hook, nCode, wParam, lParam)
End Function

Private Sub btn_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btn.Click
  dlgHookProc = New HookProc(AddressOf DialogHookProc)

  _hook = SetWindowsHookEx(CInt(WH_CBT), dlgHookProc, IntPtr.op_Explicit(0), CInt(GetCurrentThreadId()))

  Dim dlgEmptyCheck As DialogResult = MessageBox.Show("Text", "Caption", MessageBoxButtons.YesNoCancel, MessageBoxIcon.Exclamation, MessageBoxDefaultButton.Button3)


  If dlgEmptyCheck = DialogResult.Abort Then
  End If

  UnhookWindowsHookEx(_hook)
End Sub
1
Miguel Yskatll

Код C # для выполнения той же задачи можно найти в статье на форуме MSDN, https://forums.Microsoft.com/MSDN/ShowPost.aspx?PostID=3087899&SiteID=1 .

1
balexandre

Добавьте это к кнопке, которую вы хотите, чтобы диалоговое окно отображалось из . Это пользовательская форма messageBox;

    private void DGroup_Click(object sender, EventArgs e)
    {
        messageBox m = new messageBox();
        m.ShowDialog();
        if (m.DialogResult == DialogResult.Yes)
        {
            //del(groups.php?opt=del&amp;id=613','asdasd');
            String[] asd = new String[2];
            asd[0] = "groups.php?opt=del&amp;id=613";
            asd[1] = "asdasd";
            addgroup.Document.InvokeScript("del",asd);
        }
        else
            if (m.DialogResult == DialogResult.No)
            {
                MessageBox.Show("App won´t close");
            }
    }

Добавьте этот код в messageBox.

    private void deleteGroupOnly_Click(object sender, EventArgs e)
    {
        this.DialogResult = DialogResult.Yes;
        this.Close();
    }

    private void deleteAll_Click(object sender, EventArgs e)
    {
        this.DialogResult = DialogResult.No;
        this.Close();
    }

    private void cancel_Click(object sender, EventArgs e)
    {
        this.DialogResult = DialogResult.Cancel;
        this.Close();
    }
1
Tassaduq

Вот фрагмент кода C #, который использует перехват Win32 для изменения заголовков кнопок (получен из http://icodesnip.com/snippet/csharp/custom-messagebox-buttons ):

        [DllImport("kernel32.dll")]
        static extern uint GetCurrentThreadId();

        [DllImport("user32.dll", CharSet = CharSet.Auto)]
        private static extern int CallNextHookEx(int idHook, int nCode, IntPtr wParam, IntPtr lParam);

        [DllImport("user32.dll", CharSet = CharSet.Auto)]
        private static extern bool UnhookWindowsHookEx(int idHook);

        [DllImport("user32.dll", CharSet = CharSet.Auto)]
        private static extern int SetWindowsHookEx(int idHook, HookProc lpfn, IntPtr hInstance, int threadId);

        [DllImport("user32.dll")]
        private static extern bool SetDlgItemText(IntPtr hWnd, int nIDDlgItem, string lpString);

        delegate int HookProc(int nCode, IntPtr wParam, IntPtr lParam);

        static HookProc dlgHookProc;

        private const long WH_CBT = 5;
        private const long HCBT_ACTIVATE = 5;

        private const int ID_BUT_OK = 1;
        private const int ID_BUT_CANCEL = 2;
        private const int ID_BUT_ABORT = 3;
        private const int ID_BUT_RETRY = 4;
        private const int ID_BUT_IGNORE = 5;
        private const int ID_BUT_YES = 6;
        private const int ID_BUT_NO = 7;

        private const string BUT_OK = "Save";
        private const string BUT_CANCEL = "Cancel";
        private const string BUT_ABORT = "Stop";
        private const string BUT_RETRY = "Continue";
        private const string BUT_IGNORE = "Ignore";
        private const string BUT_YES = "Yeeh";
        private const string BUT_NO = "Never";

        private static int _hook = 0;

        private static int DialogHookProc(int nCode, IntPtr wParam, IntPtr lParam)
        {
            if (nCode < 0)
            {
                return CallNextHookEx(_hook, nCode, wParam, lParam);
            }

            if (nCode == HCBT_ACTIVATE)
            {
                SetDlgItemText(wParam, ID_BUT_OK, BUT_OK);
                SetDlgItemText(wParam, ID_BUT_CANCEL, BUT_CANCEL);
                SetDlgItemText(wParam, ID_BUT_ABORT, BUT_ABORT);
                SetDlgItemText(wParam, ID_BUT_RETRY, BUT_RETRY);
                SetDlgItemText(wParam, ID_BUT_IGNORE, BUT_IGNORE);
                SetDlgItemText(wParam, ID_BUT_YES, BUT_YES);
                SetDlgItemText(wParam, ID_BUT_NO, BUT_NO);
            }

            return CallNextHookEx(_hook, nCode, wParam, lParam);
        }

        private void Button_Click(object sender, EventArgs e)
        {
            dlgHookProc = new HookProc(DialogHookProc);

            _hook = SetWindowsHookEx((int)WH_CBT, dlgHookProc, (IntPtr)0, (int)GetCurrentThreadId());

            DialogResult dlgEmptyCheck = MessageBox.Show("Text", "Caption", MessageBoxButtons.AbortRetryIgnore, MessageBoxIcon.Exclamation, MessageBoxDefaultButton.Button3);

            if (dlgEmptyCheck == DialogResult.Abort)
            {

            }

            UnhookWindowsHookEx(_hook);
        }
0
Dan Nolan