Q&A

  • 일정관리 프로그램을 만들려고 합니다.
안녕하세요..

다름이 아니라 일정관리 프로그램을 아주 간단히 만들려고 합니다.

폼은 달력이 절반을 찾이 하는데 일반적인 컴포넌트는 날짜 부분에 클릭을하면

입력이 되지 않네요. 이 기능을 가진 컴퍼넌트가 없는지..

있으면 알려주시면 감사 하겠습니다.

저도 소스를 감사하는 마음으로 공개를 하겠습니다.

1  COMMENTS
  • Profile
    김영대 1999.10.22 22:33
    정용석 wrote:

    > 안녕하세요..

    > 다름이 아니라 일정관리 프로그램을 아주 간단히 만들려고 합니다.

    > 폼은 달력이 절반을 찾이 하는데 일반적인 컴포넌트는 날짜 부분에 클릭을하면

    > 입력이 되지 않네요. 이 기능을 가진 컴퍼넌트가 없는지..

    > 있으면 알려주시면 감사 하겠습니다.

    > 저도 소스를 감사하는 마음으로 공개를 하겠습니다.



    아래 예제는 제가 전에 만들었던 스케쥴관리의 일부를 발췌한건대

    폼위에는 크기가 700*500 정도의 비어있는 TImage 하고

    년월을 입력받는 TMaskEdit 와 TButton 하나를 올려놓은 다음

    아래 소스를 추가하세요

    아래 소스는 TImage에 직접 그래픽으로 달력을 그리므로 그림같은것은

    직접 Canvas 에 그리시면 됩니다



    그리고 일정의 내용을 입력하는 부분은 없습니다

    소스의 맨 뒷부분을 보시면 쉽게 구현하실 수 있을 겁니다



    unit Unit1;



    interface



    uses

    Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,

    StdCtrls, ExtCtrls, Mask, ComCtrls, Printers;



    type

    TMainForm = class(TForm)

    Button1: TButton;

    ME_yyyymm: TMaskEdit;

    Image_Schedule: TImage;

    procedure Button1Click(Sender: TObject);

    procedure FormCreate(Sender: TObject);

    private

    { Private declarations }

    public

    { Public declarations }

    procedure DrawBackGround(yyyymm: String);

    procedure DrawProgressBar(yyyymm, StartDate, EndDate: String; iColor: TColor);

    procedure DrawEvent(yyyymm, EventDate, Event: String; iColor: TColor);

    end;



    const

    DayOfWeekNames: array[0..6] of String =('일','월','화','수','목','금','토');

    NameHeight = 22;



    var

    MainForm: TMainForm;

    OccupationEvent: array[0..31] of Integer;

    OccupationBar: array[0..31] of Integer;

    MasterCanvas: TCanvas;



    implementation

    {$R *.DFM}



    procedure TMainForm.FormCreate(Sender: TObject);

    begin

    Image_Schedule.Picture.Bitmap := TBitmap.Create; {bitmap 생성}

    MasterCanvas := Image_Schedule.Picture.Bitmap.Canvas;

    ME_yyyymm.EditMask := '####.##;0;_';

    ME_yyyymm.Text := '199905';

    end;



    {===============================================================================

    주어진 년월의 마지막 일자를 구한다

    ===============================================================================}

    function Get_LastDay(yyyy,mm: Integer): Integer;

    var

    MyDate: TDateTime;

    Convert_OK: Boolean;

    dd: Integer;

    begin

    Convert_OK := True;

    dd := 28;

    while Convert_OK do

    begin

    try

    MyDate := EncodeDate(yyyy, mm, dd);

    except

    on EConvertError do

    Convert_OK := False;

    end;

    if Convert_OK then

    Inc(dd)

    else

    Dec(dd);

    end;

    Get_LastDay := dd;

    end;



    {===============================================================================

    주어진 달의 주수를 구한다(마지막 주의 의미)

    ===============================================================================}

    function Get_weeks(yyyy,mm: Integer): Integer;

    var

    MyDate: TDateTime;

    i, weeks: Integer;

    Convert_OK: Boolean;

    begin

    weeks := 0;

    for i := 1 to 31 do

    begin

    try

    Convert_OK := True;

    MyDate := EncodeDate(yyyy, mm, i);

    except

    on EConvertError do

    Convert_OK := False;

    end;

    if Convert_OK then

    if (DayOfWeek(MyDate) = 7) or (Get_LastDay(yyyy,mm) = i) then {토요일이나 달의 마지막이면 1주}

    Inc(weeks);

    end;

    Get_weeks := weeks;

    end;



    {===============================================================================

    주어진 달의 주에 해당하는 날짜from, to, 주의 첫번째 날의 요일번호를 구한다

    ===============================================================================}

    procedure Get_weekfrto(yyyy,mm,week:Integer; var weekfrom:Integer; var weekto:Integer; var dayweek:Integer);

    var

    MyDate: TDateTime;

    i, j, weeks: Integer;

    Convert_OK: Boolean;

    begin

    weekfrom := 0;

    weekto := 0;

    dayweek := 0;



    weeks := 0;

    for i := 1 to 31 do

    begin

    try

    Convert_OK := True;

    MyDate := EncodeDate(yyyy, mm, i);

    except

    on EConvertError do

    Convert_OK := False;

    end;

    if Convert_OK then

    begin

    if (DayOfWeek(MyDate) = 7) or (Get_LastDay(yyyy,mm) = i) then {토요일이나 달의 마지막이면 1주}

    Inc(weeks);

    if weeks = week then

    begin

    weekto := i; {주의 마지막 일자}

    for j := i downto 1 do

    begin

    MyDate := EncodeDate(yyyy, mm, j);

    if (DayOfWeek(MyDate) = 1) or (j = 1) then {일요일이나 그달의 1일이면 주의 시작 일자}

    begin

    weekfrom := j; {주의 시작 일자}

    dayweek := DayOfWeek(MyDate); {주의 첫번째 날의 요일번호}

    Break;

    end;

    end;

    System.Exit;

    end;

    end;

    end;

    end;



    function indc_date(yyyymmdd: String; disc: Integer): String;

    var

    yyyy,mm,dd: Integer;

    MyDate: TDateTime;

    Convert_OK: Boolean;

    begin

    yyyy := StrToIntDef(Copy(yyyymmdd,1,4),-1);

    mm := StrToIntDef(Copy(yyyymmdd,5,2),-1);

    dd := StrToIntDef(Copy(yyyymmdd,7,2),-1);

    if (yyyy <= 0) or (mm <= 0) or (dd <= 0) then

    begin

    indc_date := '';

    System.exit;

    end;



    if disc = 0 then

    begin

    try

    Convert_OK := True;

    MyDate := EncodeDate(yyyy, mm, dd);

    except

    on EConvertError do

    Convert_OK := False;

    end;

    if Convert_OK then

    begin

    indc_date := FormatDateTime('yyyymmdd', MyDate);

    end

    else

    begin

    indc_date := '';

    end;

    end

    else

    begin

    Convert_OK := True;

    try

    MyDate := EncodeDate(yyyy, mm, dd);

    except

    on EConvertError do

    Convert_OK := False;

    end;

    if Convert_OK then

    begin

    indc_date := FormatDateTime('yyyymmdd', MyDate+disc);

    end

    else

    begin

    indc_date := '';

    end;

    end;

    end;



    {===============================================================================

    주어진 년,월,일이 들어가는 주를 구한다

    ===============================================================================}

    function Get_thisweek(yyyy,mm,dd: Integer): Integer;

    var

    MyDate: TDateTime;

    i, weeks: Integer;

    Convert_OK: Boolean;

    begin

    weeks := 0;

    for i := 1 to 31 do

    begin

    try

    Convert_OK := True;

    MyDate := EncodeDate(yyyy, mm, i);

    except

    on EConvertError do

    Convert_OK := False;

    end;

    if Convert_OK then

    if (DayOfWeek(MyDate) = 7) or (Get_LastDay(yyyy,mm) = i) then {토요일이나 달의 마지막이면 1주}

    begin

    Inc(weeks);

    if dd <= i then // 해당 주를 찾았다

    Break;

    end;

    end;

    Get_thisweek := weeks;

    end;



    function DayOfWeekNum(yyyymmdd: String): Integer;

    var

    yyyy,mm,dd: Integer;

    MyDate: TDateTime;

    begin

    yyyy := StrToIntDef(Copy(yyyymmdd,1,4),-1);

    mm := StrToIntDef(Copy(yyyymmdd,5,2),-1);

    dd := StrToIntDef(Copy(yyyymmdd,7,2),-1);



    Result := -1;

    try

    MyDate := EncodeDate(yyyy, mm, dd);

    Result := DayOfWeek(MyDate);

    except

    on EConvertError do

    Result := -1;

    end;

    end;



    procedure TMainForm.DrawBackGround(yyyymm: String);

    var

    max_day, max_week: Integer;

    day_width, day_height: Integer;

    weekfrom, weekto, dayweek: Integer;

    i, j, k, yyyy, mm: Integer;

    temp: String;

    begin

    yyyy := StrToIntDef(Copy(yyyymm,1,4),0);

    mm := StrToIntDef(Copy(yyyymm,5,2),0);

    if (yyyy = 0) or (mm = 0) then

    System.Exit;



    for i := Low(OccupationEvent) to High(OccupationEvent) do

    OccupationEvent[i] := 0;

    for i := Low(OccupationBar) to High(OccupationBar) do

    OccupationBar[i] := 0;



    // 달의 마지막일자

    max_day := Get_LastDay(yyyy, mm);



    // 달의 주수

    max_week := Get_weeks(yyyy, mm);



    day_width := Image_Schedule.Width div 7; // 가로 7칸의 각 폭

    day_height := (Image_Schedule.Height-NameHeight) div 6; // 세로 6칸의 각 높이



    MasterCanvas.Font := Self.Font;



    // 이전의 화면을 지운다

    Image_Schedule.Picture.Bitmap.Width := Image_Schedule.Width;

    Image_Schedule.Picture.Bitmap.Height := Image_Schedule.Height;

    MasterCanvas.Brush.Color := clBtnFace;

    MasterCanvas.FillRect(Rect(0, 0, Image_Schedule.Width, Image_Schedule.Height));



    // 각 일자명을 그린다

    MasterCanvas.Brush.Color := clYellow;

    for i := 0 to 6 do

    begin

    MasterCanvas.Rectangle(day_width*i, 0,

    day_width*(i+1), NameHeight);



    if i = 0 then // 일요일

    MasterCanvas.Font.Color := clRed

    else if i = 6 then // 토요일

    MasterCanvas.Font.Color := clBlue

    else // 평일

    MasterCanvas.Font.Color := clBlack;

    MasterCanvas.TextOut(day_width*i+5, 5, DayOfWeekNames[i]);

    end;



    // 스케줄의 각 일자의 직사각형을 그린다

    MasterCanvas.Brush.Color := clWhite;

    for i := 0 to (max_week-1) do

    begin

    for j := 0 to 6 do

    MasterCanvas.Rectangle(day_width*j, day_height*i+NameHeight,

    day_width*(j+1), day_height*(i+1)+NameHeight);



    end;



    // 스케줄의 각 일자를 출력

    k := 0;

    for i := 0 to (max_week-1) do // 달의 주수만큼

    begin

    // 주어진 달의 주에 해당하는 날짜from, to, 주의 첫번째 날의 요일번호

    Get_weekfrto(yyyy,mm,i+1, weekfrom, weekto, dayweek);

    for j := 0 to 6 do

    begin

    if ((j+1) >= dayweek) and

    ((k+1) <= max_day) then

    begin

    Inc(k);



    if j = 0 then // 일요일

    MasterCanvas.Font.Color := clRed

    else if j = 6 then // 토요일

    MasterCanvas.Font.Color := clBlue

    else // 평일

    MasterCanvas.Font.Color := clBlack;



    MasterCanvas.Brush.Color := clWhite;

    MasterCanvas.TextOut(day_width*j+5, day_height*i+5+NameHeight, inttostr(k));

    end;

    end;

    end;

    end;



    procedure TMainForm.DrawProgressBar(yyyymm, StartDate, EndDate: String; iColor: TColor);

    var

    day_width, day_height: Integer;

    daynum, dayweek: Integer;

    yyyy, mm: Integer;

    CurDate: String;

    iPos: Integer;

    begin

    yyyy := StrToIntDef(Copy(yyyymm,1,4),0);

    mm := StrToIntDef(Copy(yyyymm,5,2),0);



    if (yyyy = 0) or (mm = 0) then

    System.Exit;



    iPos := 1;

    CurDate := StartDate; // 시작일자

    while CurDate <= EndDate do

    begin

    if Copy(CurDate,1,6) = yyyymm then // 기준월의 날짜만 그린다

    begin

    // 요일에 출력되는 막대 카운트

    OccupationBar[StrToIntDef(Copy(CurDate,7,2),0)] :=

    OccupationBar[StrToIntDef(Copy(CurDate,7,2),0)] + 1;

    if iPos < OccupationBar[StrToIntDef(Copy(CurDate,7,2),0)] then // 해당기간의 최대 카운트

    iPos := OccupationBar[StrToIntDef(Copy(CurDate,7,2),0)];

    end;

    CurDate := indc_date(CurDate, 1); // 날짜증가

    end;



    day_width := Image_Schedule.Width div 7; // 가로 7칸의 각 폭

    day_height := (Image_Schedule.Height-NameHeight) div 6; // 세로 6칸의 각 높이



    CurDate := StartDate; // 시작일자

    while CurDate <= EndDate do

    begin

    if Copy(CurDate,1,6) = yyyymm then // 기준월의 날짜만 그린다

    begin

    daynum := Get_thisweek(StrToInt(Copy(CurDate,1,4)), // 해당 년월일의 주번호

    StrToInt(Copy(CurDate,5,2)),

    StrToInt(Copy(CurDate,7,2)));



    dayweek := DayOfWeekNum(CurDate); // 요일번호



    // 막대기

    MasterCanvas.Brush.Color := iColor;

    MasterCanvas.FillRect(Rect(day_width*(dayweek-1)+ 4,

    day_height*(daynum-1)+ day_height-(iPos*5)-2+NameHeight,

    day_width*(dayweek-1)+ day_width-4,

    day_height*(daynum-1)+ day_height-(iPos*5)+1+NameHeight));



    if CurDate = StartDate then // 시작점 그리기

    MasterCanvas.FillRect(Rect(day_width*(dayweek-1)+ 4,

    day_height*(daynum-1)+ day_height-(iPos*5)-2+NameHeight-1,

    day_width*(dayweek-1)+ 6,

    day_height*(daynum-1)+ day_height-(iPos*5)-2+NameHeight+1));



    if CurDate = EndDate then // 종료점 그리기

    MasterCanvas.FillRect(Rect(day_width*(dayweek-1)+ day_width-6,

    day_height*(daynum-1)+ day_height-(iPos*5)+1+NameHeight-1,

    day_width*(dayweek-1)+ day_width-4,

    day_height*(daynum-1)+ day_height-(iPos*5)+1+NameHeight+1));



    end;

    CurDate := indc_date(CurDate, 1); // 날짜증가

    end;

    end;



    procedure TMainForm.DrawEvent(yyyymm, EventDate, Event: String; iColor: TColor);

    var

    day_width, day_height: Integer;

    daynum, dayweek: Integer;

    iPos: Integer;

    begin

    if Copy(EventDate,1,6) <> yyyymm then // 기준월의 날짜에 속하지 않으면...

    System.Exit;



    // 요일에 출력되는 이벤트 카운트

    OccupationEvent[StrToIntDef(Copy(EventDate,7,2),0)] :=

    OccupationEvent[StrToIntDef(Copy(EventDate,7,2),0)] + 1;

    iPos := OccupationEvent[StrToIntDef(Copy(EventDate,7,2),0)];



    day_width := Image_Schedule.Width div 7; // 가로 7칸의 각 폭

    day_height := (Image_Schedule.Height-NameHeight) div 6; // 세로 6칸의 각 높이



    daynum := Get_thisweek(StrToInt(Copy(EventDate,1,4)), // 해당 년월일의 주번호

    StrToInt(Copy(EventDate,5,2)),

    StrToInt(Copy(EventDate,7,2)));



    dayweek := DayOfWeekNum(EventDate); // 요일번호



    MasterCanvas.Font.Color := iColor;

    MasterCanvas.Brush.Color := clWhite;

    MasterCanvas.TextOut(day_width*(dayweek-1)+ (day_width div 2) - (MasterCanvas.TextWidth(Event) div 2),

    day_height*(daynum-1)+ (iPos*13) +3+ NameHeight, Event);

    end;



    procedure TMainForm.Button1Click(Sender: TObject);

    begin

    // 기준년월의 달력을 그린다

    DrawBackGround(ME_yyyymm.Text);



    // 기준년월의 각 스케쥴과 이벤트를 그린다

    DrawProgressBar(ME_yyyymm.Text, '19990506', '19990510', clRed);

    DrawEvent(ME_yyyymm.Text, '19990507', '검토', clGreen);

    DrawEvent(ME_yyyymm.Text, '19990503', '술먹는날', clGreen);

    DrawEvent(ME_yyyymm.Text, '19990513', '술먹는날', clGreen);

    DrawEvent(ME_yyyymm.Text, '19990523', '술먹는날', clGreen);



    DrawProgressBar(ME_yyyymm.Text, '19990501', '19990505', clRed);

    DrawEvent(ME_yyyymm.Text, '19990502', '생일이브', clRed);

    DrawEvent(ME_yyyymm.Text, '19990503', '생일', clRed);



    DrawProgressBar(ME_yyyymm.Text, '19990520', '19990530', clBlue);

    DrawEvent(ME_yyyymm.Text, '19990522', '검수일', clBlue);

    DrawEvent(ME_yyyymm.Text, '19990529', '토요근무', clBlue);



    DrawProgressBar(ME_yyyymm.Text, '19990503', '19990506', clBlack);

    DrawEvent(ME_yyyymm.Text, '19990503', '시연회', clBlack);



    DrawProgressBar(ME_yyyymm.Text, '19990726', '19990726', clBlue);

    DrawEvent(ME_yyyymm.Text, '19990726', '생일', clBlue);

    end;



    end.