|  | @@ -7,14 +7,15 @@ uses
 | 
	
		
			
				|  |  |    sdDB, VCLZip, VCLUnZip, Dialogs, Forms, ShlObj, Classes, StrUtils, Math, ADODB,
 | 
	
		
			
				|  |  |    IdGlobal;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -type
 | 
	
		
			
				|  |  | +type 
 | 
	
		
			
				|  |  | +  TRoundMode = (rmNearest, rmUp, rmDown);
 | 
	
		
			
				|  |  |    TBookmarkRefreshEvent = procedure (AExpandFrame: Boolean) of object;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    {RoundTo}
 | 
	
		
			
				|  |  |    function QuantityRoundTo(AValue: Double): Double;
 | 
	
		
			
				|  |  |    function PriceRoundTo(AValue: Double): Double;
 | 
	
		
			
				|  |  |    function TotalPriceRoundTo(AValue: Double): Double;
 | 
	
		
			
				|  |  | -  function CommonRoundTo(AValue: Double; ADigit: Integer): Double;
 | 
	
		
			
				|  |  | +  function CommonRoundTo(AValue: Double; ADigit: Integer; RoundMode: TRoundMode = rmNearest): Double;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    {Interface Control}
 | 
	
		
			
				|  |  |    procedure AlignControl(AControl, AParent: TWinControl; AAlign: TAlign);
 | 
	
	
		
			
				|  | @@ -117,40 +118,90 @@ type
 | 
	
		
			
				|  |  |  implementation
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  uses
 | 
	
		
			
				|  |  | -  SysUtils, dxBar, MainFrm, ConstUnit, Globals, StdCtrls, ShellAPI,
 | 
	
		
			
				|  |  | -  ScUtils;
 | 
	
		
			
				|  |  | +  SysUtils, dxBar, MainFrm, ConstUnit, Globals, StdCtrls, ShellAPI;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  var
 | 
	
		
			
				|  |  |    SysProgressDisabled: Boolean;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  {RoundTo}
 | 
	
		
			
				|  |  | +function InnerRoundTo(const AValue: Extended; const ADigit: Integer; RoundMode: TRoundMode): Extended;
 | 
	
		
			
				|  |  | +var
 | 
	
		
			
				|  |  | +  LFactor, Offset: Extended;
 | 
	
		
			
				|  |  | +  HFactor: Integer;
 | 
	
		
			
				|  |  | +begin
 | 
	
		
			
				|  |  | +  LFactor := IntPower(10, ADigit);
 | 
	
		
			
				|  |  | +  HFactor := Trunc(IntPower(10, abs(ADigit)));
 | 
	
		
			
				|  |  | +  Result := AValue;
 | 
	
		
			
				|  |  | +  case RoundMode of
 | 
	
		
			
				|  |  | +    rmNearest:
 | 
	
		
			
				|  |  | +    begin
 | 
	
		
			
				|  |  | +      if AValue >= 0 then
 | 
	
		
			
				|  |  | +        Offset := 0.5
 | 
	
		
			
				|  |  | +      else
 | 
	
		
			
				|  |  | +        Offset := -0.5;
 | 
	
		
			
				|  |  | +      Result := Trunc((AValue * HFactor) + Offset) * LFactor;
 | 
	
		
			
				|  |  | +    end;
 | 
	
		
			
				|  |  | +    rmUP:
 | 
	
		
			
				|  |  | +    begin
 | 
	
		
			
				|  |  | +      if Frac(AValue / LFactor) > 0 then
 | 
	
		
			
				|  |  | +        Result := Trunc(AValue * HFactor + 1) * LFactor
 | 
	
		
			
				|  |  | +      else
 | 
	
		
			
				|  |  | +        Result := Trunc(AValue * HFactor) * LFactor;
 | 
	
		
			
				|  |  | +    end;
 | 
	
		
			
				|  |  | +    rmDown:
 | 
	
		
			
				|  |  | +    begin
 | 
	
		
			
				|  |  | +      Result := Trunc(AValue * HFactor) * LFactor;
 | 
	
		
			
				|  |  | +    end;
 | 
	
		
			
				|  |  | +  end;
 | 
	
		
			
				|  |  | +end;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  function QuantityRoundTo(AValue: Double): Double;
 | 
	
		
			
				|  |  |  begin
 | 
	
		
			
				|  |  |    if Assigned(OpenProjectManager.CurProjectData) then
 | 
	
		
			
				|  |  | -    Result := ScRoundTo(AValue, -OpenProjectManager.CurProjectData.ProjProperties.QuantityDigit)
 | 
	
		
			
				|  |  | +    Result := CommonRoundTo(AValue, -OpenProjectManager.CurProjectData.ProjProperties.QuantityDigit)
 | 
	
		
			
				|  |  |    else
 | 
	
		
			
				|  |  | -    Result := ScRoundTo(AValue, iQuantityDigit);
 | 
	
		
			
				|  |  | +    Result := CommonRoundTo(AValue, iQuantityDigit);
 | 
	
		
			
				|  |  |  end;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  function PriceRoundTo(AValue: Double): Double;
 | 
	
		
			
				|  |  |  begin
 | 
	
		
			
				|  |  |    if Assigned(OpenProjectManager.CurProjectData) then
 | 
	
		
			
				|  |  | -    Result := ScRoundTo(AValue, -OpenProjectManager.CurProjectData.ProjProperties.PriceDigit)
 | 
	
		
			
				|  |  | +    Result := CommonRoundTo(AValue, -OpenProjectManager.CurProjectData.ProjProperties.PriceDigit)
 | 
	
		
			
				|  |  |    else
 | 
	
		
			
				|  |  | -    Result := ScRoundTo(AValue, iPriceDigit);
 | 
	
		
			
				|  |  | +    Result := CommonRoundTo(AValue, iPriceDigit);
 | 
	
		
			
				|  |  |  end;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  function TotalPriceRoundTo(AValue: Double): Double;
 | 
	
		
			
				|  |  |  begin
 | 
	
		
			
				|  |  |    if Assigned(OpenProjectManager.CurProjectData) then
 | 
	
		
			
				|  |  | -    Result := ScRoundTo(AValue, -OpenProjectManager.CurProjectData.ProjProperties.TotalPriceDigit)
 | 
	
		
			
				|  |  | +    Result := CommonRoundTo(AValue, -OpenProjectManager.CurProjectData.ProjProperties.TotalPriceDigit)
 | 
	
		
			
				|  |  |    else
 | 
	
		
			
				|  |  | -    Result := ScRoundTo(AValue, iTotalPriceDigit);
 | 
	
		
			
				|  |  | +    Result := CommonRoundTo(AValue, iTotalPriceDigit);
 | 
	
		
			
				|  |  |  end;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -function CommonRoundTo(AValue: Double; ADigit: Integer): Double;
 | 
	
		
			
				|  |  | -begin
 | 
	
		
			
				|  |  | -  Result := ScRoundTo(AValue, ADigit);
 | 
	
		
			
				|  |  | +function CommonRoundTo(AValue: Double; ADigit: Integer; RoundMode: TRoundMode = rmNearest): Double;
 | 
	
		
			
				|  |  | +var
 | 
	
		
			
				|  |  | +  X: Double;
 | 
	
		
			
				|  |  | +  P: Pointer;
 | 
	
		
			
				|  |  | +  I: Integer;
 | 
	
		
			
				|  |  | +  Buf: array [0..7] of Byte;
 | 
	
		
			
				|  |  | +begin
 | 
	
		
			
				|  |  | +  P := @AValue;
 | 
	
		
			
				|  |  | +  CopyMemory(@Buf[0], P, SizeOf(AValue));
 | 
	
		
			
				|  |  | +  // 进位处理,从后往前,如果当前byte为$FF,则往前一byte进1
 | 
	
		
			
				|  |  | +  // 注意到尾数开始的位置停止
 | 
	
		
			
				|  |  | +  // 这里说的前后是二进制串,实际存储前后相反
 | 
	
		
			
				|  |  | +  for I := 0 to 6 do
 | 
	
		
			
				|  |  | +    if (I < 6) and (Buf[I] = $FF) then
 | 
	
		
			
				|  |  | +      Buf[I] := 0
 | 
	
		
			
				|  |  | +    else
 | 
	
		
			
				|  |  | +    begin
 | 
	
		
			
				|  |  | +      Buf[I] := Buf[I] + 1;
 | 
	
		
			
				|  |  | +      Break;
 | 
	
		
			
				|  |  | +    end;
 | 
	
		
			
				|  |  | +  P := @X;
 | 
	
		
			
				|  |  | +  CopyMemory(P, @Buf[0], SizeOf(X));
 | 
	
		
			
				|  |  | +  Result := InnerRoundTo(X, ADigit, RoundMode);
 | 
	
		
			
				|  |  |  end;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  {Interface Control}
 |