.net - جعل WinBorms TextBox تتصرف مثل شريط عنوان المستعرض الخاص بك




winforms user-interface (25)

عندما يتلقى مربع نص C # WinForms التركيز ، أريده أن يتصرف مثل شريط عناوين المتصفح.

لمعرفة ما أعنيه ، انقر في شريط عنوان متصفح الويب الخاص بك. ستلاحظ السلوك التالي:

  1. يجب أن يؤدي النقر في مربع النص إلى تحديد النص بالكامل إذا لم يكن مربع النص قد تم تركيزه مسبقًا.
  2. يجب أن يحدد الماوس لأسفل والسحب في مربع النص فقط النص الذي قمت بتحديده بالماوس.
  3. إذا كان مربع النص يركز بالفعل ، فإن النقر لا يحدد كل النص.
  4. التركيز على مربع النص برمجيا أو عن طريق لوحة المفاتيح tabbing يجب أن يحدد كل النص.

أريد أن أفعل هذا بالضبط في WinForms.

أسرع هجوم ALERT: يرجى قراءة ما يلي قبل الإجابة! شكرا يا شباب. :-)

لا يعمل الاتصال .SelectAll () أثناء أحداث .Enter أو .GotFocus لأنه إذا قام المستخدم بالنقر فوق مربع النص ، فسيتم وضع علامة الإقحام حيث يقوم بالنقر فوقها ، وبالتالي إلغاء تحديد كل النص.

لن يعمل الاتصال .SelectAll () أثناء حدث .Click نظرًا لأن المستخدم لن يتمكن من تحديد أي نص باستخدام الماوس ؛ ستحتفظ المكالمة .SelectAll () بالكتابة فوق تحديد نص المستخدم.

لا يعمل استدعاء BeginInvoke ((Action) textbox.SelectAll) على التركيز / دخول الحدث enter لأنه يخرق القاعدة # 2 أعلاه ، فإنه سيبقي على اختيار المستخدم في التركيز.


Answers

مجرد استخدام selectall () على دخول وانقر فوق الأحداث

private void textBox1_Enter(object sender, EventArgs e)
        {

            textBox1.SelectAll();
        }
        private void textBox1_Click(object sender, EventArgs e)
        {
            textBox1.SelectAll();
        }

حلمي هو بدائي جدا لكنه يعمل بشكل جيد لغرضي

private async void TextBox_GotFocus(object sender, RoutedEventArgs e)
{
    if (sender is TextBox)
    {
        await Task.Delay(100);
        (sender as TextBox).SelectAll();
    }
}

الحل الخاص بك جيد ، لكنه يفشل في حالة محددة. إذا كنت تعطي التركيز TextBox عن طريق تحديد نطاق من النص بدلاً من النقر فقط ، فلن يتم ضبط العلامة التي لم يتم تحديدها بالفعل على true ، لذلك عند النقر في مربع النص مرة ثانية ، يتم تحديد كل النص.

هنا هو نسختك من الحل. لقد وضعت أيضا رمز في فئة التي ترث TextBox ، لذلك يتم إخفاء المنطق بشكل جيد بعيدا.

public class MyTextBox : System.Windows.Forms.TextBox
{
    private bool _focused;

    protected override void OnEnter(EventArgs e)
    {
        base.OnEnter(e);
        if (MouseButtons == MouseButtons.None)
        {
            SelectAll();
            _focused = true;
        }
    }

    protected override void OnLeave(EventArgs e)
    {
        base.OnLeave(e);
        _focused = false;
    }

    protected override void OnMouseUp(MouseEventArgs mevent)
    {
        base.OnMouseUp(mevent);
        if (!_focused)
        {
            if (SelectionLength == 0)
                SelectAll();
            _focused = true;
        }
    }
}

يبدو أدناه للعمل. يعالج الحدث إدخال tabbing إلى عنصر التحكم ويعمل MouseDown عند النقر فوق عنصر التحكم.

    private ########### void textBox1_Enter(object sender, EventArgs e)
    {
        textBox1.SelectAll();
    }

    private void textBox1_MouseDown(object sender, MouseEventArgs e)
    {
        if (textBox1.Focused)
            textBox1.SelectAll();
    }

'Inside the Enter event
TextBox1.SelectAll();

حسنًا ، بعد تجربتها هنا ، ما تريده هو:

  • في الحدث Enter ، ابدأ علامة تشير إلى أنك كنت في حدث الإدخال
  • في الحدث Click ، ​​إذا قمت بتعيين العلامة ، استدعاء .SelectAll () وإعادة تعيين العلامة.
  • في حدث MouseMove ، عيّن العلامة التي تم إدخالها إلى false ، والتي ستسمح لك بالنقر فوق التمييز دون الحاجة إلى إدخال مربع النص أولاً.

