⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 unitresourcedetails.pas

📁 灰鸽子VIP1.2经典源代码
💻 PAS
字号:
unit unitResourceDetails;

interface

uses Windows, Classes, SysUtils;

type

TResourceDetails = class;
TResourceDetailsClass = class of TResourceDetails;

TResourceModule = class
private
  fDirty : Boolean;
  function GetDirty: Boolean;
protected
  function GetResourceCount: Integer; virtual; abstract;
  function GetResourceDetails(idx: Integer): TResourceDetails; virtual; abstract;

public
  procedure DeleteResource (idx : Integer); virtual;
  procedure InsertResource (idx : Integer; details : TResourceDetails); virtual;
  function AddResource (details : TResourceDetails) : Integer; virtual;
  function IndexOfResource (details : TResourceDetails) : Integer; virtual; abstract;
  function GetUniqueResourceName (const tp : string) : string;

  procedure SaveToStream (stream : TStream); virtual;
  procedure LoadFromStream (stream : TStream); virtual;

  procedure SaveToFile (const FileName : string); virtual;
  procedure LoadFromFile (const FileName : string); virtual;
  procedure SortResources; virtual;

  function FindResource (const tp, Name : string; ALanguage : Integer) : TResourceDetails;

  property ResourceCount : Integer read GetResourceCount;
  property ResourceDetails [idx : Integer] : TResourceDetails read GetResourceDetails;
  property Dirty : Boolean read GetDirty write fDirty;
  procedure ClearDirty;
end;

//======================================================================
// TResourceDetails class

TResourceDetails = class
private
  fParent : TResourceModule;
  fData : TMemoryStream;
  fCodePage : Integer;
  fResourceLanguage: LCID;
  fResourceName: string;
  fResourceType: string;

  fMemoryFlags : word;                    // Resource memory flags
  fDataVersion, fVersion : DWORD;         // Resource header version info
  fCharacteristics : DWORD;
  fTag: LongInt;
  fDirty : Boolean;
                                         // Resource header characteristics

protected
  constructor Create (AParent : TResourceModule; ALanguage : Integer; const AName, AType : string; ASize : Integer; AData : pointer); virtual;
  procedure InitNew; virtual;
  procedure SetResourceName(const Value: string); virtual;
  class function SupportsRCData (const AName : string; Size : Integer; data : Pointer) : Boolean; virtual;
  class function SupportsData (Size : Integer; data : Pointer) : Boolean; virtual;
public
  class function CreateResourceDetails (AParent : TResourceModule; ALanguage : Integer; const AName, AType : string; ASize : Integer; AData : pointer) : TResourceDetails;
  class function GetBaseType : string; virtual;

  constructor CreateNew (AParent : TResourceModule; ALanguage : Integer; const AName : string); virtual;
  destructor Destroy; override;
  procedure BeforeDelete; virtual;

  procedure ChangeData (newData : TMemoryStream); virtual;

  property Parent : TResourceModule read fParent;
  property Data : TMemoryStream read fData;
  property ResourceName : string read fResourceName write SetResourceName;
  property ResourceType : string read fResourceType;
  property ResourceLanguage : LCID read fResourceLanguage write fResourceLanguage;

  property CodePage : Integer read fCodePage write fCodePage;
  property Characteristics : DWORD read fCharacteristics write fCharacteristics;
  property Version : DWORD read fVersion write fDataVersion;
  property DataVersion : DWORD read fDataVersion write fDataVersion;
  property MemoryFlags : WORD read fMemoryFlags write fMemoryFlags;

  property Dirty : Boolean read fDirty write fDirty;

  property Tag : LongInt read fTag write fTag;
end;

//======================================================================
// Global function definitions

procedure RegisterResourceDetails (resourceClass : TResourceDetailsClass);
procedure UnRegisterResourceDetails (resourceClass : TResourceDetailsClass);
function ResourceWideCharToStr(var wstr : PWideChar) : string;
procedure ResourceStrToWideChar (const s : string; var p : PWideChar);
function ResourceNameToInt (const s : string) : Integer;
function CompareDetails (p1, p2 : Pointer) : Integer;

implementation

var
  registeredResourceDetails : array of TResourceDetailsClass;
  registeredResourceDetailsCount : Integer = 0;

resourcestring
  rstNoBaseType = 'Can''t register resource details class with no base type';
  rstNoStreaming = 'Module doesn''t support streaming';


procedure RegisterResourceDetails (resourceClass : TResourceDetailsClass);
begin
  if Length (registeredResourceDetails) = registeredResourceDetailsCount then
    SetLength (registeredResourceDetails, Length (registeredResourceDetails) + 10);

  registeredResourceDetails [registeredResourceDetailsCount] := resourceClass;

  Inc (registeredResourceDetailsCount)
end;


procedure UnRegisterResourceDetails (resourceClass : TResourceDetailsClass);
var
  i : Integer;
