如何避免Delphi DFM属性清理工具误删相似名称属性
解决Delphi DFM属性清理工具误删相似名称属性的问题
你的问题根源很明确:原来的StrIPos(mPropList.Lines[K] + ' =', S)是子串匹配,当要删除的属性名是Prop时,SecondProp = ...这行里的Prop =会被当作子串命中,导致误删包含目标属性名的其他属性。
要实现精确匹配,我们需要提取DFM行中完整的属性名再做匹配,因为DFM的属性行格式通常是[前导空格]属性名 = 值/结构,核心思路是:
- 先去除行的前导空格,找到第一个
=的位置,提取等号前的部分作为当前行的属性名 - 将提取出的属性名与目标属性名做不区分大小写的精确匹配
下面是修改后的完整Button2Click代码,我标注了关键修改的部分:
procedure TfrmDeleteProp_MainForm.Button2Click(Sender: TObject); var LFile, LSource, LResult: TStringList; I, J, K, Processed, WasError, Removed: Integer; SkipPropData: Boolean; FLOpt: TFileListOptions; S, CurrentProp: String; EqualsPos: Integer; // 新增:存储等号的位置 begin LFile := TStringList.Create; LSource := TStringList.Create; LResult := TStringList.Create; try if chbxSubFolders.Checked then FLOpt := [flFullNames, flRecursive] else FLOpt := [flFullNames]; if not AdvBuildFileList(IncludeTrailingBackslash(edPath.Text) + '*.DFM', faAnyFile, LFile, FLOpt) then begin MessageBox(Handle, 'Invalid path specified. Can not process.', 'Warning', MB_OK or MB_ICONEXCLAMATION); exit; end; Processed := 0; WasError := 0; for I := 0 to LFile.Count - 1 do begin LSource.LoadFromFile(LFile[I]); Removed := 0; for K := 0 to mPropList.Lines.Count - 1 do begin if K > 0 then LSource.Assign(LResult); if Trim(mPropList.Lines[K]) = '' then continue; LResult.Clear; SkipPropData := False; for J := 0 to LSource.Count - 1 do begin S := Trim(LSource[J]); if SkipPropData then begin if (S > '') and (S[Length(S)] in [')', '}']) then SkipPropData := False; continue; end; // --- 开始修改部分 --- CurrentProp := ''; EqualsPos := Pos('=', S); if EqualsPos > 0 then begin // 提取等号前的部分,去除末尾空格,得到当前属性名 CurrentProp := Trim(Copy(S, 1, EqualsPos - 1)); end; // 做不区分大小写的精确匹配 if StrIComp(PChar(CurrentProp), PChar(mPropList.Lines[K])) <> 0 then // --- 结束修改部分 --- begin LResult.Add(LSource[J]); continue; end; if (S > '') and (S[Length(S)] in ['(', '{']) then SkipPropData := True; Removed := Removed + 1; end; end; if Removed > 0 then begin if RenameFile(LFile[I], ChangeFileExt(LFile[I], '.BAK')) then begin LResult.SaveToFile(LFile[I]); Processed := Processed + 1; end else begin MessageBox(Handle, PChar('Can not create back up copy for file: ' + LFile[I] + #13#10'File is not processed.'), 'Warning', MB_OK or MB_ICONEXCLAMATION); WasError := WasError + 1; end; end; end; MessageBox(Handle, PChar(Format('Total files found: %d'#13#10'Properties were removed from: %d'#13#10'Error files: %d', [LFile.Count, Processed, WasError])), 'Statistics', MB_OK or MB_ICONINFORMATION); finally LFile.Free; LSource.Free; LResult.Free; end; end;
修改说明:
- 新增了
EqualsPos变量用来定位行中第一个=的位置,CurrentProp存储提取出的当前行属性名 - 替换了原来的子串匹配逻辑,改为提取完整属性名后做精确的不区分大小写匹配,这样就不会误删
SecondProp这类包含目标属性名的其他属性 - 保留了原有的
SkipPropData逻辑,确保正确处理多行结构的属性(比如Font = { ... }这种需要跳过后续行的情况)
这个修改后,工具只会删除完全匹配目标属性名的行,不会再误删相似名称的属性了。
内容的提问来源于stack exchange,提问作者User421
相关产品推荐
相关产品推荐