حدّد هذا جميع النصوص عند الدخول ، ولكن سمح لي بتمييز جزء من النص بعد ذلك ، أو السماح لك بالتمييز عند النقرة الأولى.

حسب الطلب:

    bool entered = false;
    private void textBox1_Enter(object sender, EventArgs e)
    {
        entered = true;
        textBox1.SelectAll();   //From Jakub's answer.
    }

    private void textBox1_Click(object sender, EventArgs e)
    {
        if (entered) textBox1.SelectAll();
        entered = false;
    }

    private void textBox1_MouseMove(object sender, MouseEventArgs e)
    {
        if (entered) entered = false;
    }

بالنسبة لي ، يحدد tabbing في عنصر التحكم كل النص.


في الواقع GotFocus هو الحدث الصحيح (الرسالة حقا) التي تهتم بها ، لأنه بغض النظر عن كيفية الوصول إلى السيطرة ، فستحصل على هذا في نهاية المطاف. السؤال هو متى تستدعي SelectAll ().

جرب هذا:

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
        this.textBox1.GotFocus += new EventHandler(textBox1_GotFocus);
    }

    private delegate void SelectAllDelegate();    
    private IAsyncResult _selectAllar = null; //So we can clean up afterwards.

    //Catch the input focus event
    void textBox1_GotFocus(object sender, EventArgs e)
    {
        //We could have gotten here many ways (including mouse click)
        //so there could be other messages queued up already that might change the selection.
        //Don't call SelectAll here, since it might get undone by things such as positioning the cursor.
        //Instead use BeginInvoke on the form to queue up a message
        //to select all the text after everything caused by the current event is processed.
        this._selectAllar = this.BeginInvoke(new SelectAllDelegate(this._SelectAll));
    }

    private void _SelectAll()
    {
        //Clean-up the BeginInvoke
        if (this._selectAllar != null)
        {
            this.EndInvoke(this._selectAllar);
        }
        //Now select everything.
        this.textBox1.SelectAll();
    }
}

لقد وجدت حلا أبسط:

للتأكد من تحديد كافة النص عند النقر فوق مربع نص ، تأكد من أن "معالج النقر" يستدعي معالج "الإدخال". لا حاجة لمتغيرات إضافية!

مثال:

private void textBox1_Click(object sender, EventArgs e){
        textBox1_Enter(sender, e);
    }

private void textBox1_Enter(object sender, EventArgs e){
        TextBox tb = ((TextBox)sender);
        tb.SelectAll();
    }

لمجموعة من مربعات النص في نموذج:

private System.Windows.Forms.TextBox lastFocus;   

private void textBox_GotFocus(object sender, System.Windows.Forms.MouseEventArgs e)   
{
    TextBox senderTextBox = sender as TextBox;
    if (lastFocus!=senderTextBox){
        senderTextBox.SelectAll();
    }
    lastFocus = senderTextBox;   
}

أجد هذا العمل أفضل ، عند النقر بالماوس وعدم الإفراج عنه على الفور:

    private bool SearchBoxInFocusAlready = false;
    private void SearchBox_LostFocus(object sender, RoutedEventArgs e)
    {
        SearchBoxInFocusAlready = false;
    }

    private void SearchBox_PreviewMouseUp(object sender, MouseButtonEventArgs e)
    {
        if (e.ButtonState == MouseButtonState.Released && e.ChangedButton == MouseButton.Left &&
            SearchBox.SelectionLength == 0 && SearchBoxInFocusAlready == false)
        {
            SearchBox.SelectAll();
        }

        SearchBoxInFocusAlready = true;
    }

هذا العمل ل WPF / XAML TextBox.

    private bool initialEntry = true;
    private void TextBox_SelectionChanged(object sender, RoutedEventArgs e)
    {
        if (initialEntry)
        {
            e.Handled = true;
            initialEntry = false;
            TextBox.SelectAll();
        }
    }
    private void TextBox_GotFocus(object sender, RoutedEventArgs e)
    {
        TextBox.SelectAll();
        initialEntry = true;      
    }

إجابة سطر واحد أستخدمها ... قد تكون ركل نفسك ...

في أدخل الحدث:

txtFilter.BeginInvoke (new MethodInvoker (txtFilter.SelectAll))؛


SelectAll لم يعمل لي.

هذا يعمل.

ActiveControl = textBox1;
textBox1->SelectionStart = 0;
textBox1->SelectionLength = textBox1->Text->Length;

