Отправляет email-рассылки с помощью сервиса Sendsay

Программирование. Форум !!!

За 2006-02-13

Re[2]: Найти иконку в трее

Здравствуйте, Алексей.

Monday, February 13, 2006, 11:58:18 AM, you wrote:

А> Вобщем я делал так. System Tray это toolbar с кнопками. Все что нужно
А> это получить список этих кнопок. Прям так сходу не смогу сказать как
А> это делается, MSDN нет под рукой. Что то типа GET_BUTTON мессадж
А> должен быть. Могу поискать проект на делфи если интересует. Эту идею в
А> свое время я высмотрел на CodeProject.com. Там проект был на C++
А> написан.

Был бы Вам очень признателен за этот проект. Вообще-то, я нашел пример
на С++ и переделал его на Делфу. Получилось такое:
var
wnd,hpr :HWND;
pid :Cardinal;
n,i :Integer;
bt :PTBBUTTON;
mBt,mRect :Pointer;
r :TRect;
RBytes :DWORD;
p :PChar;
begin
wnd := FindWindowEx(0,0,'Shell_TrayWnd',0);
wnd := FindWindowEx(wnd,0,'TrayNotifyWnd',0);
wnd := FindWindowEx(wnd,0,'SysPager',0);
wnd := FindWindowEx(wnd,0,'ToolbarWindow32',0);
GetWindowThreadProcessId(wnd, pid);

hpr := OpenProcess(PROCESS_VM_OPERATION or PROCESS_VM_READ, False, pid);
mBt := VirtualAllocEx(hpr, nil, SizeOf(TTBButton), MEM_COMMIT or MEM_RESERVE,
PAGE_READWRITE);
mRect := VirtualAllocEx(hpr, nil, SizeOf(TRect), MEM_COMMIT or MEM_RESERVE,
PAGE_READWRITE);

GetMem(p, 255);
lbx.Items.Clear;
n := SendMessage(wnd, TB_BUTTONCOUNT, 0, 0);
for i := 0 to n-1 do
begin
// ZeroMemory(mBt, SizeOf(mBt^));
if BOOL(SendMessage(wnd, TB_GETBUTTON, WParam(i), LParam(Bt))) then
Tag := SendMessage(wnd, TB_GETBUTTONTEXT, Bt.idCommand, LParam(p));
// if BOOL(ReadProcessMemory(hpr, mBt, @bt, SizeOf(TTBButton), RBytes))
then
// Tag := SendMessage(wnd, TB_GETBUTTONTEXT, bt.idCommand, LParam(p[0]));
end;
FreeMem(p, 255);
VirtualFreeEx(hPr, mBt, 0, MEM_RELEASE);
VirtualFreeEx(hPr, mRect, 0, MEM_RELEASE);
// close thread process handle
CloseHandle(hPr);
end;
Я тут в качестве эксперементов "поначеркивал" и поудалял кое-что по
сравнению с оригиналом. Cамое интересное то, что число кнопок в трее
определяет четко, а вот чтобы определить параметры i-ой кнопки... В
принципе, я понимаю, почему так происходит - число-то определяется по
хэндлу бара. А после, этого я начинаю "плавать", поскольку не совсем
понимаю, как добраться до этой i-й кнопки. В частности, у меня большое
удивление вызывает то, что SendMessage(wnd, TB_GETBUTTON, WParam(i),
LParam(Bt)) в Bt возвращает одно и то же для любого i.
В общем, если меня поправите, буду признателен.
Кстати, вот оригинальный текст на С. Но даже при более-менее точном
его переводе на Делфи ничего не вышло.

HWND hWnd; // my window
RECT rcTray; // my icon rect
HWND hTrayToolTip; // tray tooltip
HWND hTrayBalloon; // tray balloon
HWND hTrayToolBar; // handle to tray window

