Jump to content
u666sa

Help me with translating reinit.pas into C++

Recommended Posts

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
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.

 

  • Like 1

Share this post


Link to post
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
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

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×