2010-03-01 40 views
7

Có, đây lại là câu hỏi này:Làm thế nào bạn có thể thay đổi màu phông chữ của một điều khiển hỗ trợ chủ đề?

Làm cách nào để thay đổi màu phông chữ của một TCheckBox (hoặc bất kỳ điều khiển được xử lý nào) bằng Delphi7-> Delphi2007 trên một ứng dụng đã bật chủ đề?

Sau khi đọc rất nhiều trên internet và trên trang web này, tôi thấy 4 loại câu trả lời:

  1. và Hầu hết populare (thậm chí từ QC): Bạn không có thể, nó được thiết kế như thế bởi Microsoft.
  2. Tạo thành phần cho phép bạn vẽ nó theo ý muốn.
  3. Mua bộ thành phần đắt tiền thu hút như bạn muốn.
  4. Không sử dụng chủ đề.

OK, nhưng tôi vẫn không hài lòng với điều đó.

Cung cấp cho người dùng phản hồi màu về trạng thái của thuộc tính/dữ liệu mà anh ta có trên biểu mẫu, có vẻ hợp pháp đối với tôi.

Sau đó, tôi vừa cài đặt phiên bản MSVC# 2008 Express và thật bất ngờ, họ có thể thay đổi màu của phông chữ (thuộc tính ForeColor của hộp kiểm) Sau đó, sao?

Nó dường như không phải là "nó được thiết kế như vậy, bởi Microsoft." thì bây giờ câu hỏi lại:

Làm cách nào để thay đổi màu phông chữ của một TCheckBox (hoặc bất kỳ điều khiển được xử lý nào) với Delphi 7 thông qua Delphi 2007 trên một ứng dụng hỗ trợ chủ đề?

+0

Điều gì làm cho bạn nghĩ các nhà phát triển của Visual Studio không chỉ đơn giản là sử dụng tùy chọn 2? –

+0

Vâng, tôi không phải, trong khi cố gắng tái sản xuất rằng "nó được thiết kế như vậy, bởi Microsoft." trên C#. Tôi đã đặt ForeColor thành Đỏ và nhận chú thích màu đỏ cho hộp kiểm của mình. –

Trả lời

0

Tùy chọn 5. Sử dụng quyền điều khiển như tùy chọn cơ sở và ghi đè tất cả các thông báo vẽ trong điều khiển (có bạn có thể gọi nó là thành phần nhưng điều khiển là tên cho các thành phần hiển thị, vì vậy bạn nên sử dụng điều đó). Đơn giản chỉ cần nắm bắt WM_PAINT, có thể WM_NCPAINT bạn có thể vẽ điều khiển theo phong cách riêng của bạn. Ít nhất bạn có thể tái sử dụng toàn bộ chức năng từ điều khiển. Miễn là bạn không thay đổi cách bố trí, chỉ có các màu sắc bạn sẽ không cần phải thay đổi các mousedowns hittests. up di chuyển vv vv

Lưu ý: Tôi có kinh nghiệm với việc ghi đè TCustomEdit để cho phép tất cả các loại màu, văn bản nền, nút phụ vv .. Phải mất khá nhiều thời gian để đọc đúng và đọc tất cả tài liệu từ MSDn và KB để đảm bảo kiểm soát đã làm những gì tôi muốn nó làm.

+0

Tôi hiểu rằng không phải là tùy chọn 5, nhưng tùy chọn 2a và tùy chọn 2 của tôi là tùy chọn 2b; ^)! Nhưng tại sao C# không cần phải ghi đè lên biến tần wm_paint để thay đổi màu của màu phông chữ của thành phần Checkbox? –

+0

@Edouard. Có gì trong một tên .. về C# không cần nó: C# có lớp điều khiển riêng của nó (Microsoft phát minh một cái mới cho môi trường .NET mỗi năm rất nhiều), Delphi sử dụng các điều khiển tương tự tồn tại từ Windows 95. Do đó nhiều ổn định hơn nhưng đôi khi bạn trả tiền cho rằng một cái gì đó đơn giản trở nên khó khăn hơn; GDI là cũ nhưng tôi nghĩ rằng trong 10 năm GDi vẫn còn xung quanh và những gì bạn nên làm gì với ứng dụng WinForms của bạn? Nghĩ về điều đó! –

+0