إنها kludgey صغيرة ، ولكن في حدث النقر الخاص بك ، استخدم SendKeys.Send( "{HOME}+{END}" ); .


فقط اشتقاق فئة من TextBox أو MaskedTextBox:

public class SMaskedTextBox : MaskedTextBox
{
    protected override void OnGotFocus(EventArgs e)
    {
        base.OnGotFocus(e);
        this.SelectAll();
    }
}

واستخدامها على النماذج الخاصة بك.


يمكن أن تكون الإجابة أكثر بساطة من كل ما سبق ، على سبيل المثال (في WPF):

public void YourTextBox_MouseEnter(object sender, MouseEventArgs e)
    {
        YourTextBox.Focus();
        YourTextBox.SelectAll();
    }

بالطبع لا أعرف كيف تريد استخدام هذا الرمز ، ولكن الجزء الرئيسي للنظر هنا هو: المكالمة الأولى. التركيز () ثم الاتصال .SelectAll ()؛


هذا مشابه للإجابة الشعبية لـ nzhenry ، لكني أجد أنه من الأسهل عدم استخدام فئة فرعية:

    Private LastFocused As Control = Nothing

Private Sub TextBox1_Enter(sender As Object, e As System.EventArgs) Handles TextBox1.Enter, TextBox2.Enter, TextBox3.Enter
    If MouseButtons = Windows.Forms.MouseButtons.None Then LastFocused = sender
End Sub

Private Sub TextBox1_Leave(sender As Object, e As System.EventArgs) Handles TextBox1.Leave, TextBox2.Leave, TextBox3.Leave
    LastFocused = Nothing
End Sub

Private Sub TextBox1_MouseUp(sender As Object, e As System.Windows.Forms.MouseEventArgs) Handles TextBox1.MouseUp, TextBox2.MouseUp, TextBox3.MouseUp
    With CType(sender, TextBox)
        If LastFocused IsNot sender AndAlso .SelectionLength = 0 Then .SelectAll()
    End With
    LastFocused = sender
End Sub

ضبط selction عند مغادرة السيطرة. سيكون هناك عند العودة. انقر فوق علامة التبويب حول النموذج وعند الرجوع إلى عنصر التحكم ، سيتم تحديد كافة النص.

إذا دخلت بالماوس ، فسيتم وضع علامة الإقحام في المكان الذي قمت بالنقر فوقه.

private void maskedTextBox1_Leave(object sender, CancelEventArgs e)
    {
        maskedTextBox1.SelectAll();
    }

ومن المثير للاهتمام ، و ComboBox مع DropDownStyle = بسيط لديه حد كبير بالضبط السلوك الذي تبحث عنه ، على ما أعتقد.

(إذا قمت بتقليل ارتفاع عنصر التحكم لعدم إظهار القائمة - ثم ببضع وحدات بكسل أكثر - لا يوجد فرق فعال بين ComboBox و TextBox.)


هذا يعمل لي في .NET 2005 -

    ' * if the mouse button is down, do not run the select all.
    If MouseButtons = Windows.Forms.MouseButtons.Left Then
        Exit Sub
    End If

 ' * OTHERWISE INVOKE THE SELECT ALL AS DISCUSSED.

وهنا وظيفة المساعد مع الحل إلى المستوى التالي - إعادة الاستخدام دون الوراثة.

    public static void WireSelectAllOnFocus( TextBox aTextBox )
    {
        bool lActive = false;
        aTextBox.GotFocus += new EventHandler( ( sender, e ) =>
        {
            if ( System.Windows.Forms.Control.MouseButtons == MouseButtons.None )
            {
                aTextBox.SelectAll();
                lActive = true;
            }
        } );

        aTextBox.Leave += new EventHandler( (sender, e ) => {
            lActive = false;
        } );

        aTextBox.MouseUp += new MouseEventHandler( (sender, e ) => {
            if ( !lActive )
            {
                lActive = true;
                if ( aTextBox.SelectionLength == 0 ) aTextBox.SelectAll();
            }   
        });
    }

لاستخدام هذا ببساطة استدعاء الدالة تمرير مربع نص ويعتني كافة بت فوضوي لك. أقترح توصيل جميع مربعات النص في الحدث Form_Load. يمكنك وضع هذه الوظيفة في النموذج الخاص بك ، أو إذا كان مثلي ، في مكان ما في فصل دراسي من أجل إعادة استخدام أكثر.


