±Û³»¿ë - °­ÁÂ, ÆÁ, Á¤º¸
 Tray icon °»½Å (¸¶¿ì½º·Î Èȴ°Š¾Æ´Ô)
¹ß¹Ù´ß
(ryujaeuk)
2011-05-27 ¿ÀÈÄ 8:27:45
Ä«Å×°í¸®:ÆÁ
7570ȸ Á¶È¸



÷ºÎÆÄÀÏ ´Ù¿î·Îµå
ShellTrayIconRefreshExample.zip

¿¹Àü¿¡ ¸¶¿ì½º Æ÷ÀÎÅ͸¦ Æ®·¹ÀÌÂÊÀ¸·Î ¿Å°Ü¼­ Áö¿öÁÖ´Â ¼Ò½º°¡ ÀÖ¾ú´Âµ¥
´©°¡ Àß ¾ÈµÈ´Ù°í Çؼ­ ´Ù½Ã ¸¸µé¾ú½À´Ï´Ù.



¼Ò½º´Â ¼ÀÇà ÄÚµå¶ó Á» ÁöÀúºÐÇÕ´Ï´Ù.

  TB_BUTTONCOUNT ¸Þ½ÃÁö·Î Æ®·¹ÀÌ ¾ÆÀÌÄÜ °¹¼ö¸¦ ¾ò°í

  TB_GETBUTTON À¸·Î ¹öÆ° ±¸Á¶Ã¼¸¦ ¾ò¾î¼­ ProcessID¸¦ ±¸ÇÏ°í

ProcessID°¡ ºñ¾î ÀÖ´Â(¾²·¹±â) ¾ÆÀÌÄÜÀ»

Shell_NotifyIcon(NIM_DELETE, @icon); API·Î Á÷Á¢ Á¦°ÅÇÕ´Ï´Ù.

64ºñÆ®¶û 32ºñÆ®´Â ±¸Á¶Ã¼°¡ Á¶±Ý ´Þ¶ó¼­

ÇÔ¼ö°¡ µÎ°³¿©¿ä.








unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

type
  TIsWow64Process = function (hProcess: THANDLE; Wow64Process: PBOOL): BOOL; stdcall;

  TForm1 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

  //=========================================================
  // ±¸Á¶Ã¼ Á¤ÀÇ
  //=========================================================

  TRAYDATA = packed record
    wnd: HWND;
   uID: UINT;
   uCallbackMessage: UINT;
   Reserved: array [0..1] of DWORD;
   hIcon: HICON;
  end;

  TBBUTTON = packed record
    iBitmap: Integer;
    idCommand: Integer;
    fsState: BYTE;
    fsStyle: BYTE;
    bReserved: array [0..1] of BYTE;    // padding for alignment
    dwData: Pointer;                    //DWORD_PTR;
    iString: Pointer;                   //INT_PTR;
  end;

  TBBUTTON64 = packed record
    iBitmap: Integer;
    idCommand: Integer;
    fsState: BYTE;
    fsStyle: BYTE;
    bReserved: array [0..5] of BYTE;    // padding for alignment  64bit
    dwData: Pointer;                    //DWORD_PTR;
    iString: Pointer;                   //INT_PTR;
  end; 

const
  TB_BUTTONCOUNT = WM_USER + 24; 
  TB_GETBUTTON = WM_USER + 23;
 
var
  Form1: TForm1;
  IsWow64Process: TIsWow64Process;

implementation

{$R *.dfm}

uses
  ShellAPI;

//=========================================================
// Tray ¾ÆÀÌÄÜÀÇ ÇÁ·Î¼¼½º À̸§À» ¾ò±â À§ÇØ À©µµ¿ì ÇÚµéÀ» ¾ò´Â ÇÔ¼ö
//=========================================================
function FindTrayToolbarWindow: HWND;
var
  hWnd_ToolbarWindow32: HWND;
 hWnd_ShellTrayWnd: HWND;
  hWnd_TrayNotifyWnd: HWND;
  hWnd_SysPager: HWND;
