2012-01-04 17 views
13

Khi chuyển từ Delphi 2006 sang Delphi XE2, một trong những điều chúng ta học được là RichEdit 2.0 thay thế các cặp CRLF nội bộ với một đơn CR tính cách. Điều này có tác dụng không may của việc ném ra tất cả các tính toán chỉ mục ký tự dựa trên chuỗi văn bản thực tế ở phía bên VCL.Sử dụng ký tự CR đơn lẻ của RichEdit 2.0 để xóa các tính toán của SelStart (Delphi XE2)

Các hành vi tôi có thể nhìn thấy bằng cách truy tìm thông qua các mã VCL là như sau:

  1. Gửi nhắn WM_GETTEXT (thực hiện trong TControl.GetTextBuf) sẽ trả về một bộ đệm văn bản có chứa CRLF cặp.
  2. Gửi thông báo WM_GETTEXTLENGTH (được thực hiện trong TControl.GetTextLen) sẽ trả về một giá trị như thể văn bản vẫn còn chứa CRLF ký tự.
  3. Ngược lại, việc gửi thông báo EM_SETSELEX (tức là thiết lập SelStart) sẽ coi giá trị đầu vào như thể văn bản có chứa chỉCR ký tự.

Điều này làm cho tất cả mọi thứ thất bại (chẳng hạn như làm nổi bật cú pháp) trong ứng dụng của chúng tôi. Như bạn có thể nói, tất cả mọi thứ được tắt bởi chính xác một ký tự cho mỗi dòng mới cho đến thời điểm đó.

Rõ ràng, vì đây là hành vi không nhất quán, chúng ta phải thiếu điều gì đó hoặc làm điều gì đó rất sai.

Có ai khác có bất kỳ trải nghiệm nào với việc chuyển đổi từ RichEdit 1.0 sang kiểm soát RichEdit 2.0 và cách bạn giải quyết vấn đề này? Cuối cùng, có cách nào để buộc RichEdit 2.0 sử dụng các cặp CRLF giống như RichEdit 1.0 không?

+1

