2010-03-27 21 views
9

Tôi đang triển khai kiểm soát tùy chỉnh kế thừa từ Control. Tôi muốn nó được tập trung (nó là một loại hộp danh sách).Tôi có thực sự phải gọi Focus trong OnMouseDown của Điều khiển tùy chỉnh của mình không?

Trong constructor, tôi làm

SetStyle(ControlStyles.Selectable, true); 

tôi bây giờ có thể sử dụng Tab để di chuyển để kiểm soát.

Tuy nhiên, khi điều khiển nhận được nhấp chuột, nó không tự động xác nhận tiêu điểm. Tôi có thể làm việc xung quanh điều này, tất nhiên:

protected override void OnMouseDown(MouseEventArgs e) 
{ 
    Focus(); 
    base.OnMouseDown(e); 
} 

Nhưng điều này giống như một kludge không cần thiết. Đây thực sự là con đường để đi? Hoặc có cách nào để yêu cầu Control tự động lấy tiêu điểm khi nhận được nhấp chuột không?

+0

@Thomas: bạn đề cập đến "Tôi đã có hình chữ nhật tiêu điểm tại chỗ": bạn có đang làm điều này bằng cách cưỡi OnGotFocus và OnLostFocus và gọi ControlPaint.DrawFocusRectangle không? Đánh giá cao bất kỳ phản hồi nào. – BillW

+1

@BillW: Đúng, đó là những gì tôi làm. 'OnGotFocus' và' OnLostFocus' làm mất hiệu lực hình chữ nhật có chứa hình chữ nhật lấy nét; 'OnPaint' kiểm tra thuộc tính' Focused' và gọi 'ControlPaint.DrawFocusRectangle' nếu cần. – Thomas

+0

câu trả lời của bệnh nhân cho câu hỏi của tôi được nhiều người đánh giá cao! Tôi gửi một câu trả lời nhiều hơn là cách duy nhất tôi có thể nhận được điều này để làm việc trong Visual Studio RC1 biên soạn với FrameWork 3.5 (đầy đủ). Bởi "công việc": Tôi có nghĩa là khi Control được "tabbed-to:" nó nhận được một hình chữ nhật lựa chọn được hiển thị, và khi "tabbed-away-from" hình chữ nhật lựa chọn biến mất: và khi nhấn vào Control sẽ hiển thị hình chữ nhật lựa chọn. – BillW

Trả lời

4

Tháo gỡ để giải cứu! Hóa ra là

SetStyle(ControlStyles.UserMouse, true); 

thực hiện thủ thuật.

Trớ trêu thay, tôi đã đọc trong documentation:

UserMouse: Nếu đúng, việc kiểm soát thực hiện chế biến chuột riêng của mình, và các sự kiện chuột không được xử lý bởi hệ điều hành.

Điều đó dường như hoàn toàn trái ngược với những gì tôi muốn, vì vậy tôi chỉ cố gắng đặt nó thành false ... Cách để đi, tài liệu WinForms.

+2

Điều này không chính xác. Việc tắt kiểu UserMouse chỉ nên được thực hiện đối với các trình bao bọc lớp kiểm soát xung quanh các điều khiển gốc thực hiện xử lý thông điệp chuột của riêng chúng. Bạn cho phép điều khiển lấy tiêu điểm vì bạn quan tâm đến các sự kiện đầu vào. Cố tình biến chế độ xử lý sự kiện đầu vào không có ý nghĩa. –

+0

Câu "bộ điều khiển xử lý chuột của chính nó" gây nhầm lẫn hơn trong ánh sáng làm rõ của bạn: điều khiển * WinForms * có chế biến chuột riêng (ghi đè 'OnMouseDown', v.v.) hay điều khiển * native * làm tự chế biến chuột (có nghĩa là điều khiển WinForms nên tránh xa nó)? Dù sao, dường như 'UserMouse' là' false' theo mặc định. Và vì tôi không gói một điều khiển bản địa, nó phải là 'đúng', đúng không? – Thomas

+0

Có, nó gọi phương thức OnMouseDown. Mà bạn sẽ ghi đè để cung cấp cho kiểm soát của riêng bạn hành vi chuột của nó. Giống như cho nó sự tập trung. Điều khiển của bạn kế thừa từ Kiểm soát, không có kiểm soát Windows gốc được bao bọc (như ListBox hoặc TreeView). Nó chỉ là một cửa sổ đơn giản. –

2

Có, bạn nên làm gì. Có nhiều điều khiển không có một cách có ý nghĩa để tập trung. PictureBox, Panel là những ví dụ hay. Bất cứ thứ gì xuất phát từ ContainerControl. Control.OnMouseDown() do đó không tự động gọi Focus() trong OnMouseDown().