begin
  hWnd_ToolbarWindow32 := 0;

  hWnd_ShellTrayWnd := FindWindow('Shell_TrayWnd', nil);
 if hWnd_ShellTrayWnd <> 0 then begin
  hWnd_TrayNotifyWnd := FindWindowEx(hWnd_ShellTrayWnd, 0, 'TrayNotifyWnd', nil);
  if hWnd_TrayNotifyWnd <> 0 then begin
   hWnd_SysPager := FindWindowEx(hWnd_TrayNotifyWnd, 0,'SysPager', nil); // WinXP

   // WinXP ¿¡¼­´Â SysPager ±îÁö ÃßÀû
   if hWnd_SysPager <> 0 then begin
    hWnd_ToolbarWindow32 := FindWindowEx(hWnd_SysPager, 0, 'ToolbarWindow32', nil);
      end else begin
        // Win2000 ÀÏ °æ¿ì¿¡´Â SysPager °¡ ¾øÀÌ TrayNotifyWnd -> ToolbarWindow32 ·Î ³Ñ¾î°£´Ù
        hWnd_ToolbarWindow32 := FindWindowEx(hWnd_TrayNotifyWnd, 0,'ToolbarWindow32', nil);
      end;
  end;
 end;
   
 Result := hWnd_ToolbarWindow32;
end;

//=========================================================
// Refresh ÀÇ ¸ÞÀÎ
//=========================================================
function ShellTrayIconRefresh32: Boolean;
var
  m_hProcess: THANDLE;
  m_lpData: ^TBBUTTON;
  tb: TBBUTTON;
  tray: TRAYDATA;  //NOTIFYICONDATA;  //
  dwTrayPid: DWORD;
  TrayCount: Integer;
  m_hTrayWnd: HWND;
  i: Integer;
  read: Cardinal;
  dwProcessId: DWORD;
  icon: NOTIFYICONDATA;
  aRes: Integer;
begin
 try
  // Tray ÀÇ À©µµ¿ì ÇÚµé ¾ò±â
  m_hTrayWnd := FindTrayToolbarWindow();
    if m_hTrayWnd = 0 then begin
      Result := False;
   Exit;
    end;
  
  // Tray ÀÇ °³¼ö¸¦ ±¸ÇÏ°í
  TrayCount := SendMessage(m_hTrayWnd, TB_BUTTONCOUNT, 0, 0);
  
  // Tray À©µµ¿ì ÇÚµéÀÇ PID ¸¦ ±¸ÇÑ´Ù
  GetWindowThreadProcessId(m_hTrayWnd, dwTrayPid);
  
    // ÇØ´ç Tray ÀÇ Process ¸¦ ¿­¾î¼­ ¸Þ¸ð¸®¸¦ ÇÒ´çÇÑ´Ù
  m_hProcess := OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwTrayPid);
    if m_hProcess = 0 then begin
      Result := False;
      Exit;
    end;
  
    // ÇØ´ç ÇÁ·Î¼¼½º ³»¿¡ ¸Þ¸ð¸®¸¦ ÇÒ´ç
  m_lpData := VirtualAllocEx(m_hProcess, nil, sizeof(TBBUTTON), MEM_COMMIT, PAGE_READWRITE);
  if m_lpData = nil then begin
      Result := False;
      Exit;
    end;
  
  // Tray ¸¸Å­ »±»±ÀÌ
  for i := TrayCount - 1 downto 0 do begin
      aRes := SendMessage(m_hTrayWnd, TB_GETBUTTON, i, Integer(m_lpData));
   if aRes = 0 then
        Continue; 
   
   // TBBUTTON ÀÇ ±¸Á¶Ã¼¿Í TRAYDATA ÀÇ ³»¿ëÀ» ¾ò±â
   ReadProcessMemory(m_hProcess, m_lpData, @tb, sizeof(TBBUTTON), read);
      ReadProcessMemory(m_hProcess, tb.dwData, @tray, sizeof(tray), read);
           
   // °¢°¢ Æ®·¹ÀÌÀÇ ÇÁ·Î¼¼½º ¹øÈ£¸¦ ¾ò¾î¼­
   dwProcessId := 0;
   GetWindowThreadProcessId(tray.Wnd, dwProcessId);
   
   // Process °¡ ¾ø´Â °æ¿ì TrayIcon À» »èÁ¦ÇÑ´Ù
   if dwProcessId = 0 then begin
    icon.cbSize