解決Raize日曆控制元件顯示的問題

findumars發表於2013-07-28

解決Raize日曆控制元件顯示的問題

近自己的程式被測試人員發現一個小問題,就是程式中的日曆選擇框,顯示中的“星期一、星期二。。。。”都顯示成了“星。。。。。”,我自己看了程式碼,原來是raize的控制元件問題,並且無論用4.x版本還是5.x版本,問題都依然存在。沒辦法,就在網上找找看,結果還是找到了,原來需要修改下原始碼檔案:
修改:RzPopups.pas,該檔案在raize目錄下的source子目錄,修改其中的procedure TRzCalendar.Paint這個過程,下面是修改後的程式碼:

procedure TRzCalendar.Paint;
var
  S, S2, F: string;
  R, WR, SelRect, DaysRect, DayR: TRect;
  I, J, WN, Offset, MaxLen, SaveFontSize: Integer;
  DrawDate: TDateTime;
  Year, Month, Day, ViewMonth, ViewYear: Word;
  DayColor, DayFontColor, TempC, C: TColor;
  DayFontStyle: TFontStyles;
  CustomDayFormat: Boolean;
  PMBoldDays, NMBoldDays, CMBoldDays, BoldDaysMask: Cardinal;
  ArrowFont: TFont;
  ButtonsVisible, DrawFlat: Boolean;
  Areas: TRzCalendarAreas;

  procedure DrawHorizontalLine( ALeft, ARight, AHeight: Integer );
  var
    ElementDetails: TThemedElementDetails;
  begin
    if FThemeAware and ThemeServices.ThemesEnabled then
    begin
      ElementDetails := ThemeServices.GetElementDetails( ttbSeparatorVertNormal );
      ThemeServices.DrawElement( Canvas.Handle, ElementDetails, Rect( ALeft, AHeight, ARight, AHeight + 3 ) );
    end
    else
    begin
      Canvas.Pen.Color := FCalendarColors.Lines;
      Canvas.MoveTo( ALeft, AHeight );
      Canvas.LineTo( ARight, AHeight );
    end;
  end;

  procedure DrawVerticalLine( ATop, ABottom, ALeft: Integer );
  var
    ElementDetails: TThemedElementDetails;
  begin
    if FThemeAware and ThemeServices.ThemesEnabled then
    begin
      ElementDetails := ThemeServices.GetElementDetails( ttbSeparatorNormal );
      ThemeServices.DrawElement( Canvas.Handle, ElementDetails, Rect( ALeft, ATop, ALeft + 3, ABottom ) );
    end
    else
    begin
      Canvas.Pen.Color := FCalendarColors.Lines;
      Canvas.MoveTo( ALeft, ATop );
      Canvas.LineTo( ALeft, ABottom );
    end;
  end;
