[Delphi] ActiveX + TListView
FListView := TListView.Create(MyForm);
Насколько я понимаю, мне надо будет писать ещё одну ActiveX на основе TStringGrid и использовать её. Но это я всегда успею сделать. Хотелось бы без лишних заморочек, потому как уже есть TListView. Помогите, пожалуйста.
А пробовал временно закоментить создание TListView и все что с ним связано?
TabSheet создается подобным образом? С ним есть проблемы?
Control <ListView.Name> has no parent windowМожешь выложить минимальный код, в котором появляется ошибка? (файлы проектов, чтобы можно было посмотреть из дельфи)
TabSheet создается подобным образом? С ним есть проблемы?Всё нормально создаётся, никаких проблем. Даже есть обработчик при прорисовке элементов списка (изменение шрифта, цвета и тп но при клике на списке вылезает ошибка
Можешь выложить минимальный код, в котором появляется ошибка? (файлы проектов, чтобы можно было посмотреть из дельфи)Если создавал ActiveX, то вот процедура инициализации компонента
procedure TNPanelX.InitializeControl;
var
FPageControl: TPageControl;
FTabSheet: TTabSheet;
FWebBrowser: TWebBrowser;
FListView: TListView;
FPanel: TPanel;
FBitBtn: TBitBtn;
begin
FDelphiControl := Control as TPanel;
with FDelphiControl do begin
OnCanResize := CanResizeEvent;
OnClick := ClickEvent;
OnConstrainedResize := ConstrainedResizeEvent;
OnDblClick := DblClickEvent;
OnResize := ResizeEvent;
BevelOuter := TBevelCut(bvNone);
end;
// page control
FPageControl := TPageControl.Create(FDelphiControl);
TWinControl(FPageControl).Name := 'NPageControl';
TWinControl(FPageControl).Parent := FDelphiControl;
FPageControl.Align := alClient;
// first page
FTabSheet := TTabSheet.Create(FPAgeControl);
TWinControl(FTabSheet).Name := 'NTabSheet2';
TWinControl(FTabSheet).Parent := FPageControl;
FTabSheet.PageControl := FPageControl;
FTabSheet.Caption := 'Закладка 1';
FPanel := TPanel.Create(FTabSheet);
TWinControl(FPanel).Name := 'NPanel1';
TWinControl(FPanel).Parent := FTabSheet;
with FPanel do begin
Align := alTop;
Caption := '';
Height := 72;
end;
FBitBtn := TBitBtn.Create(FPanel);
TWinControl(FBitBtn).Name := 'NButton';
TWinControl(FBitBtn).Parent := FPanel;
with FBitBtn do begin
Top := FDatePicker.Top + FDatePicker.Height + 8;
Left := FDatePicker.Left;
Caption := 'Вывести';
Anchors := [akRight, akTop];
OnClick := NButtonClick;
end;
FPanel.InsertControl(FBitBtn);
FListView := TListView.Create(FTabSheet);
TWinControl(FListView).Name := 'NListView1';
TWinControl(FListView).Parent := FTabSheet;
with FListView do begin
Parent := FTabSheet;
ViewStyle := vsReport;
ReadOnly := true;
RowSelect := true;
GridLines := true;
HideSelection := false;
Align := alClient;
end;
// second page
FTabSheet := TTabSheet.Create(FPAgeControl);
TWinControl(FTabSheet).Name := 'NTabSheet1';
TWinControl(FTabSheet).Parent := FPageControl;
FTabSheet.PageControl := FPageControl;
FTabSheet.Caption := 'Закладка 2';
FPageControl.InsertControl(FTabSheet);
FWebBrowser := TWebBrowser.Create(FTabSheet);
TWinControl(FWebBrowser).Name := 'NWebBrowser';
TWinControl(FWebBrowser).Parent := FTabSheet;
FWebBrowser.Align := alClient;
FTabSheet.InsertControl(FWebBrowser);
FDelphiControl.InsertControl(FPageControl);
end;
А если не создавал, то надо будет создать проект ActiveXControl, за основу взять TPanel. Впихнуть этот код в процедуру инициализации. Скомпилировать. Полученный файл <project_name>.ocx зарегистрировать с помощью команды regsvr32 и потом использовать этот ActiveX в любом проекте.
Description
ParentWindow refers to the window handle that underlies the parent control. To designate a non-VCL control as a parent, assign that control’s handle to ParentWindow. This assignment causes the control to be moved into the parent’s screen area. Setting ParentWindow has no effect if Parent is not nil (Delphi) or NULL (C++).
TActiveXControl objects use ParentWindow to insert a control in an ActiveX container window.
ParentWindow is set automatically when a control is constructed with a call to CreateParented (Delphi) or the appropriate overloaded constructor (C++).
Use ParentWindow with windowed controls that are packaged in a DLL. This allows references to the control by applications based on other applications.
У тебя в исходниках:
TWinControl(FListView).Parent := FTabSheet;
При клике на TListView код компоненты пытается передать ему фокус. Не знаю почему, но Delphi в этом коде проверяет, является ли самый верхний Parent VCL-контейнером, если нет - генерит исключение.
controls.pas:
procedure TWinControl.SetFocus;
var
Parent: TCustomForm;
begin
Parent := GetParentForm(Self);
if Parent <> nil then
Parent.FocusControl(Self)
else if ParentWindow <> 0 then
Windows.SetFocus(Handle)
else
ValidParentForm(Self);
end;
function GetParentForm(Control: TControl): TCustomForm;
begin
while Control.Parent <> nil do Control := Control.Parent;
if Control is TCustomForm then
Result := TCustomForm(Control) else
Result := nil;
end;
function ValidParentForm(Control: TControl): TCustomForm;
begin
Result := GetParentForm(Control);
if Result = nil then
raise EInvalidOperation.CreateFmt(SParentRequired, [Control.Name]); //Тут непонятно с какой целью генерится исключение
end;
Исходня из этого, можно решить проблему двумя способами:
1. Перекрыть метод SetFocus класса TListView (а он к счастью виртуальный). Недостатки - этот метод идет вразрез с рекомендациями хелпа, и нет гарантии, что исключение не появится где-нибудь еще.
2. При создании FListView указать
FListView.Parent := nil;
FListView.ParentWindow := FTabSheet.Handle;
Недостатки - в этом методе игнорируются свойства Top, Left, Align и т.д. Приходится для определения местоположения использовать дополнительные невидимые контейнеры.
Громадное спасибо. С меня пивко. Если вдруг где-нить как-нить пересечёмся =)
Оставить комментарий
stm5999302
ПриветствуюЯ пишу свою компоненту ActiveX (TPanel на неё кладу PageControl и в одну из закладок кладу ListView. Так вот, при нажатии любой клавишей мыши на этом списке появляется сообщение "Control <ListView.Name> has no parent window". В чём проблема и как её обойти?
Обработчиков нажатия клавиш нет.
Кусок кода
...
FListView := TListView.Create(FTabSheet);
TWinControl(FListView).Name := 'NListView1';
TWinControl(FListView).Parent := FTabSheet;
with FListView do begin
// ... описание ...
end;
...
Спасибо за внимание