1. 개요
TDateTimePicker 또는 TMonthCalendar의 월력을 Open 했을 때 특정 지정된 날짜를 마킹하여 특정한 목적으로 사용자에게 알려 주어야 하는 경우가 있다. 기본 컴포넌트인 TMonthCalendar를 이용하여 원하는 날짜들에 마킹(볼드체)하는 방법을 알아보자
2. TMonthCalendar의 "OnGetMonthInfo" 이벤트
이 이벤트는 TMonthCalendar 컴포넌트에 새로운 월(Month)가 Display될 때 호출 되는데 화면에 노출되는 일자에 대한 특정한 속성을 초기화 하고자 할 때 사용된다.(예를 들어 일요일 토요일, 국경일 등에 대한 표식이 필요할 경우 등)
이 이벤트 호출을 통하여 특정한 날짜를 굵게(Bold)로 표시할 수 있다.
// 표시된 달력의 1일, 8일을 굵게 표시한다.
BoldDays([1,8], MonthBoldInfo);
or
unsigned bolddays[2] = {1,2};
BoldDays(bolddays, MonthBoldInfo);
3. 매월 표시해야 할 사용자 지정일자가 다른 경우에 대한 처리
위에서 처럼 처리하면 모든 월(Month)에 동일한 날짜가 굵게 표시 되는데 일반적으로 스케쥴 관리와 같이 매월 사용자가 지정한 특정한 날이 다를 수 있는데 이를 위해서는 좀 다르게 처리해 주어야 한다.
OnGetMonthInfo이벤트는 달력의 월이 바뀔 때마다 발생하게 되는데 매번 3번씩 호출 된다. 첫 번째는 이전달, 두 번째는 이번달 그리고 세 번째는 다음달이 Month 파라미터에 넘겨져서 호출 된다. 따라서 표시하고자 하는 현재 월만 선택하여 현재 선택된 월의 마킹 날자 리스트를 얻고 표시해 주어야 한다. 여기서 주의 할 점은 Month(월)만 넘어오기 때문에 연도를 유추 해 내야 한다는 것인데 이를 위해서도 약간의 코딩이 필요하다.
4. TMonthCalendar의 "BoldDays" 함수
파라미터인 ABoldDays 배열에 담긴 지정된 날짜들을 1~31 비트로 매핑하여 DWORD 값으로 MonthBoldInfo에 리턴한다
예) MonthCalendar1.BoldDays([3,21,28],MonthBoldInfo); { Day 3, 21, 28 }
5. TEST 프로그램 결과
6. TEST 프로그램 소스
unit uTestMain; {** Usage : TMonthCalendar에 월별 특정한 날짜들을 마킹(Bold) 해 본다 * Created By niceondal, 2014-12-08 *} interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, ComCtrls, CommCtrl; type TForm1 = class(TForm) calendar: TMonthCalendar; procedure calendarGetMonthInfo(Sender: TObject; Month: Cardinal; var MonthBoldInfo: Cardinal); private function SetExistDateToCalenar(ADate: TDateTime): DWORD; { Private declarations } public { Public declarations } end; var Form1: TForm1; implementation {$R *.dfm} type TArrBold = array of DWORD; const testBoldDates : array[1..12] of array[0..6] of DWORD = ((1,3,4,6,7,8,9), (1,2,3,4,5,9,10), (4,6,8,15,19,20,21), (11,22,23,24,25,29,30), (11,12,13,14,15,19,20), (5,10,15,20,25,26,27), (2,4,6,8,10,12,14), (12,14,16,18,20,22,24), (1,3,5,7,5,9,10), (4,8,12,16,20,24,28), (1,2,4,8,16,21,22), (1,3,5,16,20,24,28) ); var _LastMonth : integer; _LastYear : integer; _LastTickCount : Integer; _CallCountOfMonthInfo : Integer; function CheckTickCount:Boolean; var C:Cardinal; begin C:=GetTickCount; Result: = _LastTickCount+100 < C; // Less than 0,1s allowed between events _LastTickCount := C; end; // 해당날짜가 속한 월의 마킹 날자 배열을 구하여 MonthCalendar에 적용시킨다 // 연도 옵션을 추가하여 년/월 별 마킹을 추가로 구현해보세요(....) function TForm1.SetExistDateToCalenar(ADate: TDateTime) : DWORD; var DayStates: array[0..2] of DWORD; mon : DWORD; arrDate : array of DWORD; yy, mm, dd : Word; begin result := 0; DecodeDate(ADate, yy, mm, dd); //여기에서 연도/월별 Bold시킬 배열을 얻도록 한다. //연도(yy)에 따라 다를 경우도 처리해 주어야 함 if Length(testBoldDates[mm])>0 then begin calendar.BoldDays(testBoldDates[mm], mon); DayStates[1] := mon; result := mon; end else begin DayStates[1] := 0; result := 0; end; DayStates[0] := 0; DayStates[2] := 0; SendMessage(calendar.Handle, MCM_SETDAYSTATE, 3, longint(@DayStates)); end; procedure TForm1.calendarGetMonthInfo(Sender: TObject; Month: Cardinal; var MonthBoldInfo: Cardinal); var dd : TDateTime; tmp : string; Year,Mon,Day,YearMonth:Word; begin // 연도를 계산하기 위한 모듈 if CheckTickCount Or ((Month<>_LastMonth+1) And Not ((_LastMonth=12) And (Month=1))) then begin DecodeDate((Sender As TMonthCalendar).Date,Year,Mon,Day); if Month>Mon then Dec(Year); end Else begin if _LastMonth=12 then Year:=_LastYear+1 Else Year:=_LastYear; end; _LastMonth:=Month; _LastYear:=Year; // 현재 노출되어져야 할 월을 판별하기 위한 모듈 Inc(_CallCountOfMonthInfo); if _CallCountOfMonthInfo=2 then //현재 표시될 월에 ㅎ당 begin // Calendar가 다음월 다음해 등으로 스크롤 되는 경우 현재 표시되고 있는 년/월을 정확히 알아낸다. tmp := Format('%4d-%2d-01', [Year, Month]); tmp := StringReplace(tmp, ' ', '0', []); //여기에 해당 월별 Bold로 표시핼 배열 정보를 얻도록 한다. MonthBoldInfo := SetExistDateToCalenar(StrToDate(tmp)); end else MonthBoldInfo := 0; if _CallCountOfMonthInfo = 3 then //초기화(3번씩 호출되는 마지막번째 호출됨) _CallCountOfMonthInfo := 0; end; end.
7. 간단하게 현재 달력에 특정한 날짜들을 간단히 Bold로 지정하는 방법은 다음과 같이 하면 된다.
procedure TForm1.btnTestClick(Sender: TObject); var monInfo : Cardinal; DayStates: array[0..2] of DWORD; begin calendar.BoldDays([1,2,3,4,5,6,7,8,9], monInfo); DayStates[0] := 0; DayStates[1] := monInfo; DayStates[2] := 0; SendMessage(calendar.Handle, MCM_SETDAYSTATE, 3, longint(@DayStates)); end;
'프로그래밍 > Delphi' 카테고리의 다른 글
TRichEdit에서 전체선택(CTRL+A)시 문서 끝으로 자동 스크롤 시키기 (0) | 2014.12.18 |
---|---|
TRichEdit에서 기본 컨텍스트팝업메뉴(Context Popup Menu) 활성화 시키기 (0) | 2014.12.18 |
TIdHTTPServer 응답헤더(Response Header) 다루기 (0) | 2014.10.14 |
문자열에서 Null문자 제거하기 (0) | 2014.10.14 |
델파이 TWebBrowser 컴포넌트에서 자바스크립트 직접 실행하는 방법 (1) | 2014.10.10 |