Календарь в дбгриде

Передо мной стояла задача в дбгрид запихать календарь и показывать его тогда когда курсор стоит на поле с типом дата.

Смысл был в том что если юзер нажал кнопку в право и фокус стоит на годе и нажата клавища в право то передать управление в грид .
и в другую сторону - если курсор на дне и клавиша в лево то тоже передать это в грид.

Пришлось усложнить жизнь пользователям (или облегчить) и делать так

Если нажат шифт то не под каким предлогом фокус в грид не возвращать .
Если не нажата клавиша шифт то отдаем фокус гриду.

Вот реализация.

Создадим сначала календарь ....

понадобятся глобальные переменные


Date_edit_base:TDateTimePicker;  
data_chebged:boolean = true;  
Date_edit_base_f_name:string;  
  
  
Date_edit_base:=TDateTimePicker.Create(DBGrid1);  
Date_edit_base.Parent:=DBGrid1;  
Date_edit_base.Left:=0;  
Date_edit_base.Top:=0;  
Date_edit_base.Visible:=false;  
Date_edit_base.ShowCheckbox:=false;  
Date_edit_base.Checked:=true;  
Date_edit_base.OnChange:=set_Date; // изменяем значение в гриде  
Date_edit_base.OnKeyDown:=datta_KeyDown; // обработка нажатий клавиш  
-----------


После смены даты в календаре меняем соответст значение поля


procedure TForm1.set_Date(Sender: TObject);  
begin  
if data_chebged then  
if not(( DataSet.State = dsEdit) or (DataSet.State = dsInsert)) then  
begin  
DataSet.Edit;  
DataSet.FieldByName(Date_edit_base_f_name).AsDateTime:=Date_edit_base.DateTime;  
end;  
data_chebged:=false;  
end;  
-------------------


procedure TForm1.datta_KeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);  
var  
locc:boolean; // локально обрабатывать нажатую клавишу или отдать гриду фокус  
begin  
locc:=false;  
if (VK_RETURN=Key) then locc:=true;  
if (key in [48..57]) then locc:=true;  
if (key in [96..105]) then locc:=true;  
  
if key=109 then key:=189;  
if (key = 189) then locc:=true;  
  
  
if ((ssShift in Shift)  
or (SsAlt in Shift)  
or (SsCtrl in Shift)) then  
begin  
// самостоятельно обработать нажатую славишу  
locc:=true;  
  
end;  
  
  
if not(locc) then  
begin  
  
//Фокус надо передать гриду  
TDateTimePicker(Sender).Visible:=false;  
DBGrid1.SetFocus;  
PostMessage(DBGrid1.Handle,WM_KEYDOWN,Key,0);  
  
Key:=0;  
end;  
  
  
if locc then  
if (key = 13) then  
push_down(Date_edit_base);  
end;  
------------------


Процедура push_down (заставляет выпать календарик ) реализована вот так


procedure push_down(contr:TDateTimePicker );  
var  
msg: tagEVENTMSG;  
begin  
msg.message:= WM_LBUTTONDOWN;  
msg.paramL:=contr.Height div 2;  
msg.paramH:= contr.Width - 5;  
msg.hwnd:=contr.Handle;  
contr.DefaultHandler(msg);  
msg.message:=WM_LBUTTONUP;  
contr.DefaultHandler(msg);  
delay(1);  
  
if contr.DroppedDown then  
begin  
contr.SetFocus;  
msg.message:= WM_LBUTTONDOWN;  
msg.paramL:= 5;  
msg.paramH:= 5;  
msg.hwnd:=contr.Handle;  
contr.DefaultHandler(msg);  
msg.message:=WM_LBUTTONUP;  
contr.DefaultHandler(msg);  
contr.SetFocus;  
end;  
end;  
----------------------------------


Также потребуется собственоо нарисовать (0тбразить = переместить ) календарик в грде
Для этого у грида есть всем извесное и любимое событие


procedure TForm1.DBGrid1DrawColumnCell(Sender: TObject; const Rect: TRect;  
DataCol: Integer; Column: TColumn; State: TGridDrawState);  
begin  
if (gdFocused in State) then  
if(( AnsiUpperCase(Column.FieldName) = AnsiUpperCase('Din') )  
// тут я перечислил все свои поля типа даты  
  
or ( AnsiUpperCase(Column.FieldName) = AnsiUpperCase('UPD_DATE') ))  
  
then  
if not(Column.Field.DataSet.FieldByName(Column.FieldName).AsDateTime=0) then  
begin  
  
Date_edit_base_f_name:=Column.FieldName; // задали в глоб перем имя столбца  
Date_edit_base.Left := Rect.Left ; // левая точка календаря в координ грида  
Date_edit_base.Top := Rect.Top ; // верхняя точка  
Date_edit_base.Width := Rect.Right - Rect.Left + 2; // длина :)  
Date_edit_base.Visible := True;  
data_chebged:=true; // флажок что мол данные сменидися  
  
Date_edit_base.DateTime:= Column.Field.DataSet.FieldByName(Column.FieldName).AsDateTime;  
// записали в календарь нужное время  
Date_edit_base.SetFocus; // отдали фокус календ  
// push_down(Date_edit_base); // по желанию можно заставить его сразу и выпасть  
  
end  
else  
begin  
  
DBGrid1.Canvas.TextOut(Rect.Left+1,Rect.Top+1,'Нет данных!');  
// Дата не проставлена  
end;  
end;  
-------------------


также по мере отладки выяснилося что надо такой финт дописать
(поймете по чему если будете делать)


procedure TForm1.DBGrid1KeyDown(Sender: TObject; var Key: Word;  
Shift: TShiftState);  
begin  
IF Date_edit_base.DroppedDown THEN  
PostMessage(DBGrid1.Handle,WM_KEYDOWN,VK_ESCAPE,0);  
end;  
  
  
procedure TForm1.DBGrid1ColExit(Sender: TObject);  
begin  
Date_edit_base.Visible := False;  
end;  
----------------


Спрашивается для чего все это нужно = смотрите скрин шот
Теги:
Календарь, дбгрид
Добавлено: 27 Июля 2018 22:46:43 Добавил: Андрей Ковальчук Нравится 0
Добавить
Комментарии:
Нету комментариев для вывода...