![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Требуется разъяснение команды AS
alfa © (2012-09-16 12:25:00)Не программист, понять описание порой очень сложно. Стояла задача читать содержимое окошек класса 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
Простите за сумбур, попытался объяснить своими словами, как сам понимаю происходящее, то есть "не программистким" языком. Структуры, указатели, интерфейсы - темный лес.
Юрий Зотов (2012-09-16 19:46:00) [1]Или ни одного.
Насчет AS см. [3], но сначала выполняется проверка. Если приведение невозможно, то генерится исключение.
Dimka Maslov (2012-09-16 19:45:00) [2]AS это оператор приведения типов. Похож на dynamic_cast в С++, с той разницей, что генерирует исключение, если типы несовместимы. Но для интерфейсов он работает следующим образом:
Enum := aAccessible as IEnumVARIANT это то же самое что
if aAccessible.QueryInterface(IID_IEnumVARIANT, Enum) != S_OK then raise EКакое-тоТамException.Create(SНетуИнтерфейсаБуквальноВообще)
А вообще для понимания что она там делает за кадром - очень хорошая штука пошаговый отладчик с дизассемблером.
Германн (2012-09-16 17:43:00) [3]выполняется только одно
alfa (2012-09-16 17:13:00) [4]А насчет case? Правил синтаксиса дельфи не знаем. Это два разных значения и выполняется только одно при срабатывании, или же там обе команды исполняются друг за другом?
RWolf (2012-09-16 16:35:00) [5]ничего не конвертируется, данные вообще не меняются; as — просто приведение типа объекта/интерфейса к типу его предка или потомка, или взятие интерфейса у объекта.
alfa (2012-09-16 15:22:00) [6]На котором пишем - 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 я не знаю. Но хотелось бы узнать каким образом она конвертирует один в другой, то есть узнать что делает делфи "за кадром" при применении этой команды.
Inovet (2012-09-16 13:05:00) [7]> [0] alfa © (16.09.12 12:25)
> Мы не уверены, видимо "ваш", дельфийский. У нас язык совсем
> другой, и малознаменитый
> [0] alfa © (16.09.12 12:25)
> попытался объяснить своими словами, как сам понимаю происходящее,
> то есть "не программистким" языком.
Так всё-таки какой ваш язык?