Форум программистов, компьютерный форум, киберфорум
Lazarus
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.73/11: Рейтинг темы: голосов - 11, средняя оценка - 4.73
0 / 0 / 0
Регистрация: 08.11.2018
Сообщений: 24
1

Как задать строгое расположение иконок в трее для своего приложения?

23.11.2018, 09:45. Показов 2028. Ответов 2
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Воспользовавшись предложенным в теме Динамически отображать в SysTray информацию программы-таймера решением для вывода в систрее числа минут и секунд в программе таймера через использование двух компонентов TrayIcon с рисованием на их иконках, в ряде случаев столкнулся с проблемой.
Например, если при загрузке программы в Windows ХР, на которой программа была скомпилирована, расположение обеих иконок верное, т.е. слева иконка для показа минут, справа - для показа секунд (ММ:СС), то при загрузке той же самой программы уже на другом компьютере с Windows 7 - иконки сразу же при загрузке почему-то меняются местами. Т.е. там отображается все наоборот - слева иконка, показывающая секунды, а справа от нее - минуты (СС:ММ).
В свойствах TrayIcon к сожалению нет ничего, чтобы могло бы задавать какое-то относительное расположение иконки в трее или хотя бы например порядок ее загрузки в самом приложении, скажем что-то наподобие Z-order.
Пробовал поиграться с видимостью этих двух компонентов TrayIcon, просто попереключав ее.
При этом после компиляции проекта на Windows 7 - порядок иконок там вроде бы становится нормальным. но зато теперь этот же исполняемый файл, но на компьютере с Windows ХР - снова дает неправильное расположение иконок теперь уже там!
Ну и соответственно наоборот.
Пробовал даже уже и какие-то чисто шаманские действия - скажем вставлять в процедуру создание формы подряд команды отключения-включения видимости обеих иконок. И опять - если получается нормальное расположение на одном компе, где проект компилируется - на другом снова показывается все наоборот.
В связи с этим и сам вопрос - каким образом можно задать полностью однозначное расположение этих двух иконок в своем приложении?
В принципе такое похоже как-то возможно - например в программе AnvirTaskManager при включении нескольких иконок в систрее для отображения памяти, процессора и т.п. - порядок их расположения, сколько доводилось наблюдать, никогда не менялся в зависимости от компьютера или системы, всегда очередность их показа одна и та же.
Но как вот всего этого добиться в своем приложении на Lazarus?
0
Лучшие ответы (1)
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
23.11.2018, 09:45
Ответы с готовыми решениями:

Как получить имена иконок приложения в трее для их сортировки?
При построении проекта таймера с выводом минут-секунд в иконки трея, возникшая было проблема...

Появляется много иконок в трее при отладке приложения
При сворачивании окна в трей и последующей работы с программой, появляется много иконок, при...

