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;
'IT > 델파이' 카테고리의 다른 글
TRichEdit에서 전체선택(CTRL+A)시 문서 끝으로 자동 스크롤 시키기 (0) | 2023.02.15 |
---|---|
TRichEdit에서 기본 컨텍스트팝업메뉴(Context Popup Menu) 활성화 시키기 (0) | 2023.02.15 |
TIdHTTPServer 응답헤더(Response Header) (0) | 2023.02.15 |
문자열에서 Null문자 제거하기 (0) | 2023.02.15 |
델파이 TWebBrowser 컴포넌트에서 자바스크립트 직접 실행하는 방법 (0) | 2023.02.15 |