begin
  i := 0;
  while i < registeredResourceDetailsCount do
    if registeredResourceDetails [i] = resourceClass then
    begin
      if i < Length (registeredResourceDetails) - 1 then
        Move (registeredResourceDetails [i + 1], registeredResourceDetails [i], (Length (registeredResourceDetails) - i - 1) * sizeof (TResourceDetailsClass));

      Dec (registeredResourceDetailsCount)
    end
    else
      Inc (i)
end;


function ResourceWideCharToStr(var wstr : PWideChar) : string;
var
  len : word;
begin
  len := word (wstr^);
  SetLength (result, len);
  Inc (wstr);
  WideCharToMultiByte(CP_ACP, 0, WStr, Len, PChar (Result), Len + 1, nil, nil);
  Inc (wstr, len);
  result := PChar (result);
end;


procedure ResourceStrToWideChar (const s : string; var p : PWideChar);
var
  buffer : PWideChar;
  len, size : word;
begin
  len := Length (s);
  size := (Length (s) + 1) * sizeof (WideChar);
  GetMem (buffer, size);
  try
    MultiByteToWideChar (CP_ACP, 0, PChar (s), -1, buffer, size);
    p^ := WideChar (len);
    Inc (p);
    Move (buffer^, p^, len * sizeof (WideChar));
    Inc (p, len)
  finally
    FreeMem (buffer)
  end
end;

(*----------------------------------------------------------------------*
 | procedure ResourceNameToInt                                          |
 |                                                                      |
 | Get integer value of resource name (or type).  Return -1 if it's     |
 | not numeric.                                                         |
 *----------------------------------------------------------------------*)
function ResourceNameToInt (const s : string) : Integer;
var
  isNumeric : Boolean;
  i : Integer;
begin
  isNumeric := Length (s) > 0;
  for i := 1 to Length (s) do
    if not (s [i] in ['0'..'9']) then
    begin
      isNumeric := False;
      break
    end;

  if isNumeric then
    Result := StrToInt (s)
  else
    Result := -1
end;


function CompareDetails (p1, p2 : Pointer) : Integer;
var
  d1 : TResourceDetails;
  d2 : TResourceDetails;
  i1, i2 : Integer;
begin
  d1 := TResourceDetails (p1);
  d2 := TResourceDetails (p2);

  i1 := ResourceNameToInt (d1.ResourceType);
  i2 := ResourceNameToInt (d2.ResourceType);

  if i1 >= 0 then
    if i2 >= 0 then
      Result := i1 - i2         // Compare two integer ids
    else
      Result := 1               // id1 is int, so it's greater than non-int id2
  else
    if i2 >= 0 then
      Result := -1              // id2 is int, so it's less than non-int id1
    else
                                // Compare two string resource ids
      Result := CompareText (d1.ResourceType, d2.ResourceType);

  if Result = 0 then            // If they match, do the same with the names
  begin
    i1 := ResourceNameToInt (d1.ResourceName);
    i2 := ResourceNameToInt (d2.ResourceName);

    if i1 >= 0 then
      if i2 >= 0 then
        Result := i1 - i2
      else
        Result := 1
    else
      if i2 >= 0 then
        Result := -1
      else
        Result := CompareText (d1.ResourceName, d2.ResourceName)
  end
end;


procedure TResourceDetails.BeforeDelete;
begin
  // Stub
end;


procedure TResourceDetails.ChangeData(newData: TMemoryStream);
begin
  fData.Clear;
  fData.CopyFrom (newData, 0);
end;


constructor TResourceDetails.Create(AParent: TResourceModule; ALanguage: Integer; const AName, AType: string; ASize: Integer;
  AData: pointer);
begin
  fParent := AParent;
  fResourceLanguage := ALanguage;
  fResourceName := AName;
  fResourceType := AType;
  fData := TMemoryStream.Create;
  fData.Write (AData^, ASize)
end;


constructor TResourceDetails.CreateNew(AParent: TResourceModule;
  ALanguage: Integer; const aName : string);
begin
  fParent := AParent;
  fResourceLanguage := ALanguage;
  fResourceName := AName;
  fResourceType := GetBaseType;
  if Assigned (AParent) then
    AParent.AddResource (Self);
  fData := TMemoryStream.Create;
  InitNew
end;


class function TResourceDetails.CreateResourceDetails(
  AParent: TResourceModule; ALanguage: Integer; const AName,
  AType: string; ASize: Integer; AData: pointer): TResourceDetails;
var
  i : Integer;
begin
  result := Nil;

  if (Length (AType) > 0) and (AType [1] in ['0'..'9']) then
  try
    for i := 0 to registeredResourceDetailsCount - 1 do
      if registeredResourceDetails [i].GetBaseType = AType then
      begin
        if (AType <> IntToStr (Integer (RT_RCDATA))) or registeredResourceDetails [i].SupportsRCData (AName, ASize, AData) then
        begin
          result := registeredResourceDetails [i].Create (AParent, ALanguage, AName, AType, ASize, AData);
          break
        end
      end;
  except
  end;

  if Result = nil then
  try
    for i := 0 to registeredResourceDetailsCount - 1 do
      if registeredResourceDetails [i].SupportsData (ASize, AData) then
      begin
        result := registeredResourceDetails [i].Create (AParent, ALanguage, AName, AType, ASize, AData);
        break
      end;
  except
  end;

  if result = Nil then
    result := TResourceDetails.Create (AParent, ALanguage, AName, AType, ASize, AData)
