Форум: "Начинающим";
Текущий архив: 2013.03.22;
Скачать: [xml.tar.bz2];
ВнизТребуется разъяснение команды AS Найти похожие ветки
← →
alfa © (2012-09-16 12:25) [0]Не программист, понять описание порой очень сложно. Стояла задача читать содержимое окошек класса DirectUIHWND. Подсказали пример:
function AccessibleChildren(paccContainer : Pointer; iChildStart : LONGINT; cChildren : LONGINT; out rgvarChildren : OleVariant; out pcObtained : LONGINT) : HRESULT; stdcall;
stdcall; external "oleacc.dll";
procedure TForm1.DisplayInfo(const aAccessible : IAccessible; const aOffset : string);
procedure ProcessChild(const aChild : OleVariant);
var
ChildAccessible : IAccessible;
ChildDispatch : IDispatch;
begin
ChildDispatch := nil;
case VarType(aChild) of
varInteger : aAccessible.Get_accChild(aChild, ChildDispatch);
varDispatch : ChildDispatch := aChild;
end;
if (ChildDispatch <> nil) and (ChildDispatch.QueryInterface(IAccessible, ChildAccessible) = S_OK) then
DisplayInfo(ChildAccessible, aOffset + " ")
end;
var
Child, CurrentChild : OleVariant;
ChildArray : array of OleVariant;
dwNum : DWord;
Enum : IEnumVARIANT;
i, iChildCount, iObtained : Integer;
wsText : WideString;
begin
if aAccessible <> nil then begin
if aAccessible.get_AccName(CHILDID_SELF, wsText) = S_OK then
Memo1.Lines.Add(aOffset + "Name: " + wsText)
else
Memo1.Lines.Add(aOffset + "Name: Empty");
if aAccessible.get_AccValue(CHILDID_SELF, wsText) = S_OK then
Memo1.Lines.Add(aOffset + " Value: " + wsText);
if aAccessible.get_AccDescription(CHILDID_SELF, wsText) = S_OK then
Memo1.Lines.Add(aOffset + " Description: " + wsText);
if (aAccessible.Get_accChildCount(iChildCount) = S_OK) and (iChildCount > 0) then begin
Form1.Memo1.Lines.Add(aOffset + " Children: " + IntToStr(iChildCount));
SetLength(ChildArray, iChildCount);
if AccessibleChildren(Pointer(aAccessible), 0, iChildCount, ChildArray[0], iObtained) = S_OK then begin
for i := 0 to iObtained - 1 do
ProcessChild(ChildArray[i])
end else if aAccessible.QueryInterface(IEnumVARIANT, Enum) = S_OK then begin
Enum := aAccessible as IEnumVARIANT;
for i := 0 to iChildCount - 1 do
if Enum.Next(1, Child, dwNum) = S_OK then
ProcessChild(Child);
end else begin
if aAccessible.accNavigate(NAVDIR_FIRSTCHILD, CHILDID_SELF, CurrentChild) = S_OK then begin
repeat
ProcessChild(CurrentChild)
until aAccessible.accNavigate(NAVDIR_NEXT, CurrentChild, CurrentChild) <> S_OK;
end
end
end
end
end;
-------------------------------------------------------------------------------------
var
Accessible : IAccessible;
hWindow : HWnd;
begin
Memo1.Lines.Clear;
hWindow := FindWindowA("CabinetWClass", nil);
if AccessibleObjectFromWindow(hWindow, 0, IID_IAccessible, Accessible) = S_OK then
DisplayInfo(Accessible, "");
-------------------------------------------------------------------------------------
Мы не уверены, видимо "ваш", дельфийский. У нас язык совсем другой, и малознаменитый, с малым количеством талантливых поклонников, у кого можно проконсультироваться. Так вот собственно вопрос: при портировании кода на наш язык, возникла непонятка с использованием вашей хитрющей функцией "AS". Может ли кто подробно рассказать что за операция происходит в делфи в этой части кода:
Enum := aAccessible as IEnumVARIANT;
Судя по описанию приведение одного "формата" в другой. Но вся эта операция делается в дельфи "за кадром" можно ли поподробнее получить консультацию как это происходит в развернутом виде?
И второй вопрос по этому же семплу:
case VarType(aChild) of
varInteger : aAccessible.Get_accChild(aChild, ChildDispatch);
varDispatch : ChildDispatch := aChild;
end;
if (ChildDispatch <> nil) and (ChildDispatch.QueryInterface(IAccessible, ChildAccessible) = S_OK) then
Идет case, название переменной, которую мы исследуем - aChild, и варианты значения. Так вот вопрос - здесь имеется два разных значения?
varInteger : aAccessible.Get_accChild(aChild, ChildDispatch); - первый вариант значения aChild
varDispatch : ChildDispatch := aChild; - второй вариант значения aChild
то есть если одно значение сошлось, то второе не проверяется. или имелось ввиду на любое значение aChild произвести две операции. сначала aAccessible.Get_accChild(aChild, ChildDispatch), а следом ChildDispatch := aChild?
Мы попытались перевести это как:
Select *aChild\vt
Case #VT_INT ; varInteger
*aAccessible\get_accChild(*aChild, @*ChildDispatch)
Case #VT_DISPATCH ; varDispatch
*ChildDispatch = *aChild\pdispVal
EndSelect
Но у меня сомнения. Во первых может там были две операции по каждому значению, а не разделение на две операции, взависимости от входящего значения. А во вторых *aChild\vt вроде как должен иметь всего два значения VT_DISPATCH (9) или VT_I4 (3), VT_INT (22) вроде как в этом описании отсутствует: http://msdn.microsoft.com/en-us/library/windows/desktop/dd318448(v=vs.85).aspx
Простите за сумбур, попытался объяснить своими словами, как сам понимаю происходящее, то есть "не программистким" языком. Структуры, указатели, интерфейсы - темный лес.
← →
Inovet © (2012-09-16 13:05) [1]> [0] alfa © (16.09.12 12:25)
> Мы не уверены, видимо "ваш", дельфийский. У нас язык совсем
> другой, и малознаменитый
> [0] alfa © (16.09.12 12:25)
> попытался объяснить своими словами, как сам понимаю происходящее,
> то есть "не программистким" языком.
Так всё-таки какой ваш язык?
← →
alfa © (2012-09-16 15:22) [2]На котором пишем - PureBasic. Которым пытаемся объяснить что нам надо - "не программисткий", то есть не профессиональный, терминами и понятиями толком не владеем. Потому и интересуемся подробностями как это происходит в дельфи, а потом уже будем дальше обмозговывать как это правильно конвертануть. Сейчас пытаемся так:
Protected Child.VARIANT
Protected dwNum.l
If *aAccessible\QueryInterface(@IID_IEnumVARIANT, @*enum) = #S_OK
*enum = *aAccessible
For i = 0 To count - 1
If *enum\Next(1, @Child, @dwnum) = #S_OK
ProcessChild(*aAccessible, aOffset$, @Child)
EndIf
Next
Endif
есть одна структура, объявляем вторую, пока пустую. а после
вторая = первой, в надежде что данные встанут куда надо. Но видимо не верно.
Поясняю что нужно:
Есть две структуры - одна и вторая. Одна состоит из трех элементов, вторая к примеру из пяти. И вроде как нам надо взять первое значение в первой структруре и помножить на что-то, и это будет первый элемент второй структуры. берем второе значение первой и третье значение первой, складываем - это получается второе значение второй структуры. И так далее. Это грубый пример, как там на самом деле обстоит дело с командой AS я не знаю. Но хотелось бы узнать каким образом она конвертирует один в другой, то есть узнать что делает делфи "за кадром" при применении этой команды.
← →
RWolf © (2012-09-16 16:35) [3]ничего не конвертируется, данные вообще не меняются; as — просто приведение типа объекта/интерфейса к типу его предка или потомка, или взятие интерфейса у объекта.
← →
alfa © (2012-09-16 17:13) [4]А насчет case? Правил синтаксиса дельфи не знаем. Это два разных значения и выполняется только одно при срабатывании, или же там обе команды исполняются друг за другом?
← →
Германн © (2012-09-16 17:43) [5]выполняется только одно
← →
Dimka Maslov © (2012-09-16 19:45) [6]AS это оператор приведения типов. Похож на dynamic_cast в С++, с той разницей, что генерирует исключение, если типы несовместимы. Но для интерфейсов он работает следующим образом:
Enum := aAccessible as IEnumVARIANT это то же самое что
if aAccessible.QueryInterface(IID_IEnumVARIANT, Enum) != S_OK then raise EКакое-тоТамException.Create(SНетуИнтерфейсаБуквальноВообще)
А вообще для понимания что она там делает за кадром - очень хорошая штука пошаговый отладчик с дизассемблером.
← →
Юрий Зотов © (2012-09-16 19:46) [7]Или ни одного.
Насчет AS см. [3], но сначала выполняется проверка. Если приведение невозможно, то генерится исключение.
Страницы: 1 вся ветка
Форум: "Начинающим";
Текущий архив: 2013.03.22;
Скачать: [xml.tar.bz2];
Память: 0.49 MB
Время: 0.058 c