Задать глобально горячие клавиши только для своего приложения
Private Sub Avtorizacia_KeyDown(ByVal sender As Object, ByVal e As...

Как проигнорировать ToogleDesktop для своего приложения
Пишу что-то на подобии виджета Столкнулся с такой проблемой: При нажатии на Win+D или кнопки...

2
Супер-модератор
Эксперт Pascal/DelphiАвтор FAQ
32835 / 21172 / 8148
Регистрация: 22.10.2011
Сообщений: 36,431
Записей в блоге: 8
23.11.2018, 15:03 2
Лучший ответ Сообщение было отмечено Gennady7 как решение

Решение

Цитата Сообщение от Gennady7 Посмотреть сообщение
Но как вот всего этого добиться в своем приложении на Lazarus?
Под Windows с этим хардкор еще тот (под Linux есть метод GetPosition, который прекрасно возвращает расположение иконки в трее, Windows-версия его не обрабатывает, и возвращает нули). Но я все-таки попробовал. Вот что получилось:

Pascal
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
// Для начала - функция, которая вернет True, когда иконка с хинтом "MyMinuteTray" 
// находится ЛЕВЕЕ, чем иконка с хинтом MySecondTray
 
{$IFNDEF UNIX}
function FirstIsMinute : Boolean;
const
  BUFFER_SIZE = $1000;
var
  OpProc : THandle;
  ProcID : THandle;
  ToolBar : THandle;
  ButtonsCount : integer;
  i : Integer;
  Buffer : Pointer;
  DButton : TTBButton;
  RBytes : PtrUInt;
  BTextLength : Integer;
  R : array [-1 .. 1] of Windows.RECT;
  BText :  WideString;
  ix : integer;
begin
  ToolBar := FindWindow('Shell_TrayWnd', nil);
  ToolBar := FindWindowEx(ToolBar, 0, 'TrayNotifyWnd', nil);
  ToolBar := FindWindowEx(ToolBar, 0, 'SysPager', nil);
  ToolBar := FindWindowEx(ToolBar, 0, 'ToolbarWindow32', nil);
  if ToolBar = 0 then Exit;
 
  ButtonsCount := SendMessage(ToolBar, TB_BUTTONCOUNT, 0, 0);
  GetWindowThreadProcessId(ToolBar, @ProcID);
  OpProc := OpenProcess(PROCESS_ALL_ACCESS, False, ProcID);
  try
    Buffer := VirtualAllocEx(OpProc, nil, BUFFER_SIZE, MEM_COMMIT, PAGE_READWRITE);
    for i := 0 to ButtonsCount - 1 do
      begin
        SendMessage(ToolBar, TB_GETBUTTON, i, LPARAM(Buffer));
        RBytes := 0;
        ReadProcessMemory(OpProc, Buffer, @DButton, SizeOf(TTBButton), RBytes);
        BTextLength := SendMessage(ToolBar, TB_GETBUTTONTEXTW, DButton.idCommand, Integer(Buffer));
        SetLength(BText, BTextLength);
        ReadProcessMemory(OpProc, Buffer, @(BText[1]), BTextLength * SizeOf(BText[1]), RBytes);
 
        ix := IndexStr(UTF8Decode(BText), ['MyMinuteTray', 'MySecondTray']);
        if SendMessage(ToolBar, TB_GETITEMRECT, i, LPARAM(Buffer)) > 0 then
        begin
          ReadProcessMemory(OpProc, Buffer, @(R[ix]), SizeOf(Windows.RECT), RBytes);
        end;
      end;
  finally
    VirtualFreeEx(OpProc, Buffer, 0, MEM_RELEASE);
    CloseHandle(OpProc);
  end;
  Result := R[0].Left < R[1].Left;
end;
{$ENDIF}
 
// теперь изменение в обработчике таймера
procedure TForm1.Timer1Timer(Sender: TObject);
var
  bFirstIsMinute : Boolean;
begin
  // получение значения bFirstIsMinute можно, конечно, вынести из таймера, но вдруг Windows возьмет и переупорядочит иконки?
  {$IFDEF UNIX}
    bFirstIsMinute := TrayIcon1.GetPosition.x < TrayIcon2.GetPosition.x; // вот этого достаточно для того, чтобы определить взаимное расположение иконок у меня под Debian-ом (XFCE, если что)
  {$ELSE}
    bFirstIsMinute := FirstIsMinute;
  {$ENDIF}
  Caption := tm.ToString;
  Application.Title := tm.ToString;
  DrawTime(IfThen(bFirstIsMinute, tm div 60, tm mod 60), TrayIcon1); // uses Math для использования этой функции
  DrawTime(IfThen(bFirstIsMinute, tm mod 60, tm div 60), TrayIcon2);
  Dec(tm);
  Timer1.Enabled := tm <> 0;
end;
 
// ну и назначаем хинты:
procedure TForm1.FormCreate(Sender: TObject);
begin
  tm := 380; // время в секундах
  TrayIcon1.Hint := 'MyMinuteTray'; // <---
  TrayIcon2.Hint := 'MySecondTray'; // <---
end;
Тестировал под WinXP 32-bit, Win7 32/64, Win8 32-bit, десятки не держу, но не вижу причин для кода там не работать (хотя для версий Windows начиная с Win7 есть другой способ определения координат - у тебя упоминание про WinXP, поэтому привожу этот способ, который хоть и чуть длиннее, но работает везде...)
0
0 / 0 / 0
Регистрация: 08.11.2018
Сообщений: 24
26.11.2018, 13:58  [ТС] 3
volvo, действительно отлично работает и на ХР, и на 7. Решение просто-таки замечательное! Спасибо большое!
Ради интереса проверю на днях и на десятке.
0
26.11.2018, 13:58
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
26.11.2018, 13:58
Помогаю со студенческими работами здесь

Как установить иконку для своего приложения
Добрый день! Подскажите пожалуйста как приложению задать иконку. Оно ставиться но сверху но в паке...

Как создать установщик для своего приложения
давно хочу написать установкщик,но весь гугл перерыв не нашел.вот все совреемнные установщики...

Задать сборке строгое имя
Не могу понять по книге Дж.Рихтера CLR via C# 4.0. Объясните пожалуйста как создавать сборку со...

Проблема с размерами иконок в трее
Делаю иконку для проги, по правилам должно идти 48x48 на 16, 32x32 на 16, 24x24 на 16, 16x16 на 16,...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
3
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru