unit Un_frmDBGridEditDate;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls, Grids, Buttons, Menus, db,DBGrids, ExtCtrls;
type
TfrmDBGridEditDate = class(TForm)
sgDays: TStringGrid;
lMonth: TLabel;
btnNextMonth: TSpeedButton;
btnSelectMonth: TSpeedButton;
btnNextYear: TSpeedButton;
btnSelectYear: TSpeedButton;
btnPriorMonth: TSpeedButton;
btnPriorYear: TSpeedButton;
pmSelectMonth: TPopupMenu;
N01: TMenuItem;
N02: TMenuItem;
N03: TMenuItem;
N04: TMenuItem;
N05: TMenuItem;
N06: TMenuItem;
N07: TMenuItem;
N08: TMenuItem;
N09: TMenuItem;
N10: TMenuItem;
N11: TMenuItem;
N12: TMenuItem;
pmSelectYear: TPopupMenu;
N1998: TMenuItem;
N1999: TMenuItem;
N2000: TMenuItem;
N2001: TMenuItem;
N2002: TMenuItem;
N2003: TMenuItem;
shLeftLine: TShape;
shRightLine: TShape;
shTopLine: TShape;
shBottomLine: TShape;
tmrChangeTime: TTimer;
pOk: TPanel;
btnToday: TSpeedButton;
btnOk: TSpeedButton;
pClock: TPanel;
lHoure: TLabel;
Label2: TLabel;
lMinets: TLabel;
Image1: TImage;
Image2: TImage;
Image3: TImage;
Image4: TImage;
btnMinetsDown: TSpeedButton;
btnHoureDown: TSpeedButton;
btnHoureUp: TSpeedButton;
btnMinetsUp: TSpeedButton;
procedure SetToday(Sender: TObject);
procedure sgDaysDrawCell(Sender: TObject; ACol, ARow: Integer;
Rect: TRect; State: TGridDrawState);
procedure FillDays(Sender: TObject);
procedure sgDaysSelectCell(Sender: TObject; ACol, ARow: Integer;
var CanSelect: Boolean);
procedure FormShow(Sender: TObject);
procedure btnNextMonthClick(Sender: TObject);
procedure btnPriorMonthClick(Sender: TObject);
procedure btnNextYearClick(Sender: TObject);
procedure btnPriorYearClick(Sender: TObject);
procedure SelectMonth(Sender: TObject);
procedure SetMonth(Sender: TObject);
procedure SelectYear(Sender: TObject);
procedure SetYear(Sender: TObject);
procedure FormClose(Sender: TObject; var Action: TCloseAction);
procedure btnOkClick(Sender: TObject);
procedure ChangeTime(Sender: TObject);
procedure StartTimer(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
procedure StopTimer(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
procedure ChangeTimeByTimer(Sender: TObject);
private
FDate:TDate;
FMonth:Word;
FYear:Word;
FDay:Word;
FControl: TDBGrid;
FControlHandle: HWND;
FOnChangeField:TFieldNotifyEvent;
FOnStateChange:TNotifyEvent;
FTime: TTime;
FWithClock: Boolean;
procedure SetControl(const Value: TDBGrid);
procedure OnChangeField(Sender: TField);
procedure OnStateChange(Sender:TObject);
procedure RestoreEvents;
procedure SetDate(const Value: TDate);
procedure SendToControl;
procedure SendDateToControl(ADate: TDate);
procedure SendTimeToControl(ATime: TTime);
procedure SetTime(const Value: TTime);
procedure SetWithClock(const Value: Boolean);
// procedure RebuildWindowRgn;
public
property WithClock:Boolean read FWithClock write SetWithClock;
constructor Create(AOwner: TComponent);override;
property SelectedDate:TDate read FDate write SetDate;
property SelectedTime:TTime read FTime write SetTime;
property Control:TDBGrid read FControl write SetControl;
procedure Show;
end;
procedure ShowDateEditor(AGrid:TDBGrid;AWithClock:Boolean=False);
implementation
uses
DateUtil;
var
Hook:HHOOK;
AForm:TfrmDBGridEditDate;
function KeyboardProc(Code:Integer;_WParam:WParam;_LParam:LParam):LResult;stdcall;
begin
if _WParam=VK_ESCAPE then
AForm.Close;
Result:=CallNextHookEx(Hook,Code,_wParam,_LParam);
end;
{$R *.DFM}
procedure ShowDateEditor(AGrid:TDBGrid;AWithClock:Boolean=False);
var
Y,M,D,H,N,S,mS:Word;
begin
if Assigned(AForm) then begin
Beep;
Exit;
//Raise Exception.Create('ShowDateEditor:Модуль уже используется');
end;
AForm:=TfrmDBGridEditDate.Create(AGrid);
with AForm do begin
Control:=AGrid;
WithClock:=AWithClock;
Show;
if (AGrid.SelectedField.AsDateTime > 0) then
begin
DecodeDate(AGrid.SelectedField.AsDateTime,Y,M,D);
DecodeTime(AGrid.SelectedField.AsDateTime,H,N,S,mS);
end else
begin
DecodeDate(Date,Y,M,D);
DecodeTime(Date,H,N,S,mS);
end;
SelectedDate:=EncodeDate(Y,M,D);
SelectedTime:=EncodeTime(H,N,0,0);
// Show;
end;
end;
procedure TfrmDBGridEditDate.SendDateToControl(ADate:TDate);
var
sBuf:string;
I:Integer;
ALength:Integer;
begin
ALength:=GetWindowTextLength(FControlHandle);
SendMessage(FControlHandle, EM_SETSEL, 0, ALength);
SendMessage(FControlHandle, WM_CHAR, 8, 0);
sBuf:=DateToStr(ADate);
for I:=1 to Length(sBuf) do
SendMessage(FControlHandle,WM_CHAR,Ord(sBuf[I]),0);
Windows.SetFocus(FControlHandle);
end;
procedure TfrmDBGridEditDate.SetDate(const Value: TDate);
var
ARow,ACol,LastDay,ADay,AMonth,AYear:Word;
CurDate:TDate;
begin
FDate:=Value;
lMonth.Caption:=FormatDateTime('mmmm ( mm ) ,yyyy',FDate);
SendToControl;
with sgDays do begin
//Очистка грида
for ARow:=1 to RowCount-1 do
Rows[ARow].Clear;
DecodeDate(FDate,AYear,AMonth,ADay);
FDay:=ADay;
FMonth:=AMonth;
FYear:=AYear;
ADay:=1;
CurDate:=EncodeDate(AYear,AMonth,1);
ACol:=(DayOfWeek(CurDate)+5) mod 7;
ARow:=1;
LastDay:=0;
while (ARow<=6) do begin
while (ACol<=6) do begin
Cells[ACol,ARow]:=IntToStr(ADay);
if CurDate=FDate then begin
OnSelectCell:=nil;
Row:=ARow;
Col:=ACol;
OnSelectCell:=sgDaysSelectCell;
end;
CurDate:=IncDay(CurDate,1);
Inc(ACol);
LastDay:=ADay;
DecodeDate(CurDate,AYear,AMonth,ADay);
if (LastDay>ADay) then Break;
end;
if (LastDay>ADay) then Break;
ACol:=0;
Inc(ARow);
end;
end;
end;
procedure TfrmDBGridEditDate.SetToday(Sender: TObject);
begin
if SelectedDate=Date then
Close
else SelectedDate:=Date;
end;
procedure TfrmDBGridEditDate.sgDaysDrawCell(Sender: TObject; ACol,
ARow: Integer; Rect: TRect; State: TGridDrawState);
begin
with sgDays,sgDays.Canvas do begin
if (ACol in [5,6]) then
Font.Color :=clRed;
if gdSelected in State then begin
Brush.Color:=clMenu;
Font.Color:=clWhite;
end;
FillRect(Rect);
if (ARow>0)and(Cells[ACol,ARow]<>'')and(Date=EncodeDate(FYear,FMonth,StrToInt(Cells[ACol,ARow]))) then
Font.Style:=Font.Style+[fsBold];
TextOut(Rect.Right-TextWidth(Cells[ACol,ARow])-2,Rect.Top+2,Cells[ACol,ARow]);
if (ARow in [0,6]) then begin
Pen.Color:=clBlack;
MoveTo(Rect.Left,Rect.Bottom);
LineTo(Rect.Right+1,Rect.Bottom);
end;
end;
end;
procedure TfrmDBGridEditDate.FillDays(Sender: TObject);
begin
with sgDays do begin
Cells[0,0]:='Пн';
Cells[1,0]:='Вт';
Cells[2,0]:='Ср';
Cells[3,0]:='Чт';
Cells[4,0]:='Пт';
Cells[5,0]:='Сб';
Cells[6,0]:='Вс';
end;
end;
procedure TfrmDBGridEditDate.sgDaysSelectCell(Sender: TObject; ACol,
ARow: Integer; var CanSelect: Boolean);
begin
with sgDays do begin
CanSelect:=(ARow>0)and(Cells[ACol,ARow]<>'');
if CanSelect then begin
FDay:=StrToInt(Cells[ACol,ARow]);
FDate:=EncodeDate(FYear,FMonth,FDay);
SendToControl;
end;
end;
end;
procedure TfrmDBGridEditDate.FormShow(Sender: TObject);
begin
SetToday(nil);
//Устанавливаем ловушку
Hook:=SetWindowsHookEx(WH_KEYBOARD,KeyboardProc,0,GetCurrentThreadID);
if Hook=0 then
ShowMessage('Ловушка не установлена');
end;
procedure TfrmDBGridEditDate.btnNextMonthClick(Sender: TObject);
begin
SelectedDate:=IncMonth(SelectedDate,1);
Windows.SetFocus(FControlHandle);
end;
procedure TfrmDBGridEditDate.btnPriorMonthClick(Sender: TObject);
begin
SelectedDate:=IncMonth(SelectedDate,-1);
Windows.SetFocus(FControlHandle);
end;
procedure TfrmDBGridEditDate.btnNextYearClick(Sender: TObject);
begin
SelectedDate:=IncYear(SelectedDate,1);
Windows.SetFocus(FControlHandle);
end;
procedure TfrmDBGridEditDate.btnPriorYearClick(Sender: TObject);
begin
SelectedDate:=IncYear(SelectedDate,-1);
Windows.SetFocus(FControlHandle);
end;
procedure TfrmDBGridEditDate.SelectMonth(Sender: TObject);
begin
pmSelectMonth.Popup(Mouse.CursorPos.X,Mouse.CursorPos.Y);
Windows.SetFocus(FControlHandle);
end;
procedure TfrmDBGridEditDate.SetMonth(Sender: TObject);
var
ADay,AMonth,AYear:Word;
begin
DecodeDate(FDate,AYear,AMonth,ADay);
AMonth:=StrToInt(Copy((Sender as TMenuItem).Name,2,2));
SelectedDate:=EncodeDate(AYear,AMonth,ADay);
end;
procedure TfrmDBGridEditDate.SelectYear(Sender: TObject);
begin
pmSelectYear.Popup(Mouse.CursorPos.X,Mouse.CursorPos.Y);
Windows.SetFocus(FControlHandle);
end;
procedure TfrmDBGridEditDate.SetYear(Sender: TObject);
var
ADay,AMonth,AYear:Word;
begin
DecodeDate(FDate,AYear,AMonth,ADay);
AYear:=StrToInt(Copy((Sender as TMenuItem).Name,2,4));
SelectedDate:=EncodeDate(AYear,AMonth,ADay);
end;
constructor TfrmDBGridEditDate.Create(AOwner: TComponent);
begin
inherited;
// HorzScrollBar.Visible:= False; // убираем сколлбары, чтобы не мешались
// VertScrollBar.Visible:= False; // при изменении размеров формы
// RebuildWindowRgn; // строим новый регион
end;
{procedure TfrmGridEditDate.RebuildWindowRgn;
var
FullRgn, Rgn: THandle;
ClientX, ClientY, I: Integer;
begin
// определяем относительные координаты клиентской части
ClientX:= (Width - ClientWidth) div 2;
ClientY:= Height - ClientHeight - ClientX;
FullRgn:= CreateRectRgn(0, 0, Width, Height); // создаем регион для всей формы
// создаем регион для клиентской части формы и вычитаем его из FullRgn
Rgn:= CreateRectRgn(ClientX, ClientY, ClientX + ClientWidth, ClientY +ClientHeight);
CombineRgn(FullRgn, FullRgn, Rgn, rgn_Diff);
// теперь добавляем к FullRgn регионы каждого контрольного элемента
for I:= 0 to ControlCount -1 do
with Controls[I] do begin
Rgn:= CreateRectRgn(ClientX + Left, ClientY + Top, ClientX + Left +Width, ClientY + Top + Height);
CombineRgn(FullRgn, FullRgn, Rgn, rgn_Or);
end;
SetWindowRgn(Handle, FullRgn, True); // устанавливаем новый регион окна
end;
}
procedure TfrmDBGridEditDate.FormClose(Sender: TObject;var Action: TCloseAction);
begin
Action:=caFree;
RestoreEvents;
UnhookWindowsHookEx(Hook);
AForm:=nil;
end;
procedure TfrmDBGridEditDate.SetControl(const Value: TDBGrid);
begin
FControl := Value;
if FControl<>nil then
begin
FControlHandle:=GetTopWindow(FControl.Handle);
if FControlHandle=0 then
Raise Exception.Create('Grid не в режиме редактирования');
if Assigned(FControl.DataSource)and Assigned(FControl.DataSource.DataSet) then begin
//Заменяем события для того,чтобы калькулятор убирался при вводе с клавиатуры
FOnChangeField:=FControl.SelectedField.OnChange;
FControl.SelectedField.OnChange:=OnChangeField;
//Надо установить режим редактирования,чтобы калькулятор закрылся по Esc
if not(FControl.DataSource.DataSet.State in [dsEdit,dsInsert]) then
FControl.DataSource.DataSet.Edit;
FOnStateChange:=FControl.DataSource.OnStateChange;
FControl.DataSource.OnStateChange:=OnStateChange;
end;
end
else Raise Exception.Create('Должна быть ссылка на объект');
end;
procedure TfrmDBGridEditDate.OnChangeField(Sender: TField);
begin
if Assigned(FOnChangeField) then
FOnChangeField(FControl.SelectedField);
Close;
end;
procedure TfrmDBGridEditDate.OnStateChange(Sender: TObject);
begin
if Assigned(FOnStateChange) then
FOnStateChange(FControl.DataSource);
Close;
end;
procedure TfrmDBGridEditDate.RestoreEvents;
begin
with FControl do begin
SelectedField.OnChange:=FOnChangeField;
DataSource.OnStateChange:=FOnStateChange;
end;
end;
procedure TfrmDBGridEditDate.Show;
var
R:TRect;
begin
GetWindowRect(FControlHandle,R);
if (R.Bottom+Height+2<=Screen.Height) then
Top:=R.Bottom+1
else Top:=R.Top-Height-1;
if (R.Left+Width+2<=Screen.Width) then
begin
Left:=R.Left+1;
if (Left<0) then
Left:=1;
end
else Left:=Screen.Width-Width;
inherited Show;
end;
procedure TfrmDBGridEditDate.btnOkClick(Sender: TObject);
begin
Close;
end;
procedure TfrmDBGridEditDate.ChangeTime(Sender: TObject);
function GetMinCount:Integer;
begin
if Sender=btnHoureUp then
Result:=60
else if Sender=btnHoureDown then
Result:=-60
else if Sender=btnMinetsUp then
Result:=1
else if Sender=btnMinetsDown then
Result:=-1
else Raise Exception.Create('TfrmGridEditDate.ChangeTime:Неправильный параметр');
end;
begin
SelectedTime:=IncMinute(SelectedTime,GetMincount);
end;
procedure TfrmDBGridEditDate.SetTime(const Value: TTime);
var
AHoure,AMinets,ASeconds,AMili:Word;
begin
FTime := Value;
DecodeTime(FTime,AHoure,AMinets,ASeconds,AMili);
lHoure.Caption:=Format('%.2d',[AHoure]);
lMinets.Caption:=Format('%.2d',[AMinets]);
SendToControl;
end;
procedure TfrmDBGridEditDate.SendTimeToControl(ATime: TTime);
var
sBuf:string;
I:Integer;
begin
if FWithClock then begin
sBuf:=' '+FormatDateTime('hh:nn',ATime);
for I:=1 to Length(sBuf) do
SendMessage(FControlHandle,WM_CHAR,Ord(sBuf[I]),0);
Windows.SetFocus(FControlHandle);
end;
end;
procedure TfrmDBGridEditDate.SendToControl;
begin
SendDateToControl(FDate);
SendTimeToControl(FTime);
end;
procedure TfrmDBGridEditDate.SetWithClock(const Value: Boolean);
begin
FWithClock := Value;
if FWithClock then
begin
Height:=211;
pClock.Top:=145;
pOk.Top:=185;
end
else begin
Height:=170;
pClock.Top:=172;
pOk.Top:=145;
end;
end;
procedure TfrmDBGridEditDate.StartTimer(Sender: TObject;
Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
with tmrChangeTime do begin
Interval:=500;
Enabled:=True;
Tag:=Integer(Sender);
end;
end;
procedure TfrmDBGridEditDate.StopTimer(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
tmrChangeTime.Enabled:=False;
end;
procedure TfrmDBGridEditDate.ChangeTimeByTimer(Sender: TObject);
begin
tmrChangeTime.Interval:=100;
ChangeTime(TObject(tmrChangeTime.Tag));
end;
end.
Сайт управляется системой
uCoz