Конференция "Corba" » TWebBrowser -> OleObject - проверить является ли элемент NULL [Delphi, Windows]
 
  • Edgar_Wine (24.09.12 08:43) [0]
    Здравствуйте. Подскажите как проверить, делаю так вот:

    Var Element: OleVariant;
    .....
    Element:=WebBrowser1.OleObject.document.all.tags('div').namedItem('my_id');
    // работа с Element
    .....



    Когда в странице есть хотя бы один тег [div] у которого id="my_id" или name="my_id" - то всё работает как нужно.
    Но если таковых нет - функция вылетает в небеса. =(

    Руководствуясь этим: http://msdn.microsoft.com/en-us/library/ms536634(v=vs.85).aspx
    метод namedItem() должен: либо вернуть первый из подходящих элементов, либо вернуть NULL.

    Пытался проверить на NULL этими функциями: VarIsEmpty(), VarIsNull() - без результатов. =(
  • sniknik © (24.09.12 13:50) [1]
    > Пытался проверить на NULL этими функциями: VarIsEmpty(), VarIsNull() - без результатов. =(
    значит не то проверял. VarIsNull при том что возвращается именно он, то что надо...
  • sniknik © (24.09.12 13:51) [2]
    > метод namedItem() должен:
    a tags('div') не должен?
  • Edgar_Wine (24.09.12 14:34) [3]
    оой.. Куда-то я кажется в не тот раздел вообще написал.. 2 суток без сна.. Тока теперь подремав понял, простите.. =((

    ну... В том конкретном случае у меня там были ещё div, так что вылетало точно не там. хмм. Надо проверить что будет если вообще нет div, спасибо. =)

    Msg:='|';
    Element:=WebBrowser1.OleObject.document.all.tags('DIV').namedItem('test');
    if VarIsNull(Element) then Msg:=Msg+'true|' else Msg:=Msg+'false|';
    if VarIsEmpty(Element) then Msg:=Msg+'true|' else Msg:=Msg+'false|';
    if VarIsError(Element) then Msg:=Msg+'true|' else Msg:=Msg+'false|';
    ShowMessage(Msg); // Все 3 пишут "false" (в обоих случаях), а если попытаться что-то делать дальше с Element - вылетает в трубу. =(
    ShowMessage(Element.InnerText); // Например вот это: AV at 0045DE47 ... Read of address 00000000



    Может в Делфи заголовочник как-то не так что-то? А что тогда делать? =(
  • sniknik © (24.09.12 16:21) [4]
    // Все 3 пишут "false" (в обоих случаях), а если попытаться что-то делать дальше с Element - вылетает в трубу. =(
    а та проверь что пишут после каждого... кашу маслом можно испортить.

    // ... Например вот это: AV at 0045DE47 ... Read of address 00000000
    + VarToStr

    > Может в Делфи заголовочник как-то не так что-то?
    начинаешь задаваться такими вопросами, значит нужен ответ на другой "а программирование это мое? не пойти ли в дворники...".
    глюки у тебя! в 99,98% случаев, точка. по другому не думай.
  • Edgar_Wine (24.09.12 17:08) [5]
    Ну отчего же? Просто заголовочники у моей D7 древние, много раз приходилось что-то вручную объявлять, некоторое объявлено не так как в оригинальном MSDN, например GradientFill() в D7 слегка через одно место... Ну это другая история уже. =))

    Не очень понял что сделать после чего. VarToStr() в первом случае говорит [object], а во втором вылетает на ней с "EVariantTypeCastError -> Could not convert variant of type (Dispatch) into type (String)".

    Брутфорс спасёт Мир! © =))
    Перепробовал всё что начинается с VarIs - кажется мне нужно проверять по VarIsClear() - во всяком случае тока оно дало "true" на втором случае.
  • sniknik © (24.09.12 17:19) [6]
    > "EVariantTypeCastError -> Could not convert variant of type (Dispatch) into type (String)".
    означает что
    > метод namedItem() должен: либо вернуть первый из подходящих элементов, либо вернуть NULL.
    не правда... иначе хватило бы VarIsNull.
  • Edgar_Wine (24.09.12 20:24) [7]
    А я тут причём? =)
    Это в MSDN так написано, я же давал ссыль: «Returns an object or a collection of objects if successful, or null otherwise.»

    Ну ладно, сейчас ещё поподробнее потестю, с пристрастием... >:3
    Но конструктивные идеи или ссылки приветствуются! =)
  • sniknik © (25.09.12 00:44) [8]
    > я же давал ссыль:
    а я говорил
    > значит не то проверял.

    > Но конструктивные идеи или ссылки приветствуются! =)
    ошибка в программе. это самая что ни на есть конструктивная правда жизни. на 99.98%.
  • sniknik © (25.09.12 08:03) [9]
    хм. все методы namedItem любых объектов в MSHTML_TLB возвращают интерфейс. в описанном случае не найдености это нулевой интерфейс, а не null. почему в мсдн написано null... не знаю, может справка не та, для net, или с++ где либо авто приведение типа либо игнорирование, в дельфи есть разница.

    сорри, ошибался, дело не в твоей программе. 0,02% тоже бывают.
  • Плохиш © (26.09.12 00:06) [10]

    > Edgar_Wine   (24.09.12 14:34) [3]

    null в Delphi называется nil.
  • sniknik © (26.09.12 07:45) [11]
    > null в Delphi называется nil.
    > "EVariantTypeCastError -> Could not convert variant of type (Dispatch) into type (String)".
  • cobalt © (28.09.12 14:31) [12]

    >
    Msg:='|';
    > Element:=WebBrowser1.OleObject.document.all.tags('DIV').
    > namedItem('test');
    > if VarIsNull(Element) then Msg:=Msg+'true|' else Msg:=Msg+'false|';
    >
    > if VarIsEmpty(Element) then Msg:=Msg+'true|' else Msg:=Msg+'false|';
    >
    > if VarIsError(Element) then Msg:=Msg+'true|' else Msg:=Msg+'false|';
    >
    > ShowMessage(Msg); // Все 3 пишут "false" (в обоих случаях),
    >  а если попытаться что-то делать дальше с Element - вылетает
    > в трубу. =(
    > ShowMessage(Element.InnerText); // Например вот это: AV
    > at 0045DE47 ... Read of address 00000000


    >
    > Может в Делфи заголовочник как-то не так что-то? А что тогда
    > делать? =(

    А что показывает отладчик на Element?

    ЗЫ. У коллекции есть InnerText?
  • Edgar_Wine (29.09.12 02:17) [13]
    namedItem() возвращает не коллекцию, а один элемент. Вроде как. =)
    У коллекции нету innerText. А нужно ли? =)))

    Показывает $00000000, а толку?

    хм... VarIsNull() даёт false даже когда переменная вообще не инициализирована. Ну то есть не использовалась ни разу, тока в var написана - видимо компилятор или-кто-там расстарались. =)
    Зато VarIsClear() даёт true и когда не инициализирована и когда не найдено ничего в namedItem(). :3
  • sniknik © (29.09.12 11:54) [14]
    > Зато VarIsClear() даёт true
    там проверяется как раз на пустой интерфейс.

    varEmpty    = $0000; { vt_empty        0 }
    varNull     = $0001; { vt_null         1 }

    function VarIsNull(const V: Variant): Boolean;
    begin
     Result := FindVarData(V)^.VType = varNull;
    end;

    function VarIsClear(const V: Variant): Boolean;
    var
     LHandler: TCustomVariantType;
     LVarData: TVarData;
    begin
     LVarData := FindVarData(V)^;
     with LVarData do
       if VType < CFirstUserType then
         Result := (VType = varEmpty) or
                   (((VType = varDispatch) or (VType = varUnknown)) and
                     (VDispatch = nil))
       else if FindCustomVariantType(VType, LHandler) then
         Result := LHandler.IsClear(LVarData)
       else
         Result := False;
    end;

  • Плохиш © (29.09.12 16:01) [15]

    > Показывает $00000000, а толку?

    Это и есть nil. А "толк" программист знать должен.
  • Edgar_Wine (30.09.12 02:09) [16]
    Говорю же - VarIsNull() даёт false.

    >> null в Delphi называется nil.
    >> Это и есть nil.

    Я знаю! Только попробуйте сделайте проверку на него в if чтоб оно работало. У меня не вышло. =(
    Видимо компилятор как-то особо обрабатывает тип OleVariant.
  • Плохиш © (30.09.12 04:37) [17]
    If <какаятофигня> <> nil then делаем чë-то с <какаятофигня>
  • Edgar_Wine (30.09.12 05:17) [18]
    Именно так я прежде всего и пробовал:

    >> [Error] Incompatible types
  • Плохиш © (30.09.12 11:33) [19]

    > Edgar_Wine   (30.09.12 05:17) [18]
    > Именно так я прежде всего и пробовал:
    >
    > >> [Error] Incompatible types
    >
    >

    nil соместим с любым ссылочным типом. Есть подозрение, что пора искать программиста.
  • Edgar_Wine (01.10.12 05:56) [20]
    А вы пробовали? Ну и что же здесь неправильно?:

    procedure TForm1.Button8Click(Sender: TObject);
    var Element: OleVariant;
    begin
    if Element<>nil then ShowMessage('OK');
    end;




    >> [Error] Incompatible types
  • sniknik © (01.10.12 09:43) [21]
    > nil соместим с любым ссылочным типом.
    вариант не ссылка, он структура 16 байт длинной, а ссылка только 4 байта (в 32 разрядной оси).

    +
    nil <> null
    см.прям тут
    sniknik ©   (29.09.12 11:54) [14]
    varEmpty    = $0000; { vt_empty        0 }
    varNull     = $0001; { vt_null         1 }


    будет портить последовательность.
  • sniknik © (01.10.12 10:12) [22]
    для наглядности, не значение, а структура (иногда включает и значение)
    procedure TForm1.Button1Click(Sender: TObject);
    var
     v, iv, id: Variant;
     i: IUnknown;
     d: IDispatch;

     function VarStrucToStr(v: Variant): string;
     begin
       result:= StringOfChar('@', 32);
       BinToHex(@v, @result[1], 16);
     end;

    begin
     iv:= i;
     id:= d;
     ShowMessage('Empty - '+VarStrucToStr(v)+' Null - '+VarStrucToStr(Null)+' IUnknown - '+VarStrucToStr(iv)+' IDispatch - '+VarStrucToStr(id)+#13#10+
                 'Byte - '+VarStrucToStr(5)+' ShortInt - '+VarStrucToStr(-5)+' ...');
    end;

  • Edgar_Wine (01.10.12 21:40) [23]
    Спасибо! =)
    В общем через VarIsClear() работает как часы.
  • sniknik © (01.10.12 22:02) [24]
    непонятно только почему
    > Пытался проверить на NULL этими функциями: VarIsEmpty(), VarIsNull() - без результатов. =(
    "без результатов". т.к.
    > Показывает $00000000, а толку?
    это оно и есть. а VarIsClear просто "более расширенная" вариация проверки нулевого значения для дополнительных типов... диспатч например, судя по
    > "EVariantTypeCastError -> Could not convert variant of type (Dispatch) into type (String)".
    должно быть оно... т.е типа $09000000
  • sniknik © (01.10.12 22:09) [25]
    а... отладчик показывает "чисто значение", если не взять по дампу памяти.
  • Edgar_Wine (02.10.12 01:49) [26]
    Ваш пример показал что id == $09000000000000000000000000000000
    А отладчик показывает id == $00000000 - он видимо откуда-то из "середины" кусок показывает. Может надо настроить где-то чтоб целиком показывал 16 байт?
  • Edgar_Wine (02.10.12 02:19) [27]
    Для моей поделки на TWebBrowser в принципе хватило условия на VarIsClear(Element), а есть ли смысл подобного (в общем случае)?:

    if (VarIsClear(Element) or VarIsEmpty(Element) or VarIsNull(Element)) then
         ShowMessage('Error with "Element" #0011001')
    else
         ShowMessage(Element.innerText);
  • sniknik © (02.10.12 07:49) [28]
    > а есть ли смысл подобного (в общем случае)?:
    в общем это вред без смысла, т.к. твое сообщение вообще не информативно, в отличие от ошибки полученной от обращения без проверки...

    вон там смори
    sniknik ©   (29.09.12 11:54) [14]
    в VarIsClear есть
    Result := (VType = varEmpty) or
    то же что в VarIsEmpty, т.е дополнительная его проверка бессмысленна. это в частном.
  • Edgar_Wine (03.10.12 16:09) [29]
    Сообщение? Про "#0011001" чтоль? Так это я просто, для примеру, обработка отсутствия так сказать. =)
    А с VarIsEmpty это да, оплошал.. Будет думать ещё, спасибо вам огромное!
 
Конференция "Corba" » TWebBrowser -> OleObject - проверить является ли элемент NULL [Delphi, Windows]
Есть новые Нет новых   [134427   +35][b:0][p:0.003]