Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Delphi программирование > Общие вопросы Delphi
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 26.12.2016, 12:18   #1
Ship_1
Форумчанин
 
Регистрация: 10.02.2014
Сообщений: 526
По умолчанию Не пойму как правильно задать условие отрисовки месяца

Здравствуйте!
Делаю программку для задания интервала между датами кликаньем по выведенному календарю. Много сырости, которую ещё буду дорабатывать, но самое проблемное для меня - не пойму как правильно задать условие вывода первого месяца.
Суть: выводится 12 месяцев следующего (2017) года, с января по декабрь. Если навести на какой-нибудь день - он и 28 следующих дней закрашиваются другим цветом.
Если курсор наводится на день в декабре, то январь следующего (2017) года должен замениться на январь послеследующего (2018) года. А когда курсор покидает поле декабря - снова должен появиться январь следующего (2017) года.
Пробовал несколько пришедших в голову вариантов, но ни один не работал нормально. Основное, что получалось всегда - при сдвиге курсора с декабря на ноябрь январь получается "комбинированным" - несколько первых дней получаются из 2018 года, а остальные из 2017. И я никак не пойму как сделать так, чтоб смена месяца происходила правильно и полностью.
Может, кто-нибудь сможет разобраться в проблеме и посоветовать как её решить?
Весь код.
Код:
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, DateUtils, StdCtrls;

type
  TForm1 = class(TForm)
    Label1: TLabel;
    Label2: TLabel;
    Label3: TLabel;
    procedure DrawCalCel(Canv: TCanvas; DrawDate:TDate; ColZal:TColor = clWhite);
    procedure DrawMonth(Canv: TCanvas; DrawDate:TDate);
    procedure FormPaint(Sender: TObject);
    procedure FormMouseMove(Sender: TObject; Shift: TShiftState; X,
      Y: Integer);
    procedure FormCreate(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

const
  CalendStPoint: TPoint = (X:350; Y:50); // верхний левый пикселюь вывода календаря
  MCell: TPoint = (X:25; Y:20); // размер нарисованной ячейки даты календаря
  StartDate: string = '01.01.'; // для получения начала года
  MonthName: array [1..12] of string = ('январь','‘евраль','ћарт','јпрель','ћай','»юнь','»юль','јвгуст','—ент¤брь','ќкт¤брь','Ќо¤брь','ƒекабрь');
  DayWeekName: array [1..7] of string = ('пн','вт','ср','чт','пт','сб','вс');

var
  Form1: TForm1;
  OutYear: Word;
  InDate:TDate;
  PrevDate, NowDate:TDate;
  FromFeb: boolean;


implementation

{$R *.dfm}


procedure TForm1.DrawCalCel(Canv: TCanvas; DrawDate:TDate; ColZal:TColor = clWhite);
var
  Cell_DIM: TPoint;
  DatCor,MonthCor:TPoint;
  TH,TW: Integer;
  OutCorr:Integer;
begin
  OutCorr:=DayOfTheWeek(DrawDate-DayOf(DrawDate));
  If OutCorr = 7 then OutCorr := 0;
  DatCor.X:=(DayOf(DrawDate)-1+OutCorr) mod 7;   DatCor.Y:=(DayOf(DrawDate)-1+OutCorr) div 7;
  MonthCor.X:=(MonthOf(DrawDate)-1) mod 4;      MonthCor.Y:=(MonthOf(DrawDate)-1) div 4;

  Cell_DIM.X:=CalendStPoint.X+DatCor.X*(MCell.X+4)+MonthCor.X*((MCell.X+4)*7+25);
  Cell_DIM.Y:=CalendStPoint.Y+DatCor.Y*(MCell.Y+4)+MonthCor.Y*((MCell.Y+4)*6+25);
  Canvas.Brush.Color:=ColZal;
  Canvas.Rectangle(Cell_DIM.X,Cell_DIM.Y,Cell_DIM.X+MCell.X+1,Cell_DIM.Y+MCell.Y+1);
  if (DayOfTheWeek(DrawDate) = 6) or (DayOfTheWeek(DrawDate) = 7) then
    Canvas.Font.Color:=clRed
  else
    Canvas.Font.Color:=clBlack;

  TH:=Canvas.TextHeight(IntToStr(DayOf(DrawDate)));
  TW:=Canvas.TextWidth(IntToStr(DayOf(DrawDate)));
  Canvas.TextOut(Cell_DIM.X+(MCell.X div 2 - TW div 2),Cell_DIM.Y+(MCell.Y div 2 - TH div 2),IntToStr(DayOf(DrawDate)));

end;


procedure TForm1.DrawMonth(Canv: TCanvas; DrawDate:TDate);
var
  Cell_DIM: TPoint;
  DatCor,MonthCor:TPoint;
  TH,TW, i: Integer;
  OutCorr:Integer;
begin

  MonthCor.X:=(MonthOf(DrawDate)-1) mod 4;      MonthCor.Y:=(MonthOf(DrawDate)-1) div 4;

  Cell_DIM.X:=CalendStPoint.X+MonthCor.X*((MCell.X+4)*7+25);
  Cell_DIM.Y:=CalendStPoint.Y+MonthCor.Y*((MCell.Y+4)*6+25);

  Canvas.Brush.Color:=ClBlue;
  Canvas.Rectangle(Cell_DIM.X,Cell_DIM.Y,Cell_DIM.X+(MCell.X+4)*7+1,Cell_DIM.Y+(MCell.Y+4)*6+1);
  Canvas.Brush.Color:=ClWhite;

  For i:=0 to DaysInAMonth(YearOf(DrawDate),MonthOf(DrawDate))-1 do DrawCalCel(Canvas,EncodeDate(YearOf(DrawDate),MonthOf(DrawDate),i+1));


end;

procedure TForm1.FormPaint(Sender: TObject);
var i,StM:integer;
    BeginDate, OutDate:TDate;
begin
  BeginDate:=StrToDate(StartDate+IntToStr(OutYear));

  If FromFeb Then StM:=1 else StM:=0;
  For i:=0 to 11 do
     DrawMonth(Canvas,IncMonth(BeginDate,i));

end;

procedure TForm1.FormMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);
var
  AreaCal:TRect;
  MonthPos,DayPos,i:Integer;
  MonthP,DayP:TPoint;
  MonthWith, MonthHeight, OutCorr: Integer;
  OutDate:TDate;
