【问题标题】:reinit.pas translated to C++reinit.pas 翻译成 C++
【发布时间】:2022-02-03 19:23:17
【问题描述】:

我已将reinit.pas 半成功地翻译成 C++,以便在我的项目中使用它。调用int __fastcall LoadNewResourceModule(LCID locale); 的部分工作正常,事实上我什至可以在Application->Initialize() 之前调用它,它会在启动时加载正确的语言。但是调用void __fastcall ReinitializeForms(void);的部分不起作用,并给出运行时错误:

找不到资源 TControl

这是.cpp.h 的脏版本,我还没有清理它并正确评论它,此时它必须完全工作。请帮我解决这个问题。

//---------------------------------------------------------------------------

#include <System.Classes.hpp>
#include <SysInit.hpp>
#include <Vcl.Forms.hpp>
#pragma hdrstop

#include "reinit.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;
}

//---------------------------------------------------------------------------
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;
}

//---------------------------------------------------------------------------
int __fastcall LoadNewResourceModule(LCID locale)
{
  wchar_t FileName[260];
  PChar P;
  wchar_t LocaleName[4];
  int NewInst = 0;


  GetModuleFileName(HInstance, FileName, sizeof(FileName));
  GetLocaleInfo(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;
}

//---------------------------------------------------------------------------
bool __fastcall InternalReloadComponentRes(const String ResName, THandle HInst, TComponent* Instance)
{
  //TResourceStream* ResStream = new TResourceStream;
  //TAsInheritedReader* AsInheritedReader = new TAsInheritedReader;


  if (HInst == 0) {
      HInst = reinterpret_cast<THandle>(HInstance);
  }


  THandle HRsrc = reinterpret_cast<THandle>(FindResource((HMODULE)HInst, (LPCWSTR)ResName.w_str(), (LPCWSTR)RT_RCDATA));

  if(HRsrc != 0) {
      return false;
  }
   
  /* THIS IS THE OFFENDING LINE OF CODE THAT THROWS EXCEPTION
     I checked HInst, it is not 0...
     ResName = "TControl"
     and it throws exception here for some reason
     saying resource tcontrol not found
 */
  TResourceStream* ResStream = new TResourceStream(HInst, ResName, RT_RCDATA);

  try {
      TAsInheritedReader* AsInheritedReader = new TAsInheritedReader(ResStream, 4096);

      try {
          Instance = AsInheritedReader->ReadRootComponent(Instance);
      } __finally {
          delete AsInheritedReader;
      }
  }
  __finally {
      delete ResStream;
  }


  return true;
}

//---------------------------------------------------------------------------
bool __fastcall InitComponent(TClass ClassType)
{
  if ((ClassType->ClassName() == "TComponent") || (ClassType->ClassName() == "RootAncestor")) {
      return false;
  }

  InitComponent(ClassType->ClassParent());
  return InternalReloadComponentRes(ClassType->ClassName(), FindResourceHInstance(FindClassHInstance(ClassType)), (TComponent*)&ClassType);
}

//---------------------------------------------------------------------------
bool __fastcall ReloadInheritedComponent(TComponent* Instance)
{
  return InitComponent(Instance->ClassType());
}

//---------------------------------------------------------------------------
void __fastcall ReinitializeForms(void)
{
  for(int i=0; i<Screen->FormCount-1; i++) {
      ReloadInheritedComponent(Screen->Forms[i]);
  }

}



#ifndef _reinit_h
#define _reinit_h

#include <windows.h>




extern int __fastcall LoadNewResourceModule(LCID locale);
extern void __fastcall ReinitializeForms(void);






#endif

【问题讨论】:

  • 翻译正确吗? ` HRsrc := FindResource(HInst, PChar(ResName), RT_RCDATA);结果:= HRsrc 0; if not Result then Exit;` ` if(HRsrc != 0) { return false; }`

标签: delphi c++builder vcl


【解决方案1】:

您根本不需要翻译代码。您可以在 C++Builder 项目中按原样使用 Delphi .pas 单元。只需将.pas 文件添加到您的项目并编译它,IDE 将生成一个.hpp 文件,然后您可以在您的C++ 代码中使用#include

无论如何,您的翻译在很多地方都不正确。

例如,原始代码在编写时并未考虑到 Unicode,但您在代码中使用了 Unicode 字符串。像 sizeof(FileName)sizeof(LocaleName) 这样的表达式是传递给正在使用的 Win32 API 的错误缓冲区大小,这可能会导致缓冲区溢出。代码显然需要 BYTE 大小的窄字符,而不是 WORD 大小的宽字符。

看起来原始代码也没有考虑到 64 位。它在需要 64 位整数的地方使用 32 位整数(用于资源句柄等)。

因此,原始代码需要一些更新才能正确支持现代系统。

而且,您对InitComponent() 的翻译是错误的。它使用的是字符串,而原始代码使用的是元类引用,并且它在 InternalReloadComponentRes() 的最后一个参数中传递了错误的值,您甚至没有正确声明。

而且,ReinitializeForms() 中的循环正在跳过 Screen-&gt;Forms[] 数组中的最后一个 TForm

现在,说了这么多,试试这样的:

ReInit.h

#ifndef REINIT_H
#define REINIT_H

void __fastcall ReinitializeForms();
NativeUInt __fastcall LoadNewResourceModule(unsigned long Locale);

#endif

ReInit.cpp

#include "ReInit.h"

#include <Windows.hpp>
#include <SysInit.hpp>
#include <SysUtils.hpp>
#include <Classes.hpp>
#include <Forms.hpp>

#include <memory>

class TAsInheritedReader : public TReader
{
public:
    void __fastcall ReadPrefix(TFilerFlags &Flags, int &AChildPos) override;
};

void __fastcall TAsInheritedReader::ReadPrefix(TFilerFlags &Flags, int &AChildPos)
{
    TReader::ReadPrefix(Flags, AChildPos);
    Flags << ffInherited;
}

NativeUInt __fastcall SetResourceHInstance(NativeUInt NewInstance)
{
    PLibModule CurModule = LibModuleList;
    while (CurModule)
    {
        if (CurModule->Instance == HInstance)
        {
            if (CurModule->ResInstance != CurModule->Instance)
                ::FreeLibrary(reinterpret_cast<HMODULE>(CurModule->ResInstance));
            CurModule->ResInstance = NewInstance;
            return NewInstance;
        }
        CurModule = CurModule->Next;
    }
    return 0;
}

NativeUInt __fastcall LoadNewResourceModule(unsigned long Locale)
{
    WCHAR FileName[MAX_PATH+1] = {};
    ::GetModuleFileNameW(reinterpret_cast<HMODULE>(HInstance), FileName, MAX_PATH+1);

    WCHAR LocaleName[5] = {};
    ::GetLocaleInfoW(Locale, LOCALE_SABBREVLANGNAME, LocaleName, 5);

    LPWSTR P = &FileName[lstrlenW(FileName)];
    while ((*P != L'.') && (P != FileName)) --P;

    HMODULE NewInst = nullptr;
    if (P != FileName)
    {
        ++P;
        if (LocaleName[0] != L'\0')
        {
            // Then look for a potential language/country translation
            lstrcpyW(P, LocaleName);
            NewInst = LoadLibraryEx(FileName, 0, LOAD_LIBRARY_AS_DATAFILE);
            if (!NewInst)
            {
                // Finally look for a language only translation
                LocaleName[2] = L'\0';
                lstrcpyW(P, LocaleName);
                NewInst = LoadLibraryEx(FileName, 0, LOAD_LIBRARY_AS_DATAFILE);
            }
        }
    }
    if (NewInst)
        return SetResourceHInstance(reinterpret_cast<NativeUInt>(NewInst));
    return 0;
}

bool __fastcall InternalReloadComponentRes(const UnicodeString &ResName, NativeUInt HInst, TComponent* &Instance)
{
    // avoid possible EResNotFound exception
    if (HInst == 0) HInst = HInstance;
    HRSRC HRsrc = FindResourceW(reinterpret_cast<HMODULE>(HInst), ResName.c_str(), MAKEINTRESOURCEW(10)/*RT_RCDATA*/);
    if (!HRsrc) return false;

    auto ResStream = std::make_unique<TResourceStream>(HInst, ResName, MAKEINTRESOURCEW(10)/*RT_RCDATA*/);

    auto AsInheritedReader = std::make_unique<TAsInheritedReader>(ResStream.get(), 4096);
    Instance = AsInheritedReader->ReadRootComponent(Instance);

    return true;
}

bool __fastcall ReloadInheritedComponent(TComponent *Instance, TClass RootAncestor)
{
    const auto InitComponent = [&Instance,RootAncestor](TClass ClassType) -> bool
    {
        auto InitComponent_impl = [&Instance,RootAncestor](TClass ClassType, auto& InitComponent_ref) -> bool
        {
            if ((ClassType == __classid(TComponent)) || (ClassType == RootAncestor)) return false;
            bool Result = InitComponent_ref(ClassType->ClassParent(), InitComponent_ref);
            return InternalReloadComponentRes(ClassType->ClassName(), FindResourceHInstance(FindClassHInstance(ClassType)), Instance) || Result;
        }
        return InitComponent_impl(ClassType, InitComponent_impl);
    }

    return InitComponent(Instance->ClassType());
}

void __fastcall ReinitializeForms()
{
    int Count = Screen->FormCount;
    for(int i = 0; i < Count; ++i)
    {
        ReloadInheritedComponent(Screen->Forms[I], __classid(TForm));
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-10-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-01-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多