#delphi
#delphi
Вопрос:
К какому классу TDBGridEh
принадлежит? Я пытался:
if (AForm.Components[i] IS TDBGridEh)
if (AForm.Components[i] IS TCustomDBGrid) or
if (AForm.Components[i] IS TCustomGrid) or
if (AForm.Components[i] IS TDBGrid) or
но я получаю сообщение об ошибке: необъявленный идентификатор ‘***’
Обновить:
Это мой общий обработчик для подэлементов TMainMenu
и столбцов TDBGrid
. Я должен добавить в этот общий обработчик некоторый код для TDBGridEh
.
Есть ли способ иметь одну процедуру для подэлементов TDBGrid
, TDBGridEh
, и TMainMenu
?
procedure RightsOnSubElements(AForm: TForm; AComp: TComponent);
function FindFieldColumn(AComp: TComponent; const FieldName: String): TColumn;
var
i: Integer;
begin
Result := nil;
for i := 0 to (AComp as TDBGrid).Columns.Count - 1 do
if AnsiCompareText((AComp as TDBGrid).Columns[i].FieldName, FieldName) = 0 then
begin
Result := (AComp as TDBGrid).Columns[i];
Break;
end;
end;
var
Column : TColumn;
i: Integer;
begin
fMain.qSubElements.Close;
fMain.qSubElements.Parambyname('Form_Name').AsString := AForm.Name;
fMain.qSubElements.Parambyname('ROLE_ID').AsInteger := ROLE_ID;
fMain.qSubElements.Parambyname('name').AsString := AComp.Name;
fMain.qSubElements.Open;
if fMain.qSubElements.RecordCount > 0 then begin
while not fMain.qSubElements.Eof do begin
for i := 0 to AForm.ComponentCount - 1 do
if (AForm.Components[i] is TMenuItem) then begin
if UpperCase(AForm.Components[i].Name) = UpperCase(fMain.qSubElements.FieldByName('Sub_Name').AsString) then
begin
(AForm.Components[i] as TMenuItem).Visible := fmain.qSubElements.FieldByName('Visible').AsBoolean;
(AForm.Components[i] as TMenuItem).Enabled := fmain.qSubElements.FieldByName('Enabled').AsBoolean;
end;
end
else if (AForm.Components[i] is TDBGrid) then begin
if UpperCase(AForm.Components[i].Name) = UpperCase(fMain.qSubElements.FieldByName('Name').AsString) then
begin
Column := FindFieldColumn(AComp as TDBGrid, fMain.qSubElements.FieldByName('sub_name').AsString);
if Assigned(Column) then Column.Visible := fMain.qSubElements.FieldByName('Visible').AsBoolean;
end;
end;
fMain.qSubElements.Next;
end;
end;
end;
Комментарии:
1. Вы знаете, что можете использовать метод ClassParent для поиска родительского класса каждого существующего класса в вашем приложении. Поместите это в цикл, и вы можете получить целое иерархическое дерево.
Ответ №1:
Согласно документации EhLib:Что является родительским классом компонента DBGridEh?
TDBGridEh
происходит изTCustomDBGridEh
,- который является производным от
TCustomDBAxisGridEh
, - который является производным от
TCustomGridEh
, - который является производным от
TCustomControl
Таким образом, при AForm.Components[i]
обращении к TDBGridEh
объекту он будет положительным для TDBGridEh
, но будет отрицательным для TCustomDBGrid
, TCustomGrid
, и TDBGrid
.
Вы уже знаете, как отличать TMainMenu
от TDBGrid
, так что же мешает вам отличать TDBGridEh
от TDBGrid
?
procedure RightsOnSubElements(AForm: TForm; AComp: TComponent);
function FindFieldColumn(AComp: TDBGrid; const FieldName: String): TColumn;
var
i: Integer;
begin
for i := 0 to AComp.Columns.Count - 1 do begin
Result := AComp.Columns[i];
if SameText(Reslut.FieldName, FieldName) then
Exit;
end;
Result := nil;
end;
function FindFieldColumnEh(AComp: TDBGridEh; const FieldName: String): TColumnEh;
var
i: Integer;
begin
for i := 0 to AComp.Columns.Count - 1 do begin
Result := AComp.Columns[i];
if SameText(Result.FieldName, FieldName) then
Exit;
end;
Result := nil;
end;
var
Comp: TComponent;
Column : TColumn;
ColumnEh : TColumnEh;
i: Integer;
begin
fMain.qSubElements.Close;
fMain.qSubElements.Parambyname('Form_Name').AsString := AForm.Name;
fMain.qSubElements.Parambyname('ROLE_ID').AsInteger := ROLE_ID;
fMain.qSubElements.Parambyname('name').AsString := AComp.Name;
fMain.qSubElements.Open;
while not fMain.qSubElements.Eof do begin
Comp := AForm.FindComponent(fMain.qSubElements.FieldByName('Name').AsString);
if (Comp is TMenuItem) then begin
with TMenuItem(Comp) do begin
Visible := fmain.qSubElements.FieldByName('Visible').AsBoolean;
Enabled := fmain.qSubElements.FieldByName('Enabled').AsBoolean;
end;
end
else if (Comp is TDBGrid) then begin
Column := FindFieldColumn(TDBGrid(Comp), fMain.qSubElements.FieldByName('Sub_Name').AsString);
if Column <> nil then Column.Visible := fMain.qSubElements.FieldByName('Visible').AsBoolean;
end
else if (Comp is TDBGridEh) then begin
ColumnEh := FindFieldColumnEh(TDBGridEh(Comp), fMain.qSubElements.FieldByName('Sub_Name').AsString);
if Column <> nil then Column.Visible := fMain.qSubElements.FieldByName('Visible').AsBoolean;
end;
fMain.qSubElements.Next;
end;
end;
При этом, поскольку TDBGridEh
имеет аналогичные интерфейсы, но фактически не является производным от, TDBGrid
, то в Delphi 2009 вы могли бы написать общий код для обоих TDBGrid
и TDBGridEh
с помощью дженериков, например:
type
TInternalDBGridHelper<TDBGridType: class, TColumnType: class> = class
class function FindFieldColumn(AGrid: TDBGridType; const AFieldName: string): TColumnType;
class procedure SetFieldColumnVisible(AGrid: TDBGridType; const AFieldName: string; AVisible: Boolean);
end;
TInternalHelper_DBGrid = TInternalDBGridHelper<TDBGrid, TColumn>;
TInternalHelper_DBGridEh = TInternalDBGridHelper<TDBGridEh, TColumnEh>;
TDBGridHelper = class helper for TDBGrid
procedure SetFieldColumnVisible(const AFieldName: string; AVisible: Boolean);
end;
TDBGridEhHelper = class helper for TDBGridEh
procedure SetFieldColumnVisible(const AFieldName: string; AVisible: Boolean);
end;
class function TInternalDBGridHelper<TDBGridType, TColumnType>.FindFieldColumn(
AGrid: TDBGridType; const AFieldName: string): TColumnType;
var
I: Integer;
begin
for I := 0 to AGrid.Columns.Count-1 do
begin
Result := AGrid.Columns[I];
if SameText(Result.FieldName, AFieldName) then
Exit;
end;
Result := nil;
end;
class function TInternalDBGridHelper<TDBGridType, TColumnType>.SetFieldColumnVisible(
AGrid: TDBGridType; const AFieldName: string; AVisible: Boolean);
var
Column: TColumnType;
begin
Column := FindFieldColumn(AGrid, AFieldName);
if Assigned(Column) then Column.Visible := AVisible;
end;
procedure TDBGridHelper.SetFieldColumnVisible(const AFieldName: string; AVisible: Boolean);
begin
TInternalHelper_DBGrid.SetFieldColumnVisible(Self, AFieldName, AVisible);
end;
procedure TDBGridEhHelper.SetFieldColumnVisible(const AFieldName: string; AVisible: Boolean);
begin
TInternalHelper_DBGridEh.SetFieldColumnVisible(Self, AFieldName, AVisible);
end;
procedure RightsOnSubElements(AForm: TForm; AComp: TComponent);
var
Comp: TComponent;
i: Integer;
begin
fMain.qSubElements.Close;
fMain.qSubElements.Parambyname('Form_Name').AsString := AForm.Name;
fMain.qSubElements.Parambyname('ROLE_ID').AsInteger := ROLE_ID;
fMain.qSubElements.Parambyname('name').AsString := AComp.Name;
fMain.qSubElements.Open;
while not fMain.qSubElements.Eof do begin
Comp := AForm.FindComponent(fMain.qSubElements.FieldByName('Name').AsString);
if (Comp is TMenuItem) then begin
with TMenuItem(Comp) do begin
Visible := fmain.qSubElements.FieldByName('Visible').AsBoolean;
Enabled := fmain.qSubElements.FieldByName('Enabled').AsBoolean;
end;
end
else if (Comp is TDBGrid) then begin
TDBGrid(Comp).SetFieldColumnVisible(
fMain.qSubElements.FieldByName('Sub_Name').AsString,
fMain.qSubElements.FieldByName('Visible').AsBoolean);
end
else if (Comp is TDBGridEh) then begin
TDBGridEh(Comp).SetFieldColumnVisible(
fMain.qSubElements.FieldByName('Sub_Name').AsString,
fMain.qSubElements.FieldByName('Visible').AsBoolean);
end;
fMain.qSubElements.Next;
end;
end;
Комментарии:
1. Реми Лебо, как я вижу, нет способа создать одну общую процедуру для настройки видимости столбцов DBGrid, столбцов DBGridEh и элементов MainMenu. Спасибо за ваш пример кода.
2. Реми Лебо, как ты называешь свою процедуру? Например, я вызываю свою процедуру так: RightsOnSubElements(self, MainMenu1) или RightsOnSubElements(self, dbgrid1) а вы? p.s. Я добавляю полную процедуру выше. Спасибо.
3. » Как я вижу, нет способа иметь одну общую процедуру для » — не тогда, когда у них разные типы, нет. Но, если у них общие имена, вы всегда можете прибегнуть к RTTI. Конечно, вместо этого вы можете использовать другие идиомы дизайна (полиморфные оболочки и т. Д.). » как вы называете свою процедуру? » — Я не понимаю, о чем вы спрашиваете. В примере, который я опубликовал, показано, как они вызываются. Что мешает вам применить мой пример кода к вашей ситуации? Я обновил свой ответ, чтобы показать это.
4. Реми Лебо Я попробую завтра и сообщу о результате. большое вам спасибо за ваши попытки.
5. Реми Лебо, отображаются ошибки компиляции: ‘необъявленный идентификатор TColumnType’, ‘TColumnType не является идентификатором типа’, ‘Необъявленный идентификатор: ‘TInternalDBGridHelper’. 🙁