2009-06-25 33 views
5

Trong C# .NET 2.0, tôi có một ComboBox WinForms với ComboBoxStyle DropDownList. Tuy nhiên, trình đơn thả xuống xuất hiện bất cứ khi nào người dùng nhấp vào bất kỳ đâu trên hộp tổ hợp. Thay vào đó, tôi muốn nó chỉ mở khi người dùng nhấp chuột một cách rõ ràng vào nút thả xuống. Khi người dùng nhấp vào phần còn lại của hộp kết hợp, tôi chỉ muốn gán cho nó tiêu điểm bàn phím để họ có thể sử dụng một số lệnh bàn phím trên mục đã chọn. Cách tốt nhất để làm điều này là gì?Làm cách nào để buộc một ComboBox kiểu DropDownList chỉ mở khi người dùng nhấp vào nút thả xuống?

Trả lời

4

Sau một số sự giúp đỡ từ những câu trả lời khác, tôi đến giải pháp này nhanh chóng:

public class MyComboBox : ComboBox 
{ 
    public MyComboBox() 
    { 
     FlatStyle = FlatStyle.Popup; 
     DropDownStyle = ComboBoxStyle.DropDownList; 
    } 

    protected override void WndProc(ref Message m) 
    { 
     if (m.Msg == 0x0201 /* WM_LBUTTONDOWN */ || m.Msg == 0x0203 /* WM_LBUTTONDBLCLK */) 
     { 
      int x = m.LParam.ToInt32() & 0xFFFF; 
      if (x >= Width - SystemInformation.VerticalScrollBarWidth) 
       base.WndProc(ref m); 
      else 
      { 
       Focus(); 
       Invalidate(); 
      } 
     } 
     else 
      base.WndProc(ref m); 
    } 
} 
0

Bạn có thể nhận được vị trí X, Y của nhấp chuột và từ đó bạn có thể buộc nó bị sập nếu nó không ở trên biểu tượng "thả xuống" (vì thiếu từ tốt hơn).

1

Bạn có hai vấn đề cần xem xét. Việc đầu tiên là khá đơn giản: xác định xem thả xuống nên được mở hoặc đóng. Mã này có thể làm điều đó:

void comboBox1_MouseClick(object sender, MouseEventArgs e) 
    { 
     ComboBox combo = sender as ComboBox; 
     int left = combo.Width - (SystemInformation.HorizontalScrollBarThumbWidth + SystemInformation.HorizontalResizeBorderThickness); 
     if (e.X >= left) 
     { 
      // They did click the button, so let it happen. 
     } 
     else 
     { 
      // They didn't click the button, so prevent the dropdown. 
     } 
    } 

Vấn đề thứ hai quan trọng hơn - thực sự ngăn chặn trình đơn thả xuống xuất hiện. Cách tiếp cận đơn giản nhất là:

comboBox1.DropDownStyle = ComboBoxStyle.DropDown; 

Nhưng điều đó cho phép nhập vào ô mà bạn không muốn.

Tôi dành khoảng 15 phút để xem các tùy chọn và dường như ngăn chặn trình đơn thả xuống xuất hiện đồng thời ngăn người dùng nhập vào menu thả xuống, bạn cần phải phân lớp kiểm soát. Bằng cách đó, bạn có thể ghi đè lên OnMouseClick() và chỉ gọi base.OnMouseClick() khi họ đã nhấp vào nút. Nó sẽ giống như thế này (chưa được kiểm tra):

public class CustomComboBox : ComboBox 
{ 
    protected override void OnMouseClick(MouseEventArgs e) 
    { 
     base.OnMouseClick(e); 

     int left = this.Width - (SystemInformation.HorizontalScrollBarThumbWidth + SystemInformation.HorizontalResizeBorderThickness); 
     if (e.X >= left) 
     { 
      // They did click the button, so let it happen. 
      base.OnMouseClick(e); 
     } 
     else 
     { 
      // They didn't click the button, so prevent the dropdown. 
      // Just do nothing. 
     } 
    } 
} 
+0

Chiều rộng thanh cuộn là hữu ích, nhưng sử dụng các sự kiện WinForms chuột/chức năng không hữu ích. Chúng được gọi là quá muộn. – Eric

+0

Các sự kiện và chức năng của WinForms được gọi cùng lúc với các thông báo Windows thông thường. Đó là việc xử lý chúng quan trọng. Tìm cách ngăn chặn hành vi mặc định là thử thách, vì thời gian là như nhau. –

+0

Tôi đã viết một cách ẩn dụ. Trong nội bộ, có vẻ như trước khi các sự kiện chuột WinForms được gọi là bao giờ, trình đơn thả xuống xuất hiện VÀ sự kiện thả xuống được gửi đi. Vì vậy, bằng cách sử dụng các sự kiện WinForms là không đủ để ngăn chặn thả xuống từ xuất hiện. – Eric

Các vấn đề liên quan