Tôi biết rằng GDI là khá cũ, tôi bắt đầu làm việc với nó, khi tôi đã làm bước đầu tiên của tôi trên Borland Object pascal trên "windows 2" một cái gì đó như 1988. Những gì bạn đang nói là: C# có thể làm điều đó, bởi vì họ đang sử dụng một bó khác nhau của các điều khiển hơn so với một được sử dụng bởi delphi trong khi chủ đề được kích hoạt? Như điều Theme có trách nhiệm vẽ các công cụ mới, tôi sẽ giả sử rằng delphi đang sử dụng các thành phần tương tự (ort ít nhất là thư viện) hơn C# sử dụng. –

2

Ồ, nhưng bạn có thể!

Chỉ cần đặt này trước việc kê khai của mẫu của bạn:

TCheckBox = class(StdCtrls.TCheckBox) 
public 
    procedure CNCtlColorStatic(var Message: TWMCtlColorStatic); message CN_CTLCOLORSTATIC; 
end; 

này lại tuyên bố TCheckBox hiện đang sử dụng tại thời gian chạy như các loại trực tiếp từ DFM của mẫu của bạn. Bây giờ hãy triển khai thông báo như thế này:

procedure TCheckBox.CNCtlColorStatic(var Message: TWMCtlColorStatic); 
begin 
    SetTextColor(Message.ChildDC, ColorToRGB(clRed)); // or RGB(255,0,0)); 
    SetBkMode(Message.ChildDC, TRANSPARENT); 
    Message.Result := GetStockObject(NULL_BRUSH); 
end; 

Điều này bẫy thông báo WM_CTLCOLORSTATIC và thay đổi màu văn bản thành màu đỏ. Điều này hoạt động ở chế độ không theo chủ đề cho tôi (sử dụng WinXP classic) - nhưng không ở chế độ theo chủ đề.

Bạn nên biết rằng để cho phép các điều khiển theo chủ đề gửi cho bạn thông báo này, kiểm soát sẽ cung cấp cờ DTPB_USECTLCOLORSTATIC cho API của chủ đề vẽ. Đáng buồn thay, đó không phải là hành vi mặc định, và tôi cũng không biết cách thực hiện nó. Hãy xem câu hỏi this.

1

Đây là cách tôi giải quyết này trong ứng dụng của tôi:

  1. Tháo chú thích từ hộp kiểm và làm cho nó nhỏ hơn - chỉ cần đủ lớn để hiển thị các hộp kiểm thực tế mà không có chú thích.
  2. Đặt TLabel bên cạnh hộp kiểm để làm phụ đề.
  3. Trong sự kiện OnClick của Nhãn, hãy chuyển đổi trạng thái của hộp kiểm.
  4. Nếu nhãn có bộ gia tốc bàn phím Alt + letter, hãy làm cho biểu mẫu xử lý thông báo CM_DIALOGCHAR. Sao chép trình xử lý tin nhắn từ mã nguồn của TLabel và thêm một dòng để chuyển trạng thái của hộp kiểm.

Đó không phải là hộp kiểm thực, và nó hoạt động nhiều hơn tôi muốn, nhưng nó hoạt động đủ tốt trong ứng dụng của tôi (chỉ có một hộp kiểm cần điều trị này).

4

này cần một số tinh chỉnh để có giải pháp hoàn hảo nhưng làm việc cho tôi:

Thêm 2 phương pháp để thành phần hộp kiểm của bạn

FOriginalCaption: string; 
    _MySetCap: Boolean; 
    procedure WMPaint(var msg: TWMPaint); message WM_PAINT; 
    procedure CMTextChanged(var Message: TMessage); message CM_TEXTCHANGED; 

và thực hiện theo cách này:

procedure TMyCheckbox.CMTextChanged(var Message: TMessage); 
begin 
    inherited; 
    if _MySetCap then Exit; 
    FOriginalCaption := Caption; 
end; 

procedure TMyCheckbox.WMPaint(var msg: TWMPaint); 
var 
    BtnWidth: Integer; 
    canv: TControlCanvas; 
begin 
    BtnWidth := GetSystemMetrics(SM_CXMENUCHECK); 

    _MySetCap := True; 
    if not (csDesigning in ComponentState) then 
    Caption := ''; 
    _MySetCap := False; 
    inherited; 
    canv := TControlCanvas.Create; 
    try 
    canv.Control := Self; 
    canv.Font := Font; 
    SetBkMode(canv.Handle, Ord(TRANSPARENT)); 
    canv.TextOut(BtnWidth + 1, 2, FOriginalCaption); 
    finally 
    canv.Free; 
    end; 
end; 
+0

Tôi tin rằng điều này nên được đánh dấu là câu trả lời, công việc tốt đẹp! –

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