I have an VCL Win32 application design using dynamic load packages (.bpl). I encounter "Cannot load a RichEdit library" in a sequence of operations:
- Load cxExtEditorsD12.bpl statically (e.g.: Add cxExtEditorsD12.bpl in runtime packages)
- use LoadPackage to load cxExtEditorsD12.bpl, then unload it
- use LoadPackage to load cxExtEditorsD12.bpl again and you will be prompted "Cannot load a RichEdit library".
After trace into the cxRichEdit.pas source, I found out something in the following method:
procedure TcxRichInnerEdit.RichCreateParams(var Params: TCreateParams;
out ARichVersion: Integer);
var
ARichClassName: string;
AWndClass: TWndClass;
I: Integer;
ARichClass: TcxRichEditClass;
begin
if FRichEditLibrary = 0 then
for I := High(cxRichEditDLLNames) downto Low(cxRichEditDLLNames) do
begin
FRichEditLibrary := LoadLibrary(PChar(cxRichEditDLLNames[I]));
if FRichEditLibrary <> 0 then
Break;
end;
if FRichEditLibrary = 0 then
raise EcxEditError.Create(cxGetResourceString(@cxSEditRichEditLibraryError));
for ARichClass := RichEditClass downto cxMinVersionRichEditClass do
begin
ARichClassName := cxRichEditClassNames[ARichClass];
if GetClassInfo(HInstance, PChar(ARichClassName), AWndClass) then
Break;
end;
if GetClassInfo(HInstance, PChar(ARichClassName), AWndClass) then
ARichVersion := cxRichEditVersions[ARichClass]
else
raise EcxEditError.Create(cxGetResourceString(@cxSEditRichEditLibraryError));
CreateSubClass(Params, PChar(ARichClassName));
end;
When an error is about to occurs in step 5 below, cxRichEditClassNames (a constant array) always contain 2 empty strings that doesn't make sense at all.
Steps to Reproduce: - Extract zp file in the attachment
- Use Delphi 2009 to build and run the application
- Click "Load" button (a dynamic created child form will show from package PkgChild.bpl)
- Click "Unload" button to close and PkgChild.bpl will be unloaded
- Click "Load" button again and you will be prompted "Cannot load a RichEdit library"
Actual Results:
Prompt error
Expected Results:
No error prompted even pressing many times of "Load" and "Unload"
This problem should be related to CodeGear QC#71565): http://qc.codegear.com/wc/qcmain.aspx?d=71565
Hello,
We are glad to hear that the problem is not related to our components.
Anyway, we thank you for pointing us to this glitch. This information will be useful to other programmers.
Thanks,
Vlad
SEE ALSO:
Error "Cannot load a RichEdit library" in loading DLL
I have post a workaround solution to QC#71565. I think this the solution should help solve this issue too by doing the following changes in cxRichEdit.pas:
cxRichEditClassNames: array [TcxRichEditClass] of ShortString =
('RICHEDIT',
{$IFDEF DELPHI12}'RICHEDIT20W'{$ELSE}'RICHEDIT20A'{$ENDIF}{,
'RICHEDIT30',
'RICHEDIT41',
'RICHEDIT50'});
Instead of using "array of string", change it to "array of ShortString" should solve the problem.
Hello,
Thank you for the message.
We're investigating this workaround, but this may take us some extra time. I will get back to you once we have any results.
Thanks,
Valdemar
Hello,
Our developers have investigated this issue.
When you are using a runtime package, some units that are included in this package should be used in our program, some may not. When you call the LoadPackage / UnloadPackage methods, only units that are not added are initialized/finalized.
Your suggestion works correctly. However, we've decided not to implement this in the near future, because you can avoid this problem if you use the following approaches:
FPackage := GetModuleHandle('PkgChild.bpl'); @Proc := GetProcAddress(FPackage, 'NewForm'); FForm := Proc;
Thanks,
Valdemar
Even the Delphi XE2 has released, this problem still happen (QC#71565).
I found a construct in cxRichEdit.pas:
procedure InitRichEditDLLNames;
const
cxRichEditDLLNamesCount = 3;
begin
SetLength(FRichEditDLLNames, cxRichEditDLLNamesCount);
FRichEditDLLNames[0] := 'Riched32.dll';
FRichEditDLLNames[1] := 'Riched20.dll';
FRichEditDLLNames[2] := 'Msftedit.dll';
end;
I hope DevExpress team may do the same for
cxRichEditClassNames: array [TcxRichEditClass] of string =
('RICHEDIT',
{$IFDEF DELPHI12}'RICHEDIT20W'{$ELSE}'RICHEDIT20A'{$ENDIF}{,
'RICHEDIT30',
'RICHEDIT41',
'RICHEDIT50'});
to avoid the bug happens in dynamic package loading.