Yet Another Code Site |
What follows is an analysis of what changed between BCB v4 and v5 based strictly upon a comparison of the comctrls.hpp and comctrls.pas source code. It does *not* include possible changes in ancestor classes which may have introduced further changes.
Very little changed for the TRichEdit component between Borland C++ Builder versions 4 and 5. It still implements Rich Edit 1.0, it adds one new event (OnContextPopup), and it adds one bug fix. Here is a summary of changes followed by the specific changes to the source code for the TRichEdit class.
The detailed changes are below. To summarize the changes for those uninterested in minutiae:
In BCB4, each instance of TRichEdit loaded and freed riched32.dll. In BCB5, the DLL is loaded by the first instance of TRichEdit only. The WMNCDestroy() method no longer frees the DLL. Net result? Once loaded, the Rich Edit DLL will stay in memory until the program terminates.
A new event, OnContextPopup, was added to simplify responding to right-click messages. A new message handler, WMRButtonUp, was added to support OnContextPopup events.
When loading text into the TRichEdit component using the TRichEdit::Lines::LoadFromFile() method, the method now ends by trying to set the maximum length of text in the control to 0x7FFFFFF0. This value is hard-coded and used regardless of the value of MaxLength. (This may not solve the problem for all versions of the Rich Edit control. See the related FAQ.)
The TRichEdit CreateWnd() method now uses a local variable to establish whether the component has been modified. The new local variable (WasModified) is used to save and re-establish the Modified property state. Modified should now return the correct value after changing properties that cause the control to be destroyed and recreated, e.g., changing the ScrollBars property. See the paper on Window handles vs. TRichEdit and other VCL controls for an explanation of this oblique comment.
Here are the declarations, methods, etc., that changed between BCB4 and BCB5. "<!" means removed in BCB5. "!>" means added to BCB5. "..." (ellipsis) indicates that code was omitted for brevity.
class PASCALIMPLEMENTATION TCustomRichEdit : public Stdctrls::TCustomMemo { typedef Stdctrls::TCustomMemo inherited; private: <! unsigned FLibHandle; bool FHideScrollBars; TTextAttributes* FSelAttributes; ... HIDESBASE MESSAGE void __fastcall WMPaint(Messages::TWMPaint &Message); HIDESBASE MESSAGE void __fastcall WMSetFont(Messages::TWMSetFont &Message); !> HIDESBASE MESSAGE void __fastcall WMRButtonUp(Messages::TWMMouse &Message); protected: virtual void __fastcall CreateParams(Controls::TCreateParams &Params); ... };
class PASCALIMPLEMENTATION TRichEdit : public TCustomRichEdit
{
typedef TCustomRichEdit inherited;
__published:
__property Align ;
__property Alignment ;
...
__property WordWrap ;
__property OnChange ;
!> __property OnContextPopup ;
__property OnDragDrop ;
...
};
The following is a global variable added in BCB5.
!> FRichEditModule: THandle; procedure TRichEditStrings.LoadFromFile(const FileName: string); var Ext: string; Convert: PConversionFormat; begin Ext := AnsiLowerCaseFileName(ExtractFileExt(Filename)); System.Delete(Ext, 1, 1); Convert := ConversionFormatList; while Convert <> nil do with Convert^ do if Extension <> Ext then Convert := Next else Break; if Convert = nil then Convert := @TextConversionFormat; if FConverter = nil then FConverter := Convert^.ConversionClass.Create; try inherited LoadFromFile(FileName); except FConverter.Free; FConverter := nil; raise; end; !> RichEdit.DoSetMaxLength($7FFFFFF0); end; procedure TCustomRichEdit.CreateParams(var Params: TCreateParams); const RichEditModuleName = 'RICHED32.DLL'; HideScrollBars: array[Boolean] of DWORD = (ES_DISABLENOSCROLL, 0); HideSelections: array[Boolean] of DWORD = (ES_NOHIDESEL, 0); <! var <! OldError: Longint; <! begin <! OldError := SetErrorMode(SEM_NOOPENFILEERRORBOX); <! FLibHandle := LoadLibrary(RichEditModuleName); <! if (FLibHandle > 0) and (FLibHandle < HINSTANCE_ERROR) then FLibHandle := 0; <! SetErrorMode(OldError); !> begin !> if FRichEditModule = 0 then !> begin !> FRichEditModule := LoadLibrary(RichEditModuleName); !> if FRichEditModule <= HINSTANCE_ERROR then FRichEditModule := 0; !> end; inherited CreateParams(Params); CreateSubClass(Params, 'RICHEDIT'); with Params do begin Style := Style or HideScrollBars[FHideScrollBars] or HideSelections[HideSelection]; WindowClass.style := WindowClass.style and not (CS_HREDRAW or CS_VREDRAW); end; end; procedure TCustomRichEdit.CreateWnd; var <! Plain, DesignMode: Boolean; !> Plain, DesignMode, WasModified: Boolean; begin !> WasModified := inherited Modified; inherited CreateWnd; if (SysLocale.FarEast) and not (SysLocale.PriLangID = LANG_JAPANESE) then Font.Charset := GetDefFontCharSet; SendMessage(Handle, EM_SETEVENTMASK, 0, ENM_CHANGE or ENM_SELCHANGE or ENM_REQUESTRESIZE or ENM_PROTECTED); SendMessage(Handle, EM_SETBKGNDCOLOR, 0, ColorToRGB(Color)); if FMemStream <> nil then begin Plain := PlainText; FMemStream.ReadBuffer(DesignMode, sizeof(DesignMode)); PlainText := DesignMode; try Lines.LoadFromStream(FMemStream); FMemStream.Free; FMemStream := nil; finally PlainText := Plain; end; end; <! Modified := FModified; !> Modified := WasModified; end; procedure TCustomRichEdit.WMNCDestroy(var Message: TWMNCDestroy); begin inherited; <! if FLibHandle <> 0 then FreeLibrary(FLibHandle); end; !> procedure TCustomRichEdit.WMRButtonUp(var Message: TWMRButtonUp); !> begin !> // RichEd20 does not pass the WM_RBUTTONUP message to defwndproc, !> // so we get no WM_CONTEXTMENU message. Simulate message here. !> if Win32MajorVersion < 5 then !> Perform(WM_CONTEXTMENU, Handle, LParam(PointToSmallPoint( !> ClientToScreen(SmallPointToPoint(Message.Pos))))); !> inherited; !> end;
Home | Top Of Page | Code | Papers | FAQs | Links | Search | Feedback |
Page updated |
Copyright © 2000 Thin Air Enterprises and Robert Dunn. All rights reserved.