Tôi e rằng bạn sẽ phải tuân thủ điều này vì ['EM_SETSEL'] (http://msdn.microsoft.com/en-us/library/windows/desktop/bb761661%28v=vs.85%29 .aspx) là thông báo điều khiển chỉnh sửa chung, không phải là thông điệp chỉnh sửa phong phú. – TLama

+2

Theo như tôi biết, TRichEdit chỉ là một trình bao bọc cho điều khiển chỉnh sửa cửa sổ phong phú. Vì vậy, có thể không có nhiều bạn có thể làm nhưng để tính toán xung quanh này để có được vị trí chính xác. Hoặc bạn sử dụng một điều khiển khác như WPRichText. – Andreas

+1

'TRichEdit' không phù hợp với trình soạn thảo làm nổi bật cú pháp. Hãy xem xét sử dụng một thành phần trình soạn thảo cú pháp tô sáng thực tế, chẳng hạn như SynEdit (http://synedit.sourceforge.net). –

Trả lời

4

Chúng tôi cũng gặp vấn đề này rất lớn.

Chúng tôi thực hiện loại "kết hợp thư" trong đó chúng tôi có các mẫu có mã hợp nhất được phân tích cú pháp và được thay thế bằng dữ liệu từ các nguồn bên ngoài.

Chỉ mục này không khớp giữa pos (mystring, RichEdit.Text) và chỉ mục định vị vào văn bản RichEdit bằng RichText.SelStart đã phá vỡ sự hợp nhất của chúng tôi.

Tôi không có câu trả lời hay nhưng tôi đã đưa ra giải pháp thay thế. Đó là một chút cồng kềnh (understatment!) Nhưng cho đến khi một giải pháp tốt hơn đi kèm ...

Cách giải quyết là sử dụng TMemo ẩn và sao chép văn bản RichEdit vào nó và thay đổi cặp CR/LF thành CR. Sau đó sử dụng TMemo để tìm vị trí thích hợp bằng cách sử dụng pos (chuỗi, TMemo) và sử dụng để có được vị trí selstart để sử dụng trong TRichEdit.

Điều này thực sự hút nhưng hy vọng cách giải quyết này sẽ giúp những người khác trong hoàn cảnh của chúng tôi hoặc có thể châm ngòi cho ai đó thông minh hơn tôi để đưa ra giải pháp tốt hơn.

Tôi sẽ chỉ cho một chút mẫu mã ...

Vì chúng ta đang thay thế văn bản sử dụng seltext chúng ta cần phải thay thế văn bản trong cả kiểm soát RichEdit và kiểm soát TMemo để giữ hai đồng bộ.

StartToken và EndToken là các dấu phân cách mã kết hợp và là hằng số.

function TEditForm.ParseTest: boolean; 
var TagLength: integer; 
var ValueLength: integer; 
var ParseStart: integer; 
var ParseEnd: integer; 
var ParseValue: string; 
var Memo: TMemo; 
begin 
    Result := True;//Default 
    Memo := TMemo.Create(nil); 
    try 
    Memo.Parent := self; 
    Memo.Visible := False; 
    try 
     Memo.Lines.Clear; 
     Memo.Lines.AddStrings(RichEditor.Lines); 
     Memo.Text := stringreplace(Memo.Text,#13#10,#13,[rfReplaceAll]);//strip CR/LF pairs and replace with CR 

     while (Pos(StartToken, Memo.Text) > 0) and (Pos(EndToken, Memo.Text) > 0) do begin 
     ParseStart := Pos(StartToken, Memo.SelText); 
     ParseEnd := Pos(EndToken, Memo.SelText) + Length(EndToken); 
     if ParseStart >= ParseEnd then begin//oops, something's wrong - bail out 
      Result := true; 
      myEditor.SelStart := 0; 
      exit; 
     end; 
     TagLength := ParseEnd - ParseStart; 
     ValueLength := (TagLength - Length(StartToken)) - Length(EndToken); 
     ParseValue := Copy(Memo.SelText, (ParseStart + Length(StartToken)), ValueLength); 
     Memo.selstart := ParseStart - 1; //since the .text is zero based, but pos is 1 based we subtract 1 
     Memo.sellength := TagLength; 
     RichEditor.selstart := ParseStart - 1; //since the .text is zero based, but pos is 1 based we subtract 1 
     RichEditor.sellength := TagLength; 

     TempText := GetValue(ParseValue); 
     Memo.SelText := TempText; 
     RichEditor.SelText := TempText; 
     end; 

    except 
     on e: exception do 
      begin 
      MessageDlg(e.message,mtInformation,[mbOK],0); 
      result := false; 
      end; 
     end;//try..except 
    finally 
    FreeAndNil(Memo); 
    end; 
end; 
+1

Cũng giống như một lưu ý FYI: 'FreeAndNil (Memo)' là hoàn toàn không cần thiết; như 'Memo' là một biến cục bộ, và do đó đi ra khỏi phạm vi ở cuối' cuối cùng ', trong thủ tục, có hay không nó được đặt thành 'nil' là vô nghĩa. Chỉ cần gọi 'Memo.Free' là đủ 100% và IMO dễ đọc hơn. ('FreeAndNil' với tôi làm cho nó xuất hiện rằng' Memo' có phạm vi rộng hơn quy trình hiện tại.) –

+1

Trước hết, cảm ơn bạn rất nhiều vì đã trả lời của bạn. Tôi không nghĩ bạn thực sự cần một TMemo ẩn. Miễn là chúng ta đang nói cách giải quyết, tất cả những gì bạn phải làm là đếm số lượng các cặp CRLF lên đến vị trí mong muốn và sau đó trừ một từ sau này cho mỗi cặp tìm thấy. Số kết quả sẽ là SelStart của bạn. Tuy nhiên, ngay cả điều đó cũng không thực sự chấp nhận được, vì nó sẽ quá chậm và rườm rà. Tôi vẫn không thể tin rằng chúng tôi không bỏ lỡ điều gì đó hiển nhiên ở đây. – user1127813

+0

@Ken - đã đồng ý. Đây là nỗ lực đầu tiên của tôi để kludge một cái gì đó với nhau. Nó có thể sử dụng một số công việc. –

1

Làm cách nào để trừ EM_LINEFROMCHAR từ vị trí dấu mũ? (HOẶC vị trí của EM_GETSEL) cho dù bạn cần.

Bạn thậm chí có thể nhận được hai biến số EM_LINEFROMCHAR. Một từ bắt đầu lựa chọn và một từ vị trí quan tâm/lựa chọn mong muốn, nếu bạn chỉ muốn biết có bao nhiêu cặp cl/cr trong vùng chọn.

+0

Kính gửi Joshua, chào mừng bạn đến với Stack Overflow. - Bạn có nhận thấy rằng câu hỏi mà bạn trả lời là dành cho tuổi :-)? Vì vậy, đừng thất vọng nếu không có gì xảy ra sau câu trả lời của bạn. - Cố gắng sử dụng định dạng cú pháp thích hợp như OP đã làm: http://stackoverflow.com/help/formatting. - Các đề xuất như của bạn được đặt tốt hơn làm nhận xét. Tìm hiểu cách sử dụng chúng. Chúc may mắn! –