begin

  AreaCal.Left:=CalendStPoint.X;
  AreaCal.Top:=CalendStPoint.Y;
  MonthWith:=(MCell.X+4)*7+25;
  MonthHeight:=(MCell.Y+4)*6+25;
  AreaCal.Right:=AreaCal.Left+MonthWith*4;
  AreaCal.Bottom:=AreaCal.Top+MonthHeight*3;

    Label1.Caption:=DateToStr(PrevDate);
    Label2.Caption:=DateToStr(NowDate);
    Label3.Caption:=DateToStr(InDate);

  If ((AreaCal.Left<X) and (X<AreaCal.Right)) and ((AreaCal.Top<Y) and (Y<AreaCal.Bottom)) then
  begin
    Form1.Color:=clWhite;
    //======== определение мес¤ца =====
    MonthP.X:= (X - CalendStPoint.X) div MonthWith;
    MonthP.Y:= (Y - CalendStPoint.Y) div MonthHeight;
    MonthPos:=MonthP.Y*4+MonthP.X+1;
    //======== определение мес¤ца (конец) =====
    //======== определение дн¤ =====
    DayP.X:= (X - CalendStPoint.X - MonthP.X*MonthWith) div (MCell.X+4);
    DayP.Y:= (Y - CalendStPoint.Y - MonthP.Y*MonthHeight) div (MCell.Y+4);
    InDate:=StrToDate('1.'+IntToStr(MonthPos)+'.'+IntToStr(OutYear));
    OutCorr:=DayOfTheWeek(InDate);
    DayPos:=DayP.Y*7+DayP.X+1-OutCorr+1;
    If IsValidDate(OutYear,MonthPos,DayPos) then InDate:=StrToDate(IntToStr(DayPos)+'.'+IntToStr(MonthPos)+'.'+IntToStr(OutYear))
                          else InDate:=StrToDate('01.01.1800');
    //======== определение дн¤ (конец) =====

    if MonthOf(InDate)=12 then
    begin
      if not FromFeb then
      begin
        FromFeb:=true;
        Form1.Repaint;
      end;
    end;
    if MonthOf(InDate)<>12 then
    begin
      if FromFeb then
      begin
        FromFeb:=false;
        Form1.Repaint;
      end;
    end;
    //======== закраска следующих ==========
    If (InDate<>NowDate) and (InDate<>(StrToDate('01.01.1800'))) then
    begin

      PrevDate:=NowDate;
      NowDate:=InDate;

      If PrevDate<>(StrToDate('01.01.1800')) then
      begin
        For i:=0 to 27 do
        begin
          OutDate:=PrevDate+i;
          DrawCalCel(Canvas,OutDate);
        end;
      end;
      For i:=0 to 27 do
      begin
        OutDate:=NowDate+i;
        if i=0 then DrawCalCel(Canvas,OutDate,clYellow)
               else DrawCalCel(Canvas,OutDate,clAqua);
      end;
    end;
    //===== закраска следующих (конец) =====
  end
  else
  begin
    InDate:=StrToDate('01.01.1800');
    if MonthOf(NowDate)=12 then DrawMonth(Canvas,IncMonth(NowDate,-11));
    NowDate:=StrToDate('01.01.1800');
    Form1.Color:=clBtnFace;
    Label1.Caption:='___';
  end

end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  OutYear:=YearOf(Date)+1;
  InDate:=StrToDate('01.01.1800');
  NowDate:=StrToDate('01.01.1800');
  FromFeb:=false;
end;

end.
Ship_1 вне форума Ответить с цитированием
Старый 26.12.2016, 12:37   #2
FaTaL
Участник клуба
 
Аватар для FaTaL
 
Регистрация: 09.11.2007
Сообщений: 1,761
По умолчанию

