Ru-Board.club
← Вернуться в раздел «Прикладное программирование»

» Вопросы по Delphi 2

Автор: Jokerjar
Дата сообщения: 26.09.2006 18:06
STEEL,

function MyGetDir: string;
var
TheFileName : array[0..MAX_PATH] of char;
begin
FillChar(TheFileName, sizeof(TheFileName), #0);
GetModuleFileName(hInstance, TheFileName, sizeof(TheFileName));
result:=TheFileName
end;


Добавлено:

Цитата:
wparam находится хэндл окна

То есть тип сообщения, я ошибся. Но сути дела это не меняет

Добавлено:
Могу вопрос и по-другому поставить: как узнать параметр wparam сообщения, отловленного хуком wh_mouse. Не тот wparam, где хранится, к примеру, wm_mousewhell, а wparam самого wm_mousewhell...
Автор: wader
Дата сообщения: 26.09.2006 18:49
Jokerjar
Посмотри структуру MOUSEHOOKSTRUCTEX в моем предыдущем сообщении.
Там как раз есть MouseWheel который тебе нужен.
(Но работать будет только с Win2000)
Автор: Jokerjar
Дата сообщения: 26.09.2006 20:27
wader, да вот смотрю на нее. Только не понимаю, как вытащить ее из процедуры ловушки, там ей и не пахнет.

З.Ы. В делфи я эту MOUSEHOOKSTRUCTEX ваще не нашел

Добавлено:

Цитата:
typedef struct {
MOUSEHOOKSTRUCT MOUSEHOOKSTRUCT;
DWORD mouseData;
} MOUSEHOOKSTRUCTEX, *PMOUSEHOOKSTRUCTEX;


Видно, что MOUSEHOOKSTRUCT - это часть структуры MOUSEHOOKSTRUCTEX. Мне дан указатель на MOUSEHOOKSTRUCT. Если здвинуть его на размерность MOUSEHOOKSTRUCT, возможно я попаду на mouseData... Но не факт. Повторюсь, в делфи записи вообще другие. Я их выше писал
Автор: wader
Дата сообщения: 26.09.2006 22:51
Jokerjar
Хе-хе точно, у себя в Delphi7 не нашел.

ну не проблема сделай так:

Код:
MOUSEHOOKSTRUCTEX = packed record
mhs: TMOUSEHOOKSTRUCT;
mouseData: DWORD;
end;
Автор: Jokerjar
Дата сообщения: 27.09.2006 03:28
wader

Это все понятно. Но пойми, что у меня в руках, только TMOUSEHOOKSTRUCT, и через него я не могу выйти на MOUSEHOOKSTRUCTEX, чтобы добраться до маусдата. Это главная проблема


Добавлено:
Я практически добрался вручную до этого mousedata. Смотри:

type
MOUSEHOOKSTRUCTEX = packed record
mhs: TMOUSEHOOKSTRUCT;
mouseData: DWORD;
end;

function GlobalMouseHook(code: integer; wParam: word; lParam: longword): longword; stdcall;
var
ex: MOUSEHOOKSTRUCTEX;
begin
if code <> HC_ACTION then begin
GlobalMouseHook:=CallNextHookEx(CurrentHook,code,wParam,lparam);
Exit;
end;
if Wparam = WM_MOUSEWHEEL then begin
ex.mhs := TmouseHookStruct(Pointer(lparam)^);
ex.mousedata := dword(Pointer(lparam+sizeof(TMOUSEHOOKSTRUCT))^);
showmessage(int2str(HIWORD(ex.mouseData)));
end;
CallNextHookEx(CurrentHook,code,wParam,lparam);
GlobalMouseHook:=0;
Exit
end;

Положительные значения при движении вверх получаются отлично (120, 240, 360 и т.д.), а вот отрицательные нет.
Видимо, что до нужно дополнить. Помогите

Добавлено:
При движении вниз получаю значения: 64576, 65176, 65296 ...
Совсем не то. Вспоминаю теорию (архитектура ЭВМ). Перевожу эти числа в двоичную с. исч.:

64576 = 1111 1100 0100 0000
65176 = 1111 1110 1001 1000
65296 = 1111 1111 0001 0000

Перевожу их в дополнительный код (заменяю 0 на 1 а 1 на 0)

1111 1100 0100 0000 = 1110111111
1111 1110 1001 1000 = 101100111
1111 1111 0001 0000 = 11101111

И увеличиваю младший бит на 1

1110111111 = 1111000000
101100111 = 101101000
11101111 = 11110000

и смотрю что у меня получилось:

1111000000 = 960
101101000 = 360
11110000 = 240

Это уже отрицательные значения. И видно, что они правильные, т.к. кратны 120.
Это что выходит, что hiword правильно выдает только положительные числа. А чтоб получить отрицательное, нужно проделывать вышеописанные
действия (кстати, на то, что число отрицательное указывает единица в самом старшем бите). Думаю, что в Delphi есть процедура, которая
делает это (65296 -> -240). Профи, подскажите!

Добавлено:
Все получилось! Вот рабочая функция (по крайней мере, на моем компе):

type
MOUSEHOOKSTRUCTEX = packed record
mhs: TMOUSEHOOKSTRUCT;
mouseData: DWORD;
end;

function GlobalMouseHook(code: integer; wParam: word; lParam: longword): longword; stdcall;
var
i: integer;
s: string;
ex: MOUSEHOOKSTRUCTEX;
begin
if code <> HC_ACTION then begin
GlobalMouseHook:=CallNextHookEx(CurrentHook,code,wParam,lparam);
Exit;
end;
if Wparam = WM_MOUSEWHEEL then begin
ex.mhs := TmouseHookStruct(Pointer(lparam)^);
ex.mousedata := dword(Pointer(lparam+sizeof(TMOUSEHOOKSTRUCT))^);
i := smallint(HIWORD(ex.mouseData)) div wheel_delta;
s := int2str(abs(i))+' оборот(а,ов) ';
if i>0 then s := s + 'вверх' else
s := s + 'вниз';
showmessage(s);
end;
CallNextHookEx(CurrentHook,code,wParam,lparam);
GlobalMouseHook:=0;
Exit;
end;

P.S. Странно, что ни MOUSEHOOKSTRUCTEX, ни как до него добраться в Delphi не описано, хотя мб я плохо искал

P.P.S. Спасибо всем, кто помог

P.P.P.S. У кого win 2000 и мышь с колесом, проверьте код на работоспособность
Автор: xitsmex
Дата сообщения: 27.09.2006 07:29
yuish
Самописная. Компонент для доступа к информации о версии на запись/чтения взял тут: http://delphi.michawinter.de/. Дальше - дело техники.
Автор: h0mer
Дата сообщения: 27.09.2006 07:56
Jokerjar

procedure TMainForm.FormCreate(Sender: TObject);
begin
Application.OnMessage := MainForm.AppMessage;
end;

procedure TMainForm.AppMessage(var Msg: TMsg; var Handled: Boolean);
var
i: SmallInt;
begin
if Msg.message = WM_MOUSEWHEEL then
begin{}
i := HiWord(Msg.wParam); //направление колёсика мыши
if i > 0 then
StringGrid.Perform(WM_VSCROLL,SB_LINEUP,0) // строку вверх по компоненту StringGrid
else
StringGrid.Perform(WM_VSCROLL,SB_LINEDOWN,0); // строку вниз по компоненту StringGrid
Handled := False;
end;
end;

З.Ы. Не это роешь ?
Автор: wader
Дата сообщения: 27.09.2006 08:12
Jokerjar
Ну и нафига ты лишнии движения делаешь?


Код:
var
ex: MOUSEHOOKSTRUCTEX;
...
ex := MOUSEHOOKSTRUCTEX(Pointer(lparam)^);
Автор: greenpc
Дата сообщения: 27.09.2006 08:18
Jokerjar
уже было
Автор: OdesitVadim, Отправлено:18:53 18-08-2006

x:=SmallInt(WORD(strtoint('65296')));

Автор: Jokerjar
Дата сообщения: 27.09.2006 11:14

Цитата:
var ex: MOUSEHOOKSTRUCTEX; ... ex := MOUSEHOOKSTRUCTEX(Pointer(lparam)^);  

Согласен!


Цитата:
З.Ы. Не это роешь ?

Неа, ибо все делалось в длл. Вопрос снят


Добавлено:

Цитата:
Поэтому лучше сверяться с MSDN

Очень часто это слышу, но никогда не задумываля, что это такое, где это взять и с чем есть?
Автор: wader
Дата сообщения: 27.09.2006 11:27
Jokerjar
Можешь начать отсюда: http://msdn.microsoft.com
И да поможет тебе поиск

P.S.
Но лучше иметь в локальном варианте
Автор: Hazard
Дата сообщения: 27.09.2006 15:06
Подскажите пожалуйста вариант решения такой проблемы:

Имеется главная форма
в ней есть две функции
ф1 вызывает ф2 с параметрами
ф2 работает с TWebBrowser
Если вызывать из самой формы ф1 - TWebBrowser отрабатывает.
Есть Thread
как из него вызвать ф1 и не получить "He был пpoизвeдeн вызoв CoInitialize."
Я понимаю что все делов в CoInitialize(nil) и CoUnInitialize, но где и как их прописывать ?
ActiveX и uses есть,
initialization
CoInitialize(nil);
finalization
CoUnInitialize;
перед "end." в Thread не помогает

Автор: Dmitry
Дата сообщения: 27.09.2006 15:12
в функции потока в начале вызвать CoInitialize(nil), а в конце CoUnInitialize
Автор: wader
Дата сообщения: 27.09.2006 15:13
Hazard
Попробуй сделать вызов из Thread через метод Synchronize.
например так:

Код:
procedure TMyThread.PushTheButton;
begin
Button1.Click();
end;

procedure TMyThread.Execute;
begin
...
Synchronize(PushTheButton);
...
end;
Автор: Shweper
Дата сообщения: 27.09.2006 15:19
Здравствуйте Вопрос такой. Вставил я в форму объект TShockwaveFlash и вылазит он всё время на передний план, а я хочу на него положить например TImage. Все "НА передний план" и "На задний план" почему-то в данном случае срабатывают только если речь идет о двух флешках, а флешку и рисунок никак... Может кто-нибудь что-нибудь сказать? Использую Delphi5
Автор: RomanTim
Дата сообщения: 27.09.2006 15:52
Shweper
TImage - наследник от TGraphicControl - то есть не является отдельным виндовым контролом, а рисуется самой формой по ее канвасу (как и TLabel). Виндовые контролы такие рисунки перекрывают.
Чтобы картинка была поверх контрола положи ее на TPanel, которая уже лежит на форме
Автор: Hazard
Дата сообщения: 27.09.2006 16:48
Dmitry
Если бы все было так просто - я бы не спашивал

Цитата:

procedure myThread.Execute;
begin
CoInitialize(nil);

//мой код

CoUnInitialize;
end;

Результат

Цитата:
Project 1.exe raised exception class EAccessViolation with message 'Access violation at address 7C918FEA in module 'ntdll.dll'. Write of address 00000010'.


wader
А смысл Thread при этом не теряется разве ?
Так у меня ф1 и ф2 создавались для нового потока (о чем и говорит ошибка). А как для вызова нажатия клавиши ? Да и не пойдет это. Я же писал ф2 надо вызывать с параметрами (и разными) через ф1, которая их и высчитывает...
Автор: Shweper
Дата сообщения: 27.09.2006 16:51
RomanTim
Спасибо, вроде понял почему. А TPanel мне не пойдет, она непрозрачная, а я пытаюсь на флешку положить PNG с поддержкой прозрачности... Главное теперь вижу куда искать

Добавлено:
Вообще видимо проще всего будет найти Дельфи6..
Автор: RomanTim
Дата сообщения: 27.09.2006 18:20
Hazard

Цитата:
А смысл Thread при этом не теряется разве ?

А ты прочитай в справке (да и мастер создания потока пишет в юнит) про обращение к объектам VCL из других потоков - непотокозащищенное она, VCL эта.
Кстати, этим и AccessViolation может быть спровоцирован
Автор: wader
Дата сообщения: 27.09.2006 18:28
Hazard
Не надо работать с VCL компонентами из разных потоков!!!

Если не хочешь синхронности через Synchronize, работай через передачу сообщений, будет все работать отлично и асинхронно! проверенно.
Автор: Dmitry
Дата сообщения: 27.09.2006 21:07
Hazard
Извиняюсь. Не совсем понял начальный вопрос. Я так понял что проблема была в инициализации COM в отдельном потоке. Его действительно нужно инитить в каждом потоке отдельно. Но судя по сообщению об ошибке в следующем посте, проблема не в этом. Я бы постарался найти причину AV, прежде чем делать дальнейшие выводы. При трассировке, когда именно AV вываливается?

wader
Работать с VCL компонентами из разных потоков вполне возможно, нужно только аккуратно синхронизировать эти потоки с основной очередью сообщений. Либо через Synchronize, либо напрямую через оконные сообщения.
Автор: wader
Дата сообщения: 27.09.2006 22:26
Dmitry
Так именно это я и сказал

Либо Synchronize, синхронизация (Кстати тоже через сообщения сделана )
Либо асинхронно через сообщения.
Оба эти метода не прямые. Доступ происходит в главном потоке.

А прямой метод - это непосредственно в дочернем потоке вызвать метод VCL компонента - ничего хорошего из этого не выйдет.
Автор: Hazard
Дата сообщения: 27.09.2006 22:59
Да Synchronize я пользуюсь - таймером управляю. Только это не совсем то. У меня еще и переменные глобальные есть, все синхронизировать - тяжко. Получается легче все в поток перенести или вообще логику программы менять. Вообще каковы принципы разработки многоэтапного процесса ? Ну напр. работа с бд или интернетом с возможностью прерывания любого процесс пользователем ? Если использовать большие циклы, то кроме как thread вроде ничего не пойдет - операционка будет считать приложение "зависшим", да и все контролы будут заморожены ... Или варианты все же есть ?
Автор: wader
Дата сообщения: 28.09.2006 01:25
Hazard
А чем сообщения не устраивают?
Автор: Dmitry
Дата сообщения: 28.09.2006 05:50
Hazard
Можно в длительном цикле периодически вызывать Application.ProcessMessages(). Тогда приложение будет нормально реагировать на действия пользователя и можно будет прерывать выполнение цикла допустим по нажатию кнопки и т.п.
Автор: yuish
Дата сообщения: 28.09.2006 09:35
xitsmex
Спасибо. буду пытать
Автор: Hazard
Дата сообщения: 28.09.2006 19:21
wader
Дык Synchronize хорош для обновления пары - тройки объектов, а не работы с кучей глобальных переменных. И мне он по идеологии видимо не сильно подходит.
Dmitry
Вот спасибо, так спасибо ! Уважил ! Как же я сам про ProcessMessages забыл, хотя сам ведь сам в коде отрисовки WebBrowser использовал. ОГРОМНОЕ СПАСИБО !
Автор: RomanTim
Дата сообщения: 29.09.2006 07:06
Hazard

Цитата:
Дык Synchronize хорош для обновления пары - тройки объектов, а не работы с кучей глобальных переменных. И мне он по идеологии видимо не сильно подходит.

Syncronize дает возможность выполнить что-то в контекте основного потока - преимущественно это нужно для работы с объектами из VCL, для глобальных переменных есть набор специальных средств синхронизации потоков (семафоры, крит. секции и т.д.)
А ProcessMessages при достаточно долгой итерации цикла тоже не сильно помогает
Автор: ArtemiyUO
Дата сообщения: 29.09.2006 07:31
Hazard
А не статистику времени загрузки веб страниц вы случаем пишите?)
Автор: Hazard
Дата сообщения: 29.09.2006 17:28
RomanTim
Полностью согласен, но видимо я еще не достиг "достаточно долгой итерации цикла" т.к. ProcessMessages реально помог, да же на слабой машинке. Хотя надо будет присмотреться и к твоему предложению. Что ты подразумевал под т.д. или семафоры (CreateMutex, OpenMutex, Pipe) рулитят ? Если есть опыт работы с ними - поделись

ArtemiyUO
Скорее обработку контекста Статистику вроде можно просто снять - типа так, напр.

Цитата:
//сохраняем время
WB.Navigate('что то там такое типа адреса');
// Ожидаем создания документа и позволяем обрабатывать все сообщения
while WB.Document = nil do Application.ProcessMessages;
//Смотрим скока прошло ..

или ты не об этом ?

Страницы: 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667

Предыдущая тема: Событие STFilter(DBGridEh) ???


Форум Ru-Board.club — поднят 15-09-2016 числа. Цель - сохранить наследие старого Ru-Board, истории становления российского интернета. Сделано для людей.