u666sa 0 Posted February 6, 2022 Thus far LoadNewResourceModule is translated and works properly. I've tested it by calling it before Application->Initialize. I am able to load a different language. However, ReinitializeForms does not work. Upon calling it (affter LowNewResourceModule) form locaiton changes to 0, 0 but language is not loaded, and remains same... Something is wrong. Help me translate it. Pascal code is included in coments. //--------------------------------------------------------------------------- #include <System.Classes.hpp> #include <SysInit.hpp> #include <Vcl.Forms.hpp> #include <ustring.h> #include <windows.h> #include <sysvari.h> #pragma hdrstop #include "reinit.h" //#include "_TLog.h" //--------------------------------------------------------------------------- #pragma package(smart_init) class TAsInheritedReader : public TReader { public: void __fastcall ReadPrefix(TFilerFlags &_flags, int &_aChildPos); inline __fastcall TAsInheritedReader(TStream* Stream, int BufSize) : TReader(Stream, BufSize) {} }; //--------------------------------------------------------------------------- void __fastcall TAsInheritedReader::ReadPrefix(TFilerFlags &_flags, int &_aChildPos) { TReader::ReadPrefix(_flags, _aChildPos); _flags = _flags << ffInherited; } // GOOD //--------------------------------------------------------------------------- int __fastcall SetResourceHInstance(int _newInstance) { PLibModule CurModule = LibModuleList; while(CurModule != NULL) { if (reinterpret_cast<void*>(CurModule->Instance) == HInstance) { if (CurModule->ResInstance != CurModule->Instance) { FreeLibrary(reinterpret_cast<HMODULE>(CurModule->ResInstance)); CurModule->ResInstance = _newInstance; return _newInstance; } CurModule = CurModule->Next; } } return 0; } // GOOD //--------------------------------------------------------------------------- int __fastcall LoadNewResourceModule(LCID locale) { wchar_t FileName[260]; PChar P; wchar_t LocaleName[4]; int NewInst = 0; GetModuleFileNameW(HInstance, FileName, sizeof(FileName)); GetLocaleInfoW(locale, LOCALE_SABBREVLANGNAME, LocaleName, sizeof(LocaleName)); P = PChar(&FileName) + lstrlen(FileName); while((*P != L'.') && (P != reinterpret_cast<PChar>(&FileName))) { --P; } if (P != reinterpret_cast<PChar>(&FileName)) { ++P; if (LocaleName[0] != L'\0') { NewInst = reinterpret_cast<int>(LoadLibraryEx(FileName, 0, LOAD_LIBRARY_AS_DATAFILE)); if (NewInst == 0) { LocaleName[2] = L'\0'; lstrcpy(P, LocaleName); NewInst = reinterpret_cast<int>(LoadLibraryEx(FileName, 0, LOAD_LIBRARY_AS_DATAFILE)); } } } if (NewInst != 0) { return SetResourceHInstance(NewInst); } return 0; } /* function InternalReloadComponentRes(const ResName: string; HInst: THandle; var Instance: TComponent): Boolean; var HRsrc: THandle; ResStream: TResourceStream; AsInheritedReader: TAsInheritedReader; begin { avoid possible EResNotFound exception } if HInst = 0 then HInst := HInstance; HRsrc := FindResource(HInst, PChar(ResName), RT_RCDATA); Result := HRsrc <> 0; if not Result then Exit; ResStream := TResourceStream.Create(HInst, ResName, RT_RCDATA); try AsInheritedReader := TAsInheritedReader.Create(ResStream, 4096); try Instance := AsInheritedReader.ReadRootComponent(Instance); finally AsInheritedReader.Free; end; finally ResStream.Free; end; Result := True; end; */ //--------------------------------------------------------------------------- bool __fastcall InternalReloadComponentRes(String ResName, std::uintptr_t HInst, TComponent* Instance) { std::uintptr_t HRsrc = 0; TResourceStream* ResStream = NULL; TAsInheritedReader* AsInheritedReader = NULL; if (HInst == 0) { HInst = (std::uintptr_t)HInstance; } HRsrc = (std::uintptr_t)FindResourceW((HMODULE)HInst, (LPCWSTR)ResName.c_str(), (LPCWSTR)RT_RCDATA); if (HRsrc == 0) { return false; } try { ResStream = new TResourceStream(HInst, ResName, (System::WideChar*)RT_RCDATA); try { AsInheritedReader = new TAsInheritedReader(ResStream, 4096); Instance = AsInheritedReader->ReadRootComponent(Instance); } __finally { delete AsInheritedReader; } } __finally { delete ResStream; } return true; } //--------------------------------------------------------------------------- bool __fastcall ReloadInheritedComponent(TComponent* Instance, TClass RootAncestor) { std::function<bool(TClass)> InitComponent = [&](TClass ClassType) -> bool { // This reaises questions, in particular ClassType = TComponent::ClassInfo() original delphi code has it differently // please recheck if ( (ClassType == TComponent::ClassInfo()) || (ClassType == RootAncestor) ) { return false; } bool rvl = InitComponent(ClassType->ClassParent()); if (InternalReloadComponentRes( ClassType->ClassName(), FindResourceHInstance(FindClassHInstance(ClassType)), Instance ) == false) { return false; } return rvl; }; return InitComponent(Instance->ClassType()); } /* function ReloadInheritedComponent(Instance: TComponent; RootAncestor: TClass): Boolean; function InitComponent(ClassType: TClass): Boolean; begin Result := False; if (ClassType = TComponent) or (ClassType = RootAncestor) then Exit; Result := InitComponent(ClassType.ClassParent); Result := InternalReloadComponentRes(ClassType.ClassName, FindResourceHInstance( FindClassHInstance(ClassType)), Instance) or Result; end; begin Result := InitComponent(Instance.ClassType); end; */ //--------------------------------------------------------------------------- void __fastcall ReinitializeForms() { for(int i=0; i<Screen->FormCount; i++) { // This raises questions as well, original delphi code, bellow has different second parameter ReloadInheritedComponent(Screen->Forms[i], Screen->Forms[i]->ClassParent()); } } /* procedure ReinitializeForms; var Count: Integer; I: Integer; Form: TForm; begin Count := Screen.FormCount; for I := 0 to Count-1 do begin Form := Screen.Forms[I]; ReloadInheritedComponent(Form, TForm); end; end; */ Share this post Link to post
Remy Lebeau 1436 Posted February 6, 2022 2 hours ago, u666sa said: However, ReinitializeForms does not work. I've already addressed this on your StackOverflow question on this same topic: https://stackoverflow.com/questions/70977125/ There are several issues in the original code that you would need to fix, regardless of whether you use the code in Delphi or C++Builder. The code is not using module handles and Unicode buffers correctly, which clearly indicates that the code is old, predating Delphi's support for 64bit and Unicode environments. The code needs to be updated before you can then translate it correctly. 2 hours ago, u666sa said: Help me translate it. Pascal code is included in coments. That is because the code you are struggling with is translated incorrectly. 2 hours ago, u666sa said: Help me translate it. Pascal code is included in coments. Why are you translating this code AT ALL? You never answered that when I posted it on your StackOverflow question. You can use Delphi .pas files as-is in C++ Builder projects. The IDE will generate a .hpp file that you can then #include into your C++ code. 1 Share this post Link to post
Anders Melander 1815 Posted February 7, 2022 11 hours ago, Remy Lebeau said: I've already addressed this on your StackOverflow question on this same topic I've just skimmed through that and it seems to me that your suggestion to use THandleStream is incorrect; I don't believe FileRead can be used on a resource handle. Apart from that I would advise against on-the-fly runtime change of resource module. There are simply too many things that doesn't work with it and the users doesn't really care about it either. Share this post Link to post
Remy Lebeau 1436 Posted February 7, 2022 7 hours ago, Anders Melander said: I've just skimmed through that and it seems to me that your suggestion to use THandleStream is incorrect; I don't believe FileRead can be used on a resource handle. Good point. I have removed that suggestion. Share this post Link to post