الحل التالي يعمل بالنسبة لي. لقد قمت بتجاوز حدث OnKeyUp و OnKeyUp لإبقاء نص TextBox محددًا دائمًا.

    public class NumericTextBox : TextBox
{
    private bool _focused;
    protected override void OnGotFocus(EventArgs e)
    {
        base.OnGotFocus(e);
        if (MouseButtons == MouseButtons.None)
        {
            this.SelectAll();
            _focused = true;
        }
    }
    protected override void OnEnter(EventArgs e)
    {
        base.OnEnter(e);
        if (MouseButtons == MouseButtons.None)
        {
            SelectAll();
            _focused = true;
        }
    }

    protected override void OnLeave(EventArgs e)
    {
        base.OnLeave(e);
        _focused = false;
    }

    protected override void OnMouseUp(MouseEventArgs mevent)
    {
        base.OnMouseUp(mevent);
        if (!_focused)
        {
            if (SelectionLength == 0)
                SelectAll();
            _focused = true;
        }
    }

    protected override void OnKeyUp(KeyEventArgs e)
    {
        base.OnKeyUp(e);

        if (SelectionLength == 0)
            SelectAll();
        _focused = true;
    }
    protected override void OnKeyDown(KeyEventArgs e)
    {
       base.OnKeyDown(e);
       if (SelectionLength == 0)
            SelectAll();
        _focused = true;
    }
}


حل بسيط جدا:

    private bool _focusing = false;

    protected override void OnEnter( EventArgs e )
    {
        _focusing = true;
        base.OnEnter( e );
    }

    protected override void OnMouseUp( MouseEventArgs mevent )
    {
        base.OnMouseUp( mevent );

        if( _focusing )
        {
            this.SelectAll();
            _focusing = false;
        }
    }

EDIT: كان OP الأصلي مهتمًا بشكل خاص بتسلسل الفأرة / اختيار النص / الماوس إلى أعلى ، وفي هذه الحالة سينتهي الأمر بالحل البسيط أعلاه بنص يتم اختياره جزئيًا.

يجب أن يحل هذا المشكلة * (في الممارسة أنا اعتراض WM_SETCURSOR):

    protected override void WndProc( ref Message m )
    {
        if( m.Msg == 32 ) //WM_SETCURSOR=0x20
        {
              this.SelectAll(); // or your custom logic here                
        }

        base.WndProc( ref m );
    }

* في الواقع ، ينتهي التسلسل التالي بنص جزئي ، ولكن إذا قمت بتحريك الماوس فوق مربع النص ، فسيتم تحديد كل النص مرة أخرى:

الفأرة لأسفل / تحديد النص / الفأرة - تحريك - خارج - textbox / mouse-up


أولا وقبل كل شيء ، شكرا على إجابات! 9 اجابات كاملة. شكرا لكم.

الأخبار السيئة: جميع الإجابات كان لها بعض المراوغات أو لم تعمل بشكل صحيح (أو على الإطلاق). لقد أضفت تعليقًا على كل مشاركاتك.

أخبار سارة: لقد وجدت طريقة لجعلها تعمل. هذا الحل بسيط جدًا ويبدو أنه يعمل في جميع السيناريوهات (التمرير إلى أسفل ، تحديد النص ، التركيز على الجدولة ، وما إلى ذلك)

bool alreadyFocused;

...

textBox1.GotFocus += textBox1_GotFocus;
textBox1.MouseUp += textBox1_MouseUp;
textBox1.Leave += textBox1_Leave;

...

void textBox1_Leave(object sender, EventArgs e)
{
    alreadyFocused = false;
}


void textBox1_GotFocus(object sender, EventArgs e)
{
    // Select all text only if the mouse isn't down.
    // This makes tabbing to the textbox give focus.
    if (MouseButtons == MouseButtons.None)
    {
        this.textBox1.SelectAll();
        alreadyFocused = true;
    }
}

void textBox1_MouseUp(object sender, MouseEventArgs e)
{
    // Web browsers like Google Chrome select the text on mouse up.
    // They only do it if the textbox isn't already focused,
    // and if the user hasn't selected all text.
    if (!alreadyFocused && this.textBox1.SelectionLength == 0)
    {
        alreadyFocused = true;
        this.textBox1.SelectAll();
    }
}

بقدر ما أستطيع أن أقول ، يتسبب هذا في جعل مربع النص يتصرف تمامًا مثل شريط عناوين متصفح الويب.

نأمل أن يساعد هذا الشخص القادم الذي يحاول حل هذه المشكلة البسيطة المخادعة.

شكرًا مجددًا يا شباب على جميع إجاباتك التي ساعدتني في الوصول إلى المسار الصحيح.


    string name = "Lisa";
    int age = 20;
    string str = $"Her name is {name} and she's {age} years old";

تسمى هذه السلسلة Interpolated String ، وهي عبارة عن سلسلة قالب تحتوي على تعبيرات بداخله.





.net winforms user-interface textbox