Показать полную графическую версию : *Флейм* | Delphi. Синтаксис. Использование WinAPI
DillerInc
07-02-2005, 18:52
Savant
Спасибо,попробую это теперь осмыслить и как-нибудь применить :) .
...код переварил,и то,что вышло,прикрепил в файле :) .
Вроде работает,но всё равно так и не смог придумать нормальную схему условных операторов в обработчике события OnCloseQuery,поэтому пришлось идти немного обходным путём.
Дело в том,что мне необходимо в этом обработчике проверить не только наличие изменений в открытом документе,но и то,сохранил ли пользователь уже этот документ или нет.И с последним пунктом у меня как раз и возникает загвоздка.
DillerInc
01-03-2005, 23:44
В общем,как можно догадаться - у меня снова вопросы...
...а именно,необходимо получить ссылку на какое-нибудь окно - то бишь т.н. Handle Window (HWND).И не просто получить,а вывести её как-то в виде символов,к примеру,в компоненте TLabel(метка).
Значит в чём заключается вопрос...имеется функция WinAPI :
function FindWindow(lpClassName, lpWindowName : PChar) : HWND;
...возвращающая "хэндл" искомого окна.А вот как теперь этому значению придать наглядный вид,чтобы отобразить символьно это значение в той же метке?
Возможно ли такое вообще,если да,то как?С помощью каких функций?
DillerInc
Сначала теория: хэндл окна представляет собой просто двойное слово, т.е. 32-битное число. Число можно представить в символьной форме функцией Int2Str. А например с помощью GetWindowText() можно получить заголовок окна. Функций работы с окнами очень много, конкретизируйте цель пожалуйста...
DillerInc
02-03-2005, 20:08
Savant
Цель - использование этого самого хэндла,32-битного числа,в другой программе,т.е. мне необходимо прописать в другой программе это значение как один из параметров для выполнения определённой команды.Именно поэтому мне необходимо получить символьное представление значения типа HWND.
Число можно представить в символьной форме функцией Int2Str
...т.е. если я правильно понял,можно сделать следующее:
procedure A;
var
h : String;
begin
h := IntToStr(FindWindow(TForm, Form1));
end;
...не так ли?Или...
А например с помощью GetWindowText() можно получить заголовок окна
...а что конкретно имеется в виду под словосочетанием "заголовок окна" - данная функция,если я не ошибаюсь,возвращает значение типа Integer?
DillerInc
если я правильно понял,можно сделать следующее...
да, можно, но нужно ли? Повторяю еще раз HWND есть не что иное, как Cardinal (беззнаковое длинное целое), не проще ли его передавать как параметр?
а что конкретно имеется в виду под словосочетанием "заголовок окна"
var
S: array[0..999] of Char; // Запас всегда иметь хорошо ;)
begin
.....
// Записываем по адресу @S заголовок окна формы Form1
// GetWindowText приплёл тут просто для примера,
// можно было написать вместо него константу 1000
GetWindowText(Form1.Handle,@S,GetWindowTextLength(Form1.Handle)+1);
// Выводим текст в Label1
Label1.Caption:=S;
end;
Хочу отметить также универсальность GetWindowText. Если HWND указывает на окно - возвращается заголовок окна, если на некоторый контрол, то - текстовое содержимое этого контрола (в Дельфи то же делают свойства Caption и Text).
DillerInc
02-03-2005, 23:46
Savant
Спасибо за информацию - будем мотать на ус :) .
DillerInc
18-08-2005, 20:26
Доброго всем времени суток!
Это называется - сижу, туплю...
Как можно грамотно на Delphi организовать оператор выбора case..of..end;, чтобы он был не такой примитивный как обычно его описывают,например:
case Ch of
'n', 'N', 'н', 'Н' : lbOutput.Caption := 'Нет';
'y', 'Y', 'д', 'Д' : lbOutput.Caption := 'Да';
end;
...а такой,чтобы каждая константа выбора содержала определённый кусок кода.
Можно сделать,конечно,и так:
if dEvent.dwDebugEventCode = LOAD_DLL_DEBUG_EVENT then // Первый вариант константы выбора
begin
hDllFile := dEvent.LoadDll.hFile;
if GetFileNameFromHandle(hDllFile) then
begin
PPointer(Base) := dEvent.LoadDll.lpBaseOfDll;
RestoreCode := InjectCode(EntryPoint, $FFFF);
end;
end;
if dEvent.dwDebugEventCode = EXCEPTION_DEBUG_EVENT then // второй вариант константы выбора
if dEvent.Exception.ExceptionRecord.ExceptionCode =
EXCEPTION_ILLEGAL_INSTRUCTION then
begin
RestoreData(EntryPoint, RestoreCode);
DecryptStart := SeekBpPlace(Base);
SendMessage(hMemo, WM_SETTEXT, 0,
lParam(' * Тра-ля-ля '+IntToHex(DecryptStart, 8)));
end;
...хотя подобный код работает,но он всегда будет полностью проверять все варианты прежде,чем найдёт подходящий.На что будет уходить лишнее время,что "не есть гут" .
Следовательно - как быть ?
DillerInc
Не совсем понятно, как "каждая константа выбора" может содержать "определённый кусок кода" ))). Да к тому же в общем случае процессорное время будет все равно уходить (но меньше), т.к. программа будет последовательно (хотя и это зависит от компилятора, где-то могут для поиска (при большом кол-ве вариантов) использоваться другие алгоритмы) сравнивать значения, пока не найдёт подходящее.
Но если Ваша мысля дошла, то есть два (в принципе одинаковых) решения:
1) внешние операторы if преобразовать к виду
if dEvent.dwDebugEventCode = LOAD_DLL_DEBUG_EVENT then begin
< .. >
end else
if dEvent.dwDebugEventCode = EXCEPTION_DEBUG_EVENT then begin
< .. >
end;
2) использовать case .. of .. end =)
case dEvent.dwDebugEventCode of
LOAD_DLL_DEBUG_EVENT:
begin
< .. >
end;
EXCEPTION_DEBUG_EVENT:
begin
< .. >
end;
end;
Справка: конструкция begin .. end; (блок) являет собой один оператор, вне зависимости от того, сколько операторов в ней находится и находится ли вообще хоть один.
DillerInc
18-08-2005, 22:15
Savant
Спасибо за разъяснения насчёт case .. of .. end .
Сейчас вот подумал,потом глянул это дело в отладчике - действительно оба решения в принципе одинаковы :) .
DillerInc
19-08-2005, 14:10
Вот ещё один вопрос возник:
в Delphi есть объект класса TMemo. У его свойтсва Lines имеются методы Add и Append.
Так вот как можно с помощью WinAPI организовать процедуру,аналогичную дельфийскому методу Append ?
Т.к. если послать сообщение классу STATIC...
SendMessage(handleStatic, WM_SETTEXT, 0, lParam('К примеру '+IntToHex(some_stuff)));
...то это будет аналогично дельфийскому Add, т.е. текст целиком заменится на новый,а мне необходимо добавить этот текст...
Ну нет ничего проще, чем заглянуть в папку .\vcl\source\ и хорошенько там покопаться. Итогом может стать например это:
function GetLine(hwnd: Cardinal; Index: Integer): String;
// Получает строку под номером Index из контрола с Handle = hwnd
var
Text: array[0..4095] of Char;
begin
Word((@Text)^) := SizeOf(Text);
SetString(Result, Text, SendMessage(hwnd, EM_GETLINE, Index, Longint(@Text)));
end;
procedure ReplaceLine(hwnd: Cardinal; Index: Integer; const S: String);
// Заменяет строку под номером Index в контроле hwnd на строку S
var
SelStart: Integer;
begin
SelStart := SendMessage(hwnd, EM_LINEINDEX, Index, 0);
if SelStart >= 0 then begin
SendMessage(hwnd, EM_SETSEL, SelStart, SelStart + SendMessage(hwnd, EM_LINELENGTH, SelStart, 0));
SendMessage(hwnd, EM_REPLACESEL, 0, Longint(PChar(S)));
end;
end;
procedure AddToLine(hwnd: Cardinal; Index: Integer; what: String);
// Добавляет к строке под номером Index строку what
begin
ReplaceLine(hwnd, Index, GetLine(hwnd, Index) + what);
end;
>>Т.к. если послать сообщение классу STATIC...
Замечу, что TMemo относится к "классу" (точнее, типу) EDIT
DillerInc
20-08-2005, 14:38
Savant
Я немного недопонял насчёт параметра Index, который мы передаём процедуре AddToLine, т.е. откуда мы его возьмём...или... :huh:
Мде, заклинило меня на этом Append , с StrCat чего-то попутал :rolleyes: (подумал, что надо добавить одну строку в конец другой, а не новую строку в Memo :shuffle: ). Второе намного проще:
procedure AppendLine(hwnd: Cardinal; const S: String);
// соответствует методу Append
begin
SendMessage(hwnd, EM_SETSEL, MaxInt, MaxInt);
SendMessage(hwnd, EM_REPLACESEL, 0, Longint(PChar(S + #13#10)));
end;
function AddLine(hwnd: Cardinal; const S: String): Integer;
// соответствует методу Add
begin
AppendLine(hwnd, S);
Result := SendMessage(hwnd, EM_LINEFROMCHAR, -1, 0) - 1;
end;
DillerInc
20-08-2005, 19:28
Savant
Спасибо,вот теперь всё получилось :) .
DillerInc
10-02-2006, 23:39
Вот возникла у меня тупиковая ситуация:
var
Buffer : array of Byte; // Есть массив байтов
Pos : Integer;
Bytes : DWORD; есть 32-битная переменная
begin
Bytes := Buffer[Pos+01]; Тут хочу переслать четыре байта
end;
После компиляции команда пересылки байтов выглядит как:
mov al, [edx+01] ; в EDX располагается массив
...т.е. пересылается только один байт вместо четырёх.Приходится уже вручную править это место на:
mov eax, [edx+01]
Подскажите пожалуйста,где я туплю и как заставить компилятор пересылать в данном случае двойное слово,а не один байт.
вар. 1 (следить за границами!!!)
способ универсальный, когда откуда-то надо достать нужное кол-во байтов с любой позиции
var
Buffer: array of Byte; // Есть массив байтов
Pos: Integer;
Bytes: Cardinal;
BytesPtr: ^Cardinal;
begin
BytesPtr := @Buffer[Pos+01];
Bytes := BytesPtr^;
...
вар. 2
применительно к динамическим массивам
var
Buffer: array of Byte; // Есть массив байтов
Pos: Integer;
Bytes: Cardinal;
begin
Bytes := Cardinal(Copy(Buffer, Pos+01, 4));
...
DillerInc
11-02-2006, 17:01
Savant
Спасибо,что откликнулся и помог :) .
Воспользовался первым вариантом - получилось.
P.S. Хотел бы уточнить - существуют ли всё-таки какие-то различия между типами DWORD и Cardinal ??
DillerInc
Хотел бы уточнить - существуют ли всё-таки какие-то различия между типами DWORD и Cardinal ??Абсолютно одно и то же.
32-битное беззнаковое целое, 4 байта в памяти.
Буду очень признателен тому, кто поможет решить такую задачу : при нахождении на форме кусора без движения 3 секунды - он должен исчезать , если пошевелить мышкой - появлятся ( как это сделано в видеоплеерах , например Light Alloy при просмотре видео на весь экран ) .
DillerInc
13-03-2006, 14:21
serg700
Давай пробовать :) .
Значит есть такая WinAPI-функция TrackMouseEvent,которая способна следить за состоянием курсора и отправлять соответствующие сообщения.Эти сообщения будут приниматься и обрабатываться с помощью функции WindowProc приложения.
Функция TrackMouseEvent принимает в качестве параметра указатель на структуру TRACKMOUSEEVENT (http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winui/winui/windowsuserinterface/userinput/mouseinput/mouseinputreference/mouseinputstructures/trackmouseevent.asp),заполняя которую мы указываем особенности слежения за курсором.
Итак,нам понадобится создать функцию,обрабатывающую различные сообщения, - WindowProc:
var
Hovering : Boolean; // переменная типа Boolean,которая сигнализирует о зависании курсора
TME : TTrackMouseEvent;
function WindowProc(hWnd : HWND; uMsg : UINT; wParam : WPARAM;
lParam : LPARAM) : LRESULT; stdcall;
begin
Result := DefWindowProc(hWnd, uMsg, wParam, lParam);
if uMsg = WM_MOUSEMOVE then
begin
{ Заполняем структуру TRACKMOUSEEVENT }
TME.cbSize := SizeOf(TME);
TME.dwFlags := TME_HOVER; // Вариант с зависанием курсора
TME.hwndTrack := hWnd; // Описатель,который используется первым параметром в WindowProc
TME.dwHoverTime := 3000; // три секунды зависания
TrackMouseEvent(TME); // Вызываем саму функцию
if Hovering then // Если курсор зависал и был спрятан,
begin
ShowCursor(True); // то показываем его
Hovering := False;
end;
end; // uMsg = WM_MOUSEMOVE
if uMsg = WM_MOUSEHOVER then // Если поступает сообщение
begin // о зависании курсора,то
Hovering := True; // прячем его
ShowCursor(False);
end; // uMsg = WM_MOUSEHOVER
end; // WindowProc
Функция TrackMouseEvent словно бы одноразовая,т.е. сгенерировав одно сообщение,она перестаёт функционировать,поэтому её необходимо каждый раз запускать заново.Именно поэтому я поставил её инициацию в обработчик сообщения передвижения курсора (WM_MOUSEMOVE) .
P.S. Я точно не уверен возможно ли таким образом реализовать функцию WindowProc на чистом Delphi,т.е. с применением всяких там VCL и т.п.
Я это делал на примере минимального Delphi-приложения,где используется только WinAPI.
P.P.S. Вероятно описанная WindowProc не является полнофункциональной,т.к. я старался объяснить только принцип актуального вопроса.
© OSzone.net 2001-2012
vBulletin v3.6.4, Copyright ©2000-2025, Jelsoft Enterprises Ltd.