2014-02-11 21 views
5

我試圖在RichEdit控制使用EM_SETTEXTMODE在Delphi 7爲什麼EM_SETTEXTMODE不起作用?

只需創建一個新的項目,添加一個TRichEdit控制和TButton控制和下面的代碼添加到該按鈕的點擊處理程序:

SendMessage(RichEdit1.Handle, WM_SETTEXT, 0, LPARAM(PChar(''))); 
    Button1.Caption := IntToStr(SendMessage(RichEdit1.Handle, EM_GETTEXTMODE, 0, 0)); 
    Button1.Caption := Button1.Caption + ' ' + IntToStr(SendMessage(RichEdit1.Handle, EM_SETTEXTMODE, TM_PLAINTEXT, 0)); 
    Button1.Caption := Button1.Caption + ' ' + IntToStr(SendMessage(RichEdit1.Handle, EM_GETTEXTMODE, 0, 0)); 

按鈕的標題設置爲38 0 38點擊按鈕後,這意味着該文本模式並沒有改變 - 它最初是38TM_RICHTEXT or TM_SINGLELEVELUNDO or TM_MULTICODEPAGE),然後SETTEXTMODE成功(0),但即使它是ST生病38

RichEdit的文本在使用EM_SETTEXTMODE之前按文檔建議清除。

我試過用EM_SETTEXTMODE設置不同的值,它總是保持38

我注意到EM_SETTEXTMODE總是返回0(成功),即使在調用它之前RichEdit控件包含文本。

我試過使用RichEdit1.Perform而不是SendMessage - 沒有區別。

我在這個問題的各種論壇上發現了幾個線程,並沒有解決任何問題。

任何想法爲什麼這不工作?

回答

9

較舊的Delphi版本加載位於RICHED32.DLL的RichEdit控件。 較新的Delphi版本加載RICHED20.DLL

RICHED32.DLL暴露了許多問題,像你的問題。 修復程序正在修改comctrls.pas,以便加載RICHED20.DLL。這很可能是不夠的,因爲這個DLL和VCL代碼可能存在兼容性問題。 查找TCustomRichEdit.CreateParams()過程,它包含LoadLibrary調用。

我在Delphi XE中測試了你的代碼,它在那裏工作,所以你最好的選擇是升級到更新的Delphi版本。

UPDATE

我做了一些測試用Delphi 5,它似乎足以改變2種功能。 複製Comctrls。PAS到您的項目,並執行這些修改:

1)TCustomRichEdit.CreateParams(),改變

const 
    RichEditModuleName = 'RICHED32.DLL'; 

const 
    RichEditModuleName = 'RICHED20.DLL'; 

CreateSubClass(Params, 'RICHEDIT'); 

CreateSubClass(Params, 'RICHEDIT20A'); 

2)在程序TRichEditStrings.Insert(),改變

if RichEdit.SelStart <> (Selection.cpMax + Length(Str)) then 
     raise EOutOfResources.Create(sRichEditInsertError); 

if RichEdit.SelStart <> (Selection.cpMax + Length(Str) - CountLineBreaks(Str)) then 
     raise EOutOfResources.Create(sRichEditInsertError); 

代碼CountLineBreaks/PosEx

function PosEx(const SubStr, S: string; Offset: Cardinal = 1): Integer; 
var 
Tmp: PChar; 

begin 
Result := 0; 
if (Offset > Cardinal(Length(S))) then exit; 
if Offset = 1 then 
    Result := Pos(SubStr, S) 
else 
    begin 
    Tmp := StrPos(PChar(@S[Offset]), PChar(SubStr)); 
    if Tmp = nil then exit; 
    Result := Cardinal(Tmp - PChar(@S[Offset])) + Offset; 
    end; 
end; 


function CountLineBreaks(const S: string): Integer; 
const 
    LB = #13#10; 
var 
    P: Integer; 
begin 
    Result := 0; 
    P := Pos(LB, S); 
    while P <> 0 do 
    begin 
    Inc(Result); 
    P := PosEx(LB, S, P + 2); 
    end; 
end; 

在Delphi5這樣做,我得到正確的結果:

Delphi5

有一點需要記住的是RichEdit 2.0用CR代替了CRLF對,所以其他問題可能會不斷增加。如果您遇到問題,請不要拍攝我...

+0

+1對於升級建議 –

+0

+1在項目中包含的ComCtrls.pas的本地副本中進行這些更改。 –

+0

@whosrdaddy感謝您的回答,修復工程。幾個後續問題:1. RICHED32.DLL還暴露了哪些其他問題? 2.使用RichEdit 2.0時,可能會發生哪些其他問題(如CRLF差異)?你能指點我到哪裏我可以讀更多關於差異的地方嗎?還有一個「獎勵」問題:是否有更好的方法來應用此修復方法,而不是複製整個ComCtrls單元來修復一些功能?我雖然關於製作攔截器類,但TRichEditStrings不出現在ComCtrls的接口部分。 – jedivader