为什么访问通过FindControl找到的TValueListEditor时会出现访问冲突?

问题描述

| 我已经在
TForm
上动态创建了
TValueListEditor
VCL组件。该代码位于主窗体方法之一的嵌套过程中。我已经设定:
ValueListEditor.KeyOptions := [keyEdit,keyAdd,keyUnique];
看起来像这样:
TMainForm.Method();
Method
一个嵌套过程,其中包含创建上述组件的代码。 然后,我有助手功能
function GetMenuListData(XMLNode: TXMLNode; const XNMLDoc: string = \'\') : string;
在此帮助器中,我使用以下代码加载XML文件,然后检索其节点并将其插入到“ 6”中。
XMLDoc := TXMLDocument.Create(Self);
XMLDoc.ParSEOptions := [poPreserveWhiteSpace];
try
  XMLDoc.LoadFromFile(XNMLDoc);
  try
    Control := FindControl(FindWindow(\'TForm\',PChar(\'(\' + ExtractFileExt(Form1.Edit1.Text) + \')\')));
    if Control <> nil then
    begin
      TValuelistEditor(Control).Keys[TValuelistEditor(Control).RowCount-1] := XMLDoc.DocumentElement.NodeName;
      if XMLDoc.DocumentElement.ChildNodes.First.AttributeNodes.Count > 0 then
        TValuelistEditor(Control).Values[TValuelistEditor(Control).Keys[TValuelistEditor(Control).RowCount-1]] := String(XMLDoc.DocumentElement.Attributes[\'id\'])
      else
        TValuelistEditor(Control).Values[TValuelistEditor(Control).Keys[TValuelistEditor(Control).RowCount-1]] := \'<Empty>\';
    end else begin
      MessageBeep(0);
      FlashWindow(Application.Handle,True);
      ShowMessagePos(\'...\');
    end;
  finally
    XMLDoc.Active := False; Result := \'Forced \' + Form1.RAWInputBtn.Caption + \' in \' + DateTimetoStr(Now);
  end;
except
  on E : EXMLDocError do
  begin
    Result := \'Forced \' + Form1.RAWInputBtn.Caption + \' in \' + DateTimetoStr(Now);
  end;
end;
问题是每次代码进入该行时都会出现访问冲突:
TValuelistEditor(Control).Keys[TValuelistEditor(Control).RowCount-1] := XMLDoc.DocumentElement.NodeName;
我尝试了各种类型转换,值,参数..没有任何窍门。 我怎么了 我正在使用Delphi XE。     

解决方法

        正如Ken所评论的那样,您的问题是,您没有找到值列表编辑器,而是找到了表单,然后将其类型转换为值列表编辑器,即AV。 首先,您要将\'TForm \'作为\'lpClassName \'传递给
FindWindow
。假设\ TForm \是表单的类名,它当然会找到该表单-而不是子窗口。其次,您不能使用ѭ9来查找子窗口,请参阅其文档,它会搜索顶级窗口。 如果您已经测试了
FindControl
的返回值,则提高AV的代码将永远不会运行:
  if (Control <> nil) and (Control is TValueListEditor) then
您可以使用
FindWindowEx
在子窗口中进行搜索,如果您不知道表单的句柄,请先查找它,因为您已经做完了:
FormHandle := FindWindow(\'TForm\',PChar(\'(\' + ExtractFileExt(Form1.Edit1.Text) + \')\'));
if FormHandle <> 0 then
begin
  Control := FindControl(FindWindowEx(FormHandle,\'TValueListEditor\',nil));
或者更好的方法是,先测试
FindWindowEx
的返回值,以避免将\'0 \'传递给
FindControl
ValueListEditorHandle := FindWindowEx(FormHandle,nil);
if Win32Check(ValueListEditorHandle <> 0) then
begin
  Control := FindControl(ValueListEditorHandle);
  if Assigned(Control) then
  begin
    ...
    ,        如果您动态创建的表单是同一应用程序的一部分,则不需要不正确的ѭ18的所有杂音。只需创建您的表单,为其命名,然后使所有者成为
Application
MyForm := TMyForm.Create(Application);
MyForm.Name := \'MyDynamicForm\';
当您想获得新的参考时:
var
  TheForm: TMyForm;
  i: Integer;
begin
  TheForm := nil;
  for i := 0 to Screen.FormCount - 1 do
    if Screen.Forms[i] is TMyForm then
      // Could also use Screen.Forms[i].Caption
      if Screen.Forms[i].Name = \'MyDynamicForm\' then
        TheForm := TMyForm(Screen.Forms[i]);

  if Assigned(TheForm) then
    TheForm.MethodThatLoadsXML(XMLFileName); // or whatever
end;
22ѭ现在可以直接访问
TValueListEditor
procedure TMyForm.MethodThatLoadsXML(const XMLFileName: string);
begin
  // Load xml as before,using XMLFileName
  with TValueListEditor.Create(Self) do
  begin
    Options := [Whatever];
    Parent := Self;
    Left := SomeNumber;
    Top := SomeNumber;
    // Create items for value list from XML and other stuff
  end;
end;