Вам для чего такой календарь нужен? Может легче использовать TDateTimePicker?
FaTaL вне форума Ответить с цитированием
Старый 26.12.2016, 12:59   #3
Аватар
Старожил
 
Аватар для Аватар
 
Регистрация: 17.11.2010
Сообщений: 18,922
По умолчанию

MouseMove не очень то в дебагере отладишь. В лог записывай значения переменных в нужных точках программы, там и увидишь что не так
Если бы архитекторы строили здания так, как программисты пишут программы, то первый залетевший дятел разрушил бы цивилизацию
Аватар вне форума Ответить с цитированием
Старый 26.12.2016, 13:00   #4
Ship_1
Форумчанин
 
Регистрация: 10.02.2014
Сообщений: 526
По умолчанию

В итоге - для ввода и отображения графика отпусков. Календарь будет позволять указать интервал отпуска и закрашивать другими цветами уже внесённые отпуски.
Ship_1 вне форума Ответить с цитированием
Старый 26.12.2016, 13:03   #5
Аватар
Старожил
 
Аватар для Аватар
 
Регистрация: 17.11.2010
Сообщений: 18,922
По умолчанию

На OnMouseMove зря посадил. Лучше на клик на нужной дате. Имхо. И на канвас формы прорисовку зря. Для этого есть паинтбокс. И для отпусков по идее красные дни нужно учитывать. Да и не обязательно отпуск целиком берется
Если бы архитекторы строили здания так, как программисты пишут программы, то первый залетевший дятел разрушил бы цивилизацию
Аватар вне форума Ответить с цитированием
Старый 26.12.2016, 13:15   #6
Ship_1
Форумчанин
 
Регистрация: 10.02.2014
Сообщений: 526
По умолчанию

Цитата:
Сообщение от Аватар Посмотреть сообщение
На OnMouseMove зря посадил. Лучше на клик на нужной дате.
Что зря? Заливку следующих дней? Ну может быть... Но определение даты всё равно же по OnMouseMove? На клик по нужной дате для реализации, возможно, и проще, но хуже для наглядности. Так при наведении на дату сразу видно и дату окончания предполагаемого отпуска.

Цитата:
Сообщение от Аватар Посмотреть сообщение
И на канвас формы прорисовку зря. Для этого есть паинтбокс.
Отрисовывать полностью в паинтбоксе и копировать в канвас формы целиком? А это не сложнее для программы будет?.. Если каждый момент копировать весь большой прямоугольник.

Цитата:
Сообщение от Аватар Посмотреть сообщение
И для отпусков по идее красные дни нужно учитывать. Да и не обязательно отпуск целиком берется
Ну это всё планируется в доработке: ввод и добавление праздничных дней, первый клик - для даты начала отпуска, второй в интервале оставшихся дней - для даты его окончания.
Ship_1 вне форума Ответить с цитированием
Старый 26.12.2016, 15:52   #7
Аватар
Старожил
 
Аватар для Аватар
 
Регистрация: 17.11.2010
Сообщений: 18,922
По умолчанию

А чего не стринггрид например? Удобнее же и намного
Если бы архитекторы строили здания так, как программисты пишут программы, то первый залетевший дятел разрушил бы цивилизацию
Аватар вне форума Ответить с цитированием
Старый 26.12.2016, 16:15   #8
Ship_1
Форумчанин
 
Регистрация: 10.02.2014
Сообщений: 526
По умолчанию

А смысл? Я даты разных людей разными цветами хочу закрашивать, и если два человека на одной дате - будет половина одним цветом, половина другим. Соответственно всё равно на стринггридах придётся вручную рисовать, так что разница разве что в координации по ячейкам у него в плюсе, но зато графически есть ограничения.
Ship_1 вне форума Ответить с цитированием
Старый 26.12.2016, 16:31   #9
Аватар
Старожил
 
Аватар для Аватар
 
Регистрация: 17.11.2010
Сообщений: 18,922
По умолчанию

Легких путей не ищешь? Ну как хочешь ))
Если бы архитекторы строили здания так, как программисты пишут программы, то первый залетевший дятел разрушил бы цивилизацию
Аватар вне форума Ответить с цитированием
Старый 26.12.2016, 16:48   #10
Ship_1
Форумчанин
 
Регистрация: 10.02.2014
Сообщений: 526
По умолчанию

Ну вообще что-то я действительно и не подумал про стринггрид, порисовать захотелось Но тем не менее а как лёгкими визуальными путями на стринггриде отметить отпуск двух-трёх человек в один день (и чтоб было понятно какие это люди)?
Ship_1 вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
VB как правильно задать условие в запросе на выборку? SvarogIS Microsoft Office Access 3 26.12.2015 17:56
Построить график любой функции+как задать условие Kornegi Общие вопросы Delphi 10 13.10.2014 14:52
Как правильно задать функцию ? L6go1as C# (си шарп) 3 23.04.2014 20:03
как задать условие в Excel Юлия21 Помощь студентам 2 26.04.2012 11:58
Как задать условие DDiKey Microsoft Office Excel 3 23.03.2012 01:52