bool SetTrayToolRect(bool LocateHints)
{
// find shell tray window
HWND hShellTray = ::FindWindow("Shell_TrayWnd",NULL);
// find tray notify window
HWND hTrayNotify = ::FindWindowEx(hShellTray, NULL, "TrayNotifyWnd", NULL);
// find tray toolbar
hTrayToolBar = ::FindWindowEx(hTrayNotify, NULL, "ToolbarWindow32", NULL);

// get shell tray thread and process ids
DWORD dTrayProcess, dTrayThread;
dTrayThread = ::GetWindowThreadProcessId(hTrayToolBar, &dTrayProcess);

// locate hints
if (LocateHints)
{
// find tray balloon and tooltip
hTrayBalloon = NULL;
hTrayToolTip = NULL;
// find window
HWND hBalloon = ::FindWindowEx(NULL, NULL, TOOLTIPS_CLASS, NULL);
while (hBalloon)
{
DWORD dProcess, dThread;
dThread = ::GetWindowThreadProcessId(hBalloon, &dProcess);
if (dThread == dTrayThread && dProcess == dTrayProcess)
{
// balloon style
if (::GetWindowLong(hBalloon, GWL_STYLE) & TTS_BALLOON)
{
hTrayBalloon = hBalloon;
if (hTrayToolTip) break;
}
// tooltip
if ((::GetWindowLong(hBalloon, GWL_STYLE) & TTS_NOPREFIX) == 0)
{
hTrayToolTip = hBalloon;
if (hTrayBalloon) break;
}
}
// get next window
hBalloon = ::FindWindowEx(NULL, hBalloon, TOOLTIPS_CLASS, NULL);
}
}

// open tray process
HANDLE hTrayProcess = ::OpenProcess(PROCESS_ALL_ACCESS, FALSE, dTrayProcess);
// allocate memory in tray process
// button info
void* mButton = ::VirtualAllocEx(hTrayProcess, NULL, sizeof(TBBUTTON),
MEM_COMMIT, PAGE_READWRITE);
// rect
void* mRect = ::VirtualAllocEx(hTrayProcess, NULL, sizeof(RECT),
MEM_COMMIT, PAGE_READWRITE);
// handle to window receiving tray messages
void* mWnd = ::VirtualAllocEx(hTrayProcess, NULL, sizeof(HWND),
MEM_COMMIT, PAGE_READWRITE);
// look for the icon
bool Found = false;
// get buttons count
int nButtons = ::SendMessage(hTrayToolBar, TB_BUTTONCOUNT, 0, 0);
for (int i=0; i<nButtons; i++)
{
// reset button
TBBUTTON Button;
::ZeroMemory(&Button, sizeof(TBBUTTON));
DWORD ReadBytes = 0;
// get button
::SendMessage(hTrayToolBar, TB_GETBUTTON, i, LPARAM(mButton));
// transfer to local address space
::ReadProcessMemory(hTrayProcess, mButton, &Button, sizeof(TBBUTTON), &ReadBytes);

// get icon owner window handle - this is the trick!!! ;)
HWND hCompareWnd = NULL;
// transfer to local address space
::ReadProcessMemory(hTrayProcess, (void*)Button.dwData, &hCompareWnd, sizeof(HWND),
&ReadBytes);
// compare handles
if (hCompareWnd == hOwner)
{
// found
::ZeroMemory(&rcTrayIcon, sizeof(RECT));
// get icon rect
::SendMessage(hTrayToolBar, TB_GETRECT, Button.idCommand, LPARAM(mRect));
// convert to local space
::ReadProcessMemory(hTrayProcess, mRect, &rcTrayIcon, sizeof(RECT), &ReadBytes);
// end searching
Found = true;
break;
}
}

// free memory in tray process
::VirtualFreeEx(hTrayProcess, mButton, 0, MEM_RELEASE);
::VirtualFreeEx(hTrayProcess, mRect, 0, MEM_RELEASE);
::VirtualFreeEx(hTrayProcess, mWnd, 0, MEM_RELEASE);
// close thread process handle
::CloseHandle(hTrayProcess);

// check result
if (!Found)
{
// reset
::ZeroMemory(&rcTrayIcon, sizeof(RECT));
return false;
}

// convert to screen
::ClientToScreen(hTrayToolBar, (POINT*)(&(rcTrayIcon.left)));
::ClientToScreen(hTrayToolBar, (POINT*)(&(rcTrayIcon.right)));

// successful return
return true;
}

   Вадим Шешунов 2006-02-13 23:21:28 (#514796)

Re: Найти иконку в трее

Добрый день Вадим,

Вадим> Да вот, что-то не получается у меня отыскать в списке окон окно с
Вадим> ярлычком. Я думаю, может моя прога не успевает по времени "ухватиться"
Вадим> за этот ярлык. Или я концептуально ошибаюсь?

Вобщем я делал так. System Tray это toolbar с кнопками. Все что нужно
это получить список этих кнопок. Прям так сходу не смогу сказать как
это делается, MSDN нет под рукой. Что то типа GET_BUTTON мессадж
должен быть. Могу поискать проект на делфи если интересует. Эту идею в
свое время я высмотрел на CodeProject.com. Там проект был на C++
написан.

   2006-02-13 12:58:32 (#514484)

Re: SQL в BDE

> Пробовал ADO, но так как-то странно работают внешние связи, так и не
> разобрался... Для примера, мне позарез нужно, чтоб работал такой (или
> подобный) запрос:
> ...

Ни разу не сталкивался с проблемами. Вот только синтаксис у тебя
любопытный. Никогда с таким не сталкивался, чтоб серия соединений
заключалась в скобки и к результату снова применяется соединение. Это что
вообще значит?

FROM (t1 LEFT JOIN t2 ON ...) LEFT JOIN t3 ON ...

> Пока такое работает только в BDE и DBISAM. В DBISAM только очень долго:
> ...
> В общем, довольно скромно все, ...

Скромно. Но группировка везде тормозит. В смысле, на не выделенных ДБ
серверах. Но c ADO как-то попроще. ADO, как я заметил, тормозит на
агрегатных функциях, но наверняка это от провайдера зависит.

>> А чё там писать-то?
>>
>> INSERT INTO sqlTable (fieldList) SELECT fieldList FROM dbfTable
>>
>> или даже
>>
>> INSERT INTO sqlTable SELECT * FROM dbfTable
>>
>> если структура sqlTable та же самая, что и dbfTable...
> А таблицы при таком способе создадутся автоматически?

Нет. Но ИМХО в SQL имеются все средства для управления таблицами,
индексами, представлениями (VIEW) итп. CREATE TABLE, CREATE INDEX, DROP
TABLE итп.

> В придачу к этому в нужных DBF-файлах используются нестандартные индексы,

> > приходится их отключать (без отключения индексов с этими файлами
> работают
> только Halcyon и Apollo).

Во-во. Упомянутый мной MS VSFoxPro OLEDB Provider с такими (если я
правильно понял какими) работает на ура.

--
С уважением, boroda

Номер выпуска : 5194
Возраст листа : 876 (дней)
Количество подписчиков : 546
Адрес в архиве : http://subscribe.ru/archive/comp.soft.prog.prog/msg/514409
Получить правила : mailto:comp.soft.prog.prog-rules@subscribe.ru
Формат "дайджест" : mailto:comp.soft.prog.prog-digest@subscribe.ru
Формат "каждое письмо" : mailto:comp.soft.prog.prog-normal@subscribe.ru
Формат "читать с веба" : mailto:comp.soft.prog.prog-webonly@subscribe.ru

   Шматко А.А. 2006-02-13 09:57:50 (#514409)

Re: Вывод окна приложения на передний план.

Всем привет!

Значит так:
Шматко, написал, что я примерно и думал. Поскольку в связке участвуют
3 приложения (сом-сервер внешний и прога1 и прога2), то возможно и
происходит описываемое событие. Только немного практика в теорию не
упирается.
Делал так. Приложение с editом и кнопкой. В edit вводится хэндл.
Кнопка отрабатывает SetForegroundWindow. Все работает прекрасно.
А вот если это-же приложение запускать через СОМ-сервер внешний, то
только один раз отрабатывает.

Не знаю как объяснить и тем более не знаю где рыть. Но сдается мне,
что 2 приложения завязаны на 3-ем. Т.е. когда прога1 говорит: "Выведи
мне прогу2", то СОМ-сервере, честно отрабатывает вывод, но он связан с
прогой1 и возвращает результат функции, чем не дает вывести прогу2.

Чисто условно, но что-то такое смутно вращается.
Может как-то по хитрому запустить, например, в независимом потоке из
СОМ-сервера?

   2006-02-13 06:52:31 (#514370)