begin {= TRzCalendar.Paint =}
  if FThemeAware and ThemeServices.ThemesEnabled then
  begin
    C := GetXPThemeColor( xptcEditBorder );
    R := DrawBox( Canvas, ClientRect, C );
    Canvas.Brush.Color := Color;
    Canvas.FillRect( R );
  end
  else
    inherited;
  DrawFlat := BorderOuter in [ fsFlat, fsFlatBold, fsFlatRounded ];
  CalcAreas( Areas );
  // Draw Month and Year Bar
  if ( [ ceMonth, ceYear ] * FElements ) <> [ ] then
  begin
    if FShowDays then
    begin
      R := Areas[ caYear ];
      if FThemeAware and ThemeServices.ThemesEnabled then
      begin
        GetGradientPanelColors( gcsMSOffice, TempC, C );
      end
      else
      begin
        if not DrawFlat then
          R := DrawBorder( Canvas, R, fsPopup );
        C := FButtonColor;
      end;
      Canvas.Brush.Color := C;
      Canvas.FillRect( R );
    end;
    SetBkMode( Canvas.Handle, Windows.Transparent );
    if ceArrows in FElements then
    begin
      ArrowFont := TFont.Create;
      try
        ArrowFont.Name := 'Marlett';
        ArrowFont.Size := Font.Size + 4;
        Canvas.Font.Assign( ArrowFont );
      finally
        ArrowFont.Free;
      end;
      DrawStringCentered( Canvas, '3', Areas[ caLeftArrow ] );   // Draw Left Arrow
      DrawStringCentered( Canvas, '4', Areas[ caRightArrow ] );  // Draw Right Arrow
    end;
    // Draw month and year
    Canvas.Font.Assign( Font );
    Canvas.Font.Color := FButtonFontColor;
    F := 'mmmm';
    if ceYear in FElements then
      F := F + ' yyyy';
    DrawStringCentered( Canvas, FormatDateTime( F, ViewDate ), Areas[ caYear ] );
  end;
  if FShowDays then
  begin
    ButtonsVisible := False;
    // Draw Today button
    if ceTodayButton in FElements then
    begin
      if FCaptionTodayBtn <> '' then
        S := FCaptionTodayBtn
      else
        S := '今日';
      DrawButton( Canvas, Areas[ caTodayButton ], S,
                  FButtonColor, FButtonFontColor, DrawFlat,
                  ( FPressedArea = caTodayButton ) and ( FOverArea = caTodayButton ),
                  FThemeAware );
      ButtonsVisible := True;
    end;
    // Draw Clear Button
    if ceClearButton in FElements then
    begin
      if FCaptionClearBtn <> '' then
        S := FCaptionClearBtn
      else
        S := '清除';
      DrawButton( Canvas, Areas[ caClearButton ], S,
                  FButtonColor, FButtonFontColor, DrawFlat,
                  ( FPressedArea = caClearButton ) and ( FOverArea = caClearButton ),
                  FThemeAware );
      ButtonsVisible := True;
    end;
    // Draw Day of Week Headings
    if ceDaysOfWeek in FElements then
    begin
      Canvas.Brush.Color := Color;
      Canvas.Font.Color := FCalendarColors.DaysOfWeek;
      SaveFontSize := Canvas.Font.Size;
      Canvas.Font.Size := SaveFontSize - 1;
      R := Bounds( Areas[ caDaysOfWeek ].Left, Areas[ caDaysOfWeek ].Top - 1,
                   FCellSize.X - 2, FCellSize.Y );
      MaxLen := GetMaxShortDayNameLength;
      for I := 0 to 6 do
      begin
        J := FFirstDay + I + 2;
        if J > 7 then
          Dec( J, 7 );
        S := ShortDayNames[ J ];
        if j=1 then s:=''; 
        if j=2 then s:=''; 
        if j=3 then s:=''; 
        if j=4 then s:=''; 
        if j=5 then s:=''; 
        if j=6 then s:=''; 
        if j=7 then s:=''; 
        if MaxLen > ( R.Right - R.Left ) then
        begin
          if SysLocale.DefaultLCID <> $040D then
            S2 := Copy( S, 1, 2 )
          else // Hebrew - Day name abbreviations handled differently
          begin
            if Length( S ) >= 5 then
              S2 := S[ 5 ]
            else
              S2 := S[ 1 ];
          end;
          if Canvas.TextWidth( S2 ) > ( R.Right - R.Left ) then
            DrawString( Canvas, S2[ 1 ], R, dt_VCenter or dt_SingleLine or dt_Right or dt_NoClip )
          else
            DrawString( Canvas, S2, R, dt_VCenter or dt_SingleLine or dt_Right or dt_NoClip )
        end
        else
          DrawString( Canvas, S, R, dt_VCenter or dt_SingleLine or dt_Right or dt_NoClip );
        OffsetRect( R, FCellSize.X, 0 );
      end;
      Canvas.Font.Size := SaveFontSize;
      if ceWeekNumbers in FElements then
      begin
        if FThemeAware and ThemeServices.ThemesEnabled then
          Offset := 6
        else
          Offset := 5;
        DrawHorizontalLine( Areas[ caWeekNumbers ].Right - Offset, Areas[ caDaysOfWeek ].Right, R.Bottom );
      end
      else
        DrawHorizontalLine( Areas[ caDaysOfWeek ].Left, Areas[ caDaysOfWeek ].Right, R.Bottom );
    end;
    // Draw Days
    DaysRect := Areas[ caDays ];
    CMBoldDays := 0;  // Current Month
    PMBoldDays := 0;  // Previous Month
    NMBoldDays := 0;  // Next Month
    DecodeDate( FViewDate, ViewYear, ViewMonth, Day );
    GetBoldDays( ViewYear, ViewMonth, CMBoldDays );
    if ceFillDays in FElements then
    begin
      DecodeDate( IncMonth( FViewDate, -1 ), Year, Month, Day );
      GetBoldDays( Year, Month, PMBoldDays );
      DecodeDate( IncMonth( FViewDate, 1 ), Year, Month, Day );
      GetBoldDays( Year, Month, NMBoldDays );
    end;
    if ceWeekNumbers in FElements then
    begin
      Canvas.Pen.Color := FCalendarColors.DaysOfWeek;
      if FThemeAware and ThemeServices.ThemesEnabled then
        Offset := 1
      else
        Offset := 0;
      DrawVerticalLine( Areas[ caWeekNumbers ].Top - Offset, Areas[ caWeekNumbers ].Bottom + Offset, Areas[ caWeekNumbers ].Right - 5 );
    end;
    R := Bounds( DaysRect.Left, DaysRect.Top - 1, FCellSize.X - 2, FCellSize.Y );
    WR := Areas[ caWeekNumbers ];
    Inc( WR.Top, 1 );
    WR.Bottom := WR.Top + FCellSize.Y;
    Dec( WR.Right, 5 );
    DrawDate := FFirstDateInGrid;
    for I := 0 to 5 do
    begin
      for J := 0 to 6 do
      begin
        DecodeDate( DrawDate, Year, Month, Day );
        DayColor := Color;
        DayFontStyle := [];
        if ( Month = ViewMonth ) and ( Year = ViewYear ) then
        begin
          DayFontColor := FCalendarColors.Days;
          BoldDaysMask := CMBoldDays;
        end
        else
        begin
          DayFontColor := FCalendarColors.FillDays;
          if EncodeDate( Year, Month, 1 ) > EncodeDate( ViewYear, ViewMonth, 1 ) then
            BoldDaysMask := NMBoldDays
          else
            BoldDaysMask := PMBoldDays;
        end;
        if ( ( ceFillDays in FElements ) or ( Month = ViewMonth ) ) then
        begin
          // Determine Day Color
          CustomDayFormat := GetDayFormat( DrawDate, Year, Month, Day,
                                           DayColor, DayFontColor, DayFontStyle );
          Canvas.Font.Color := DayFontColor;
          Canvas.Font.Style := DayFontStyle;
          Canvas.Brush.Color := DayColor;
          if ColorToRGB( DayColor ) <> ColorToRGB( Color )  then
          begin
            DayR := R;
            Inc( DayR.Right, 2 );
            Canvas.FillRect( DayR );
          end;
          if not CustomDayFormat then
          begin
            // if not using a CustomDayFormat, then go ahead and apply BoldDaysMask
            if ( BoldDaysMask and ( $1 shl ( Day - 1 ) ) ) = 0 then
              Canvas.Font.Style := Canvas.Font.Style - [ fsBold ]
            else
              Canvas.Font.Style := Canvas.Font.Style + [ fsBold ];
          end;
          if DrawDate = Trunc( FDate ) then
          begin
            // Highlight selected Date
            SelRect := R;
            Inc( SelRect.Right, 2 );
            Canvas.Font.Color := FCalendarColors.SelectedDateFore;
            Canvas.Brush.Color := FCalendarColors.SelectedDateBack;
            FillRect( Canvas.Handle, SelRect, Canvas.Brush.Handle );
            if Focused then
              Canvas.DrawFocusRect( SelRect );
          end;
          DrawString( Canvas, IntToStr( Day ), R, dt_VCenter or dt_SingleLine or dt_Right or dt_NoClip );
          if DrawDate = Trunc( SysUtils.Date ) then
          begin
            // Highlight Today's date
            Canvas.Pen.Color := FCalendarColors.TodaysDateFrame;
            Canvas.Brush.Style := bsClear;
            Canvas.Rectangle( R.Left, R.Top, R.Right + 2, R.Bottom );
            Canvas.Brush.Style := bsSolid;
          end;
        end;
        OffsetRect( R, FCellSize.X, 0 );
        DrawDate := DrawDate + 1;
      end;
      if ceWeekNumbers in FElements then
      begin
        Canvas.Brush.Color := Color;
        Canvas.Font.Color := FCalendarColors.DaysOfWeek;
        if Assigned( FOnGetWeekNumber ) then
        begin
          WN := WeekOf( DrawDate - 6 );
          FOnGetWeekNumber( Self, DrawDate, WN );
          DrawStringCentered( Canvas, IntToStr( WN ), WR );
        end
        else
          DrawStringCentered( Canvas, IntToStr( WeekOf( DrawDate - 6 ) ), WR );
        OffsetRect( WR, 0, FCellSize.Y );
      end;
      OffsetRect( R, DaysRect.Left - R.Left, FCellSize.Y );
    end;
    if ButtonsVisible then
    begin
      if ceWeekNumbers in FElements then
      begin
        if FThemeAware and ThemeServices.ThemesEnabled then
          Offset := 6
        else
          Offset := 5;
        DrawHorizontalLine( Areas[ caWeekNumbers ].Right - Offset, DaysRect.Right, DaysRect.Bottom - 1 );
      end
      else
        DrawHorizontalLine( DaysRect.Left, DaysRect.Right, DaysRect.Bottom - 1 );
    end;
  end;
end; {= TRzCalendar.Paint =}

修改後需要重新編譯,然後將編譯後的dcu拷貝至delphi的引用目錄下即可。但是,在編譯的時候又遇到麻煩了,編譯不過去,老是提示RzBorder.pas有問題,最後也改了這個檔案,主要更改的地方有兩個地方:
1、TRzLEDValidChars = Chr( 32 )..Chr( 126 ); //原來是255,修改為126,其實已經夠用了
2、DotMasks: TRzLEDCharacters = .......//這個宣告也改了,將( {~} Col0: $40; Col1: $80; Col2: $40; Col3: $20; Col4: $40 )後面的都截掉了,這樣就可以編譯通過,目前還沒有發現有啥副作用。

 

相關文章