end;


destructor TResourceDetails.Destroy;
begin
  fData.Free;
  inherited;
end;

class function TResourceDetails.GetBaseType: string;
begin
  Result := '0';
end;


procedure TResourceDetails.InitNew;
begin
// Stub
end;


procedure TResourceDetails.SetResourceName(const Value: string);
begin
  fResourceName := Value;
  fDirty := True
end;


function TResourceModule.AddResource(details: TResourceDetails): Integer;
begin
  result := -1
  // Stub
end;

procedure TResourceModule.ClearDirty;
var
  i : Integer;
begin
  fDirty := False;
  for i := 0 to ResourceCount - 1 do
    ResourceDetails [i].Dirty := False
end;

procedure TResourceModule.DeleteResource(idx: Integer);
begin
  fDirty := True;
  ResourceDetails [idx].BeforeDelete;
end;

function TResourceModule.FindResource(const tp,
  Name: string; ALanguage : Integer): TResourceDetails;
var
  i : Integer;
begin
  Result := nil;
  for i := 0 to ResourceCount - 1 do
    if (ResourceDetails [i].fResourceType = tp) and (ResourceDetails [i].fResourceName = Name) and (Integer (ResourceDetails [i].fResourceLanguage) = ALanguage) then
    begin
      Result := ResourceDetails [i];
      break
    end;

  if not Assigned (result) then
    for i := 0 to ResourceCount - 1 do
      if (ResourceDetails [i].fResourceType = tp) and (ResourceDetails [i].fResourceName = Name) and (ResourceDetails [i].fResourceLanguage = 0) then
      begin
        Result := ResourceDetails [i];
        break
      end
end;

function TResourceModule.GetDirty: Boolean;
var
  i : Integer;
begin
  Result := fDirty;
  if not fDirty then
    for i := 0 to ResourceCount - 1 do
      if ResourceDetails [i].Dirty then
      begin
        Result := True;
        break
      end
end;


function TResourceModule.GetUniqueResourceName(const tp: string): string;
var
  i : Integer;
  n, n1 : Integer;
  details : TResourceDetails;
begin
  n := 0;

  for i := 0 to ResourceCount - 1 do
  begin
    details := ResourceDetails [i];
    if details.ResourceType = tp then
    begin
      n1 := ResourceNametoInt (details.ResourceName);
      if n1 > n then
        n := n1
    end
  end;

  Result := IntToStr (n + 1);
end;

procedure TResourceModule.InsertResource(idx: Integer;
  details: TResourceDetails);
begin
// Stub
end;

(*----------------------------------------------------------------------*
 | TResourceModule.LoadFromFile                                         |
 |                                                                      |
 | Load from a file.  Not usually overriden.                            |
 *----------------------------------------------------------------------*)
procedure TResourceModule.LoadFromFile(const FileName: string);
var
  s : TFileStream;
begin
  s := TFileStream.Create (FileName, fmOpenRead or fmShareDenyNone);
  try
    LoadFromStream (s);
  finally
    s.Free
  end
end;

(*----------------------------------------------------------------------*
 | TResourceModule.SaveToFile                                           |
 |                                                                      |
 | Save to file.  This can be overriden but usually isn't as it         |
 | relies on SaveToStream, which must be.                               |
 *----------------------------------------------------------------------*)

procedure TResourceModule.LoadFromStream(stream: TStream);
begin
  raise Exception.Create (rstNoStreaming);
end;

procedure TResourceModule.SaveToFile(const FileName: string);
var
  s : TFileStream;
begin
  s := TFileStream.Create (FileName, fmCreate);
  try
    SaveToStream (s);
    ClearDirty
  finally
    s.Free
  end
end;

(*----------------------------------------------------------------------*
 | TResourceDetails.SupportsData                                        |
 |                                                                      |
 | Can be overridden to support a custom resource class, where you can  |
 | determine the custom class from the data - eg. RIFF data, etc.       |
 *----------------------------------------------------------------------*)
class function TResourceDetails.SupportsData(Size: Integer;
  data: Pointer): Boolean;
begin
  Result := False; // stub
end;


class function TResourceDetails.SupportsRCData(const AName: string;
  Size: Integer; data: Pointer): Boolean;
begin
  Result := False; // stub
end;

procedure TResourceModule.SaveToStream(stream: TStream);
begin
  raise Exception.Create (rstNoStreaming);
end;

procedure TResourceModule.SortResources;
begin
// Stub
end;

end.

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -