2008-10-24 11 views

Antwort

8

Nein, es gibt keine Methode für den Zugriff auf oder die Standardschaltfläche Text Messagebox zu umleiten.

Der einzige Weg, dies zu tun, ist Ihre eigene oder nur eine von vielen kostenlos sind aus dem Internet verwenden, um Code:

Free MsgBoxGo!

17

Nr.
Sie müssen ein benutzerdefiniertes Formular mit FormBorderType = FixedDialog machen.
ist hier ein kleines Tutorial:

Erstellen von Dialogfeldern in .NET

von James D. Murray auf Jun.12, 2007, unter 70-526

Microsoft Certification Exam: 70 -526 (MCTS)
Ziel: Erstellen und verwenden Sie benutzerdefinierte Dialogfelder in Windows Forms-Anwendungen.
Sprache: Visual Basic 2005 (hier klicken für die C# -Version dieses Eintrags)

Ich erinnere mich an das erste Mal, dass ich ein Dialogfeld, in einer .NET-Anwendung erstellen benötigt, die ich in C# zu schreiben. Da ich ein langjähriger Visual Basic-Programmierer bin, ging ich davon aus, dass dies leicht mithilfe einer Dialogfeldvorlage, die in Visual Studio.NET enthalten ist, erreicht werden konnte. Zu meiner Überraschung gab es für C# keine solche Formularvorlage, obwohl dies für Visual Basic 2005 der Fall ist. Nachdem ich mehrere Bücher und Webseiten mit Informationen zur Windows Forms 2.0-Programmierung durchforstet hatte, wurden mir grundlegende Schritte zur manuellen Konvertierung eines .NET-Formular in einem Windows-Dialogfeld:

Schritt 1: Fügen Sie ein Formular zu Ihrem .NET-Projekt hinzu und nennen Sie es "DialogBoxForm".

Schritt 2: Lassen Sie zwei Schaltflächen im unteren rechten Bereich des Formulars fallen und nennen Sie sie "OKButton" und "CancelButton".

Schritt 3: Ändern Sie die folgenden Eigenschaften des Formulars sein Aussehen und Verhalten anzupassen wie ein Standard-Dialogfeld zu sein:

 
    Property  Value     Description 
    ----------------------------------------------------------------------------------------------------------------------------- 
    AcceptButton OK button instance  Causes form to return value DialogResult.OK. Only used on modal dialog boxes. 
    CancelButton Cancel button instance Causes form to return value DialogResult.Cancel. Only used on modal dialog boxes. 
    FormBorderStyle FixedDialog    Create a non-sizable form with no control box on the title bar. 
    HelpButton  True The Help button appears in the caption bar next to the Close button. The ControlBox property must be True for these buttons to be visible. 
    MaximizeBox  False Hide the Maximize button in the title bar. 
    MinimizeBox  False Hide the Minimize button in the title bar. 
    ShowIcon  False The title bar icon is not visible in a dialog box. 
    ShowInTaskBar False Do not indicate the presence of the form on the Windows Task Bar. 
    Start   Position CenterParent The initial position of a dialog box is over its parent form. 
    Size   As Needed The fixed size needed for the dialog box. 

Diese Eigenschaften das Eigenschaftsfenster mit für das Formular festgelegt werden kann, oder mit in der Load-Ereignisse platziert Code der Form:

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 

Schritt 4: Fügen Sie die folgenden Button-Klick-Ereignishandler auf die Form:

 
    Private Sub OKButton_Click(ByVal sender As Object, _ByVal e As EventArgs) 
     ' User clicked the OK button 
     Me.DialogResult = Windows.Forms.DialogResult.OK 
    End Sub 

    Private Sub CancelButton_Click(ByVal sender As Object, _ByVal e As EventArgs) 
     ' User clicked the Cancel button 
     Me.DialogResult = Windows.Forms.DialogResult.Cancel 
    End Sub 

Schritt 5: Fügen Sie Eigenschaften, die Sie Daten in und aus dem Dialogfeld, wie Sie es für jede Form verschieben müssen:

 
    Private _LoginName As String 
    Private _LoginPassword As String 

    Public Property LoginName() As String 
     Get 
      Return _LoginName 
     End Get 
     Set(ByVal value As String) 
      _LoginName = value 
     End Set 
    End Property 

    Public Property LoginPassword() As String 
     Get 
      Return _LoginPassword 
     End Get 
     Set(ByVal value As String) 
      _LoginPassword = value 
     End Set 
    End Property 

Schritt 6: das Dialogfeld anzeigen modal durch den Showdialog() aufgerufen wird von die Form:

 
    Public Sub ShowDialogBox() 
     Dim dialog As New DialogBoxForm 

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

     If dialog.ShowDialog() = Windows.Forms.DialogResult.OK Then 
      Debug.WriteLine("Login Name: " & dialog.LoginName) 
      Debug.WriteLine("Password: " & dialog.LoginPassword) 
     Else 
      ' User clicked the Cancel button 
     End If 
    End Sub 

Schritt 7: das Dialogfeld modelessly anzuzeigen, rufen Sie die Show() -Methode von DialogBoxForm statt. Sie müssen einen Event-Handler an das Close-Ereignis von DialogBoxForm hinzufügen zu wissen, wann der Benutzer das Dialogfeld wird geschlossen:

 
    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 
+0

Dies ist die beste Lösung, die ich dafür gefunden habe. Sehr einfaches Tutorial, genau was ich brauchte. (VB.NET, speziell nicht C#) –

+0

Jetzt nicht verfügbar, aber hier archiviert http://web.archive.org/web/20101103044008/http://www.techexams.net/blogs/70-526/creating-dialog-boxes-in-net/ – Urbycoz

13

MessageBox verwendet ein einfaches Fenster, das wie jedes andere Fenster durchsucht werden kann. Das ist in Windows schon sehr lange, schon weit über 20 Jahre möglich. Die Techniken werden jedoch obskurer, zu viele freundliche Klassen-Wrapper, die die native Winapi verstecken und nicht alles aufdecken, was Sie damit tun können. So sehr, dass Programmierer nun automatisch davon ausgehen, dass dies nicht möglich ist, wie Sie an den Antworten erkennen können. Es ist die Art von Programmierung, die Petzold uns in seinem bahnbrechenden Buch "Programming Windows" beigebracht hat. Das Ersetzen von MessageBox durch ein benutzerdefiniertes Formular oder Fenster ist eigentlich ziemlich schwierig, es macht nicht-triviales automatisches Layout für den Text und unterstützt die Lokalisierung ohne Hilfe. Obwohl das genau das ist, was du nicht zu mögen scheinst :)

Anyhoo, das Nachrichtenfenster ist leicht zu finden. Es gehört dem UI-Thread und hat einen speziellen Klassennamen, der es einzigartig macht. EnumThreadWindows() listet die Windows auf, die einem Thread gehören. Mit GetClassName() können Sie die Art des Fensters überprüfen. Dann stecke den Text einfach mit SetWindowText() in die Schaltfläche.

Fügen Sie Ihrem Projekt eine neue Klasse hinzu und fügen Sie den unten gezeigten Code ein. Rufen Sie es mit Code wie folgt:

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

Hier ist der Code:

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 
+0

9 Jahre seit dieser Lösung zur Verfügung gestellt und interessanteste Lösung für mich :) aber, wie man das gleiche mit 'inputbox' tun? Meiner Meinung nach verdient diese Lösung viel mehr Upvotes – nelek

2

gibt es eine Lösung. Durch die Installation eines CBT-Hooks ist es möglich, eine Vielzahl von visuellen Einstellungen der MessageBox im laufenden Betrieb anzupassen: Nachrichten- und Schaltflächenschriftarten, Dialoghintergrund, Dialogpositionierung, Symbole, Schaltflächenbeschriftungen, Timeout und sogar das Einfügen zusätzlicher Steuerelemente.

Komplettlösung: Erweiterte MessageBox .NET Assembly http://www.news2news.com/vfp/?solution=5

Es ist eine voll funktionsfähige Testversion, die reguläre Version vollständigen C# Quellcode enthält.

1

Fügen Sie dies der Schaltfläche hinzu, von der der Dialog angezeigt werden soll. Dies ist ein benutzerdefiniertes Formular 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"); 
      } 
    } 

Diesen Code zu messageBox hinzufügen.

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(); 
    } 
0

Hier ist ein C# Schnipsel, die eine Win32 Haken verwendet die Taste Bildunterschriften (Das von http://icodesnip.com/snippet/csharp/custom-messagebox-buttons) zu verändern:

 [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); 
     } 
1

Die Lösung von Daniel Nolan, Code in 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