Chỉ cần ghi đè phương thức OnMouseDown là không đủ, bạn cũng nên làm rõ với người dùng rằng điều khiển của bạn có tiêu điểm. Vì vậy, cô ấy sẽ có một ý tưởng nơi mà các nét bàn phím đi. Điều đó đòi hỏi phải ghi đè OnPaint() để bạn có thể vẽ hình chữ nhật lấy nét. ControlPaint.DrawFocusRectangle() là một cài đặt boilerplate cho điều đó.

Nhưng lấy tiêu điểm thực sự chỉ hữu ích nếu bạn làm điều gì đó có ý nghĩa với thông điệp bàn phím. Vì vậy, bạn sẽ phải ghi đè OnKeyDown và/hoặc OnKeyPressed là tốt. Và hiển thị phản hồi cho người dùng để cô ấy có thể xem những gì cô ấy đã nhập. Nếu bạn không có triển khai hữu ích cho điều đó, bạn không nên lấy tiêu điểm. Đó là lý do PictureBox không.

+0

Điểm tốt, nhưng tại sao bạn nghĩ tôi muốn kiểm soát được tập trung ngay từ đầu? Tôi đã có hình chữ nhật tập trung tại chỗ, và bây giờ đang làm việc trên các trình xử lý bàn phím. – Thomas

+3

Luôn luôn đề cập đến những loại chi tiết này trong câu hỏi. –

+0

Tôi đã đề cập trong ngoặc đơn rằng đó là một loại hộp danh sách, loại sắp xếp ngụ ý rằng nó sẽ xử lý các phím bấm; Tôi không muốn đánh lạc hướng vấn đề bằng cách đề cập đến tất cả các chi tiết này. Nhưng bạn nói đúng: nó là tốt để cung cấp thông tin về phần "tại sao bạn sẽ muốn điều đó", bởi vì đôi khi nó chỉ ra rằng bạn thực sự muốn giải quyết hoặc phá vỡ các vấn đề cơ bản một cách hoàn toàn khác nhau! – Thomas

0
  1. biên dịch trong một dự án WinForms cho FrameWork 3.5

  2. kéo một thể hiện của Control1 từ ToolBox vào một bề mặt mẫu ... đảm bảo tài sản tabstop của nó được thiết lập để 'true

  3. đặt một số điều khiển khác trên biểu mẫu.

  4. xác minh rằng khi thể hiện của Control1 được gắn thẻ thành: nó hiển thị hình chữ nhật lựa chọn biến mất khi bạn "tab away" khỏi nó.

  5. xác minh xem bạn có nhấp vào thể hiện của Control1 mà nó hiển thị hình chữ nhật lựa chọn hay không và nếu bạn nhấp vào một số điều khiển khác nó sẽ biến mất.

    namespace testFocusableControl 
    { 
        // VS Studio 2010 RC1 : Tested against FrameWork 3.5 Full (not 'Client) 
    
        public class Control1 : Control 
        { 
         public Control1() 
         { 
          SetStyle(ControlStyles.UserMouse, true); 
         } 
    
         protected override void OnLostFocus(EventArgs e) 
         { 
          this.Invalidate(); 
          base.OnLostFocus(e); 
         } 
    
         protected override void OnGotFocus(EventArgs e) 
         { 
          this.Invalidate(); 
          base.OnGotFocus(e); 
         } 
    
         protected override void OnPaint(PaintEventArgs e) 
         { 
          if (this.Focused) 
          { 
           ControlPaint.DrawFocusRectangle(e.Graphics, this.ClientRectangle, Color.Red, Color.Blue); 
          } 
          base.OnPaint(e); 
         } 
        } 
    } 
    

duy nhất "lỏng lẻo kết thúc" ở đây đối với tôi là rằng giải pháp này sẽ hiển thị các hình chữ nhật lựa chọn trên một con chuột nhấp chuột, nhưng tôi đã không thực hiện bất kỳ mã MouseDown như Thomas đề nghị.

Lưu ý rằng nếu bạn thực hiện Điều khiển phía trên 'ContainerControl qua' SetStyle (ControlStyles.ContainerControl, true); và thêm một số điều khiển khác vào nó, ngay cả khi bạn đặt thuộc tính TabStop của điều khiển được thêm thành 'false: ... nếu nó được nhấp ... nó sẽ lấy tiêu điểm và bạn sẽ mất hình chữ nhật tiêu điểm được hiển thị trên ContainerControl.

+1

Các phương thức bạn đánh dấu là '// no effect' không hoạt động vì bạn khai báo chúng là' virtual', không phải 'override'. Rõ ràng 'UserPaint' và' Selectable' mặc định là 'true'. Như # 6: không hiểu mã của bạn luôn xấu, bất kể mã có hoạt động hay không. Nhưng tôi nghĩ bây giờ chúng ta hiểu những gì và không hoạt động * và * tại sao, đúng không? :) – Thomas

+0

+1 Rất cám ơn, Thomas vì những hiểu biết của bạn. Tôi đã sửa đổi mã để kết hợp thông tin của bạn. ! – BillW

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