Pastey RefreshTaskbarNotificationArea



--eu41-structs using memstruct, 
-- refresh systray & list tool tips of all eventually
--
--Refreshing the Taskbar Notification Area in Xp 32
--http://www.computersecurityarticles.info/security/refreshing-the-taskbar-notification-area/#comments

--Query the System Tray Using Interprocess Memory Communication
--http://www.freevbcode.com/ShowCode.Asp?ID=3291

--delphi code from
--???/removing-an-icon-from-the-systray-2251254.htm

include std/dll.e
include std/machine.e
include std/math.e 

public constant 
	C_BYTE = C_UCHAR,
	C_BOOL = C_INT,
	C_WORD = C_USHORT,
	C_DWORD=  C_ULONG,
	C_WPARAM = C_UINT,
	C_LPARAM = C_ULONG,
	C_HANDLE = C_POINTER,
	C_HWND = C_POINTER,
	C_DWORDLONG = C_DOUBLE,
	$

public constant 
	user32 = open_dll("user32.dll"),
	kernel32 = open_dll("kernel32.dll"),
	$

public constant 
  WM_MOUSEMOVE = #0200,
  SM_CXSMICON = 49,
  SM_CYSMICON = 50,
	--
  xSendMessage = define_c_func(user32, "SendMessageA"
          , {C_HWND, C_UINT, C_WPARAM , C_LPARAM}, C_LONG ),
  -- LRESULT SendMessage(
    -- HWND hWnd,      // handle of destination window
    -- UINT Msg,       // message to send
    -- WPARAM wParam,  // first message parameter
    -- LPARAM lParam   // second message parameter
   -- );       
	--
  xEnumWindows = define_c_func(user32, "EnumWindows", {C_POINTER, C_LPARAM}, C_BOOL),
 -- BOOL EnumWindows(
    -- WNDENUMPROC lpEnumFunc, // pointer to callback function
    -- LPARAM lParam   // application-defined value
   -- );
	--
 -- BOOL CALLBACK EnumWindowsProc(
    -- HWND hwnd,      // handle to parent window
    -- LPARAM lParam   // application-defined value
   -- );
	--
 xGetClientRect = define_c_func(user32, "GetClientRect", {C_HWND, C_POINTER}, C_BOOL),
	-- 	BOOL GetClientRect(
	-- 
	-- 	    HWND hWnd,	// handle of window
	-- 	    LPRECT lpRect 	// address of structure for client coordinates
	-- 	);	
	--
	xFindWindowA = define_c_func(user32, "FindWindowA", {C_POINTER,C_POINTER}, C_POINTER),
	--
	xFindWindowEX = define_c_func( user32, "FindWindowExA", {C_HWND, C_HWND, C_POINTER, C_POINTER}, C_HWND),
	-- 	HWND FindWindowEx(
	-- 	    HWND hwndParent,	// handle to parent window
	--     	HWND hwndChildAfter,	// handle to a child window 
	-- 	    LPCTSTR lpszClass,	// pointer to class name
	-- 	    LPCTSTR lpszWindow	// pointer to window name
	--    );	
	--
 xGlobalAddAtom  = define_c_func( kernel32, "GlobalAddAtom", {C_POINTER}, C_POINTER),
	-- ATOM GlobalAddAtom(
	-- 
	--     LPCTSTR lpString 	// pointer to the string to add 
	--    );	
	--
 xGlobalDeleteAtom  = define_c_func( kernel32, "GlobalDeleteAtom", {C_POINTER}, C_POINTER),
	-- ATOM GlobalDeleteAtom(
	-- 
	--     ATOM nAtom 	// atom to delete  
	--    );	
 xGetSystemMetrics = define_c_func(user32,"GetSystemMetrics"
            ,{C_INT},C_INT),
 $
 
public function GlobalAddAtom(object lpString)
	if sequence(lpString) then allocate_string(lpString, 1) end if
	return c_func(xGlobalAddAtom, {lpString} )
end function

public function GlobalDeleteAtom(atom nAtom)
	return c_func(xGlobalDeleteAtom, {nAtom} )
end function

public function GetSystemMetrics(integer nIndex)
    --~  2 (or 3) monitors
    --~ gcxScreenMax = GetSystemMetrics(SM_CXSCREEN) - 1
    --~ gcyScreenMax = GetSystemMetrics(SM_CYSCREEN) - 1
    --SM_CLEANBOOT  Value that specifies how the system was started:0  Normal boot1  Fail-safe boot2  Fail-safe with network bootFail-safe boot (also called SafeBoot) bypasses the user's startup files.


 return c_func(xGetSystemMetrics,{nIndex})
end function


public function SendMessage(
	atom hWnd -- handle of destination window
	,atom Msg --message to send
	,atom wParam -- first message parameter
	,object lParam --second message parameter  sometimes string
	) 
 	--If hWnd is HWND_BROADCAST then sends to all windows except child.
	-- PostMessage function, in contrast, posts a message to a thread's message queue and returns immediately
	if sequence(lParam) then lParam = allocate_string(lParam,1) end if
	return c_func(xSendMessage,{hWnd, Msg,  wParam, lParam})

end function

--**
-- 
public function EnumWindows(atom lpEnumFunc,atom lParam)
   return c_func(xEnumWindows, {lpEnumFunc,lParam} )
end function


-- 
public function FindWindowA(object lpClassName, object lpWindowName)
   return c_func(xFindWindowA,{allocate_string(lpClassName,1),allocate_string(lpWindowName,1)})
end function

-- 
public function FindWindowEX(
	object hwndParent,
	object hwndChildAfter,
	object lpszClass,
	object lpszWindow
	)
   return c_func(xFindWindowEX, {
   			hwndParent,
   			hwndChildAfter,
			allocate_string(lpszClass,1),
			allocate_string(lpszWindow,1)
			})
end function
	

public function GetClientRect(atom hWnd, atom lpRect)
   return c_func(xGetClientRect,{hWnd,lpRect})
end function



memstruct RECT
	long left
	long top
	long right
	long bottom
end memstruct 


-- memstruct _NOTIFYICONDATA --{ // nid  
--     DWORD cbSize; 
--     HWND hWnd; 
--     UINT uID; 
--     UINT uFlags; 
--     UINT uCallbackMessage; 
--     HICON hIcon; 
--     char szTip[64]; 
-- end memstruct --} NOTIFYICONDATA, *PNOTIFYICONDATA; 

-- 	uFlags
-- 	Array of flags that indicate which of the other members contain valid data. This member can be a combination of these values:
-- 	NIF_ICON	The hIcon member is valid. 
-- 	NIF_MESSAGE	The uCallbackMessage member is valid.
-- 	NIF_TIP	The szTip member is valid.


--#define FW(x,y) FindWindowEx(x, NULL, y, L”")  --a unicode quote
--
public function FW(atom x, sequence y)
	return FindWindowEX(x, NULL, y, "")
end function

procedure RefreshTaskbarNotificationArea()
    atom hNotificationArea  --HWND_

	atom r = allocate( sizeof( RECT ) ) 
	--atom LToolbarWindow32 = ”ToolbarWindow32?
	sequence LToolbarWindow32 = "ToolbarWindow32"
	sequence LNotification_Area = "Notification Area"
	--atom LShell_TrayWnd = "Shell_TrayWnd"
	sequence LShell_TrayWnd = "Shell_TrayWnd"
	sequence LTrayNotifyWnd = "TrayNotifyWnd"
	sequence LSysPager = "SysPager"

	hNotificationArea = 
		FindWindowEX(
			FW(
				FW(
					FW(NULL
						, LShell_TrayWnd)
					, LTrayNotifyWnd)
				, LSysPager),
			NULL,	--NULL,
			LToolbarWindow32,
			LNotification_Area)

	GetClientRect(hNotificationArea, r)
    
	-- 	--for (LONG x = 0; x < r.right; x += 5)
	-- 	atom rr = r.RECT.right
	-- 	for x = 0 to rr by 5 do
	-- 		--for (LONG y = 0; y < r.bottom; y += 5)
	-- 		atom rb = r.RECT.bottom
	-- 		for y = 0 to rb by 5 do
	--             SendMessage(
	--                 hNotificationArea,
	--                 WM_MOUSEMOVE,
	--                 0,
	--                 shift_bits( y,-16 ) + x)  --(y << 16) + x)
	-- 
	-- 
	-- 		end for
	-- 	end for

	integer w = GetSystemMetrics(SM_CXSMICON)
	integer h = GetSystemMetrics(SM_CYSMICON)
	-- initial y position of mouse - half of height of icon
	integer y = shift_bits( w, -1)
	while y < r.RECT.bottom do -- while y < height of tray
		integer x = shift_bits( h, 1)  --initial x position of mouse - half of width of icon
		while x < r.RECT.right do -- while x < width of tray
			--simulate moving mouse over an icon
            SendMessage(
                hNotificationArea,
                WM_MOUSEMOVE,
                0,
                shift_bits( y, -(16 + x) )  --(y shl 16 or x)  negitive is left
				)

			--need to somehow get which icon is under the curser
			--GetDlgItemText(hDlg, uTip, szTip, sizeof(szTip)


			x = x + w	--add width of icon to x position
		end while
		y = y + h --add height of icon to y position
	end while


end procedure 

RefreshTaskbarNotificationArea()


1. Comment by ne1uno Jul 21, 2011

should be shift_bits( y, -16 ) + x

in the link pete added http://www.codeguru.com/forum/showthread.php?t=507636 one of the commenters says just sending mouse move to the notification area is sufficent to refresh. another suggested adding then removing an icon.

ref:http://openeuphoria.org/forum/115974.wc

2. Comment by ne1uno Jul 21, 2011

integer y = shift_bits( w, 1)

3. Comment by petelomax Jul 23, 2011

(y*#10000 + x) is easier IMO to understand than shift_bits. In the C code that Matt posted (cmiiw) it is trying to "draw" a series of vertical lines with the mouse from, whereas yours appears to be "draw" a series of horizontal lines. Just curious whether that was a deliberate change.

4. Comment by ne1uno Jul 24, 2011

the mouse part is from a similar post but for delphi code. it makes more sense to try and target the icon centers. it also appears you can obtain the HWND directly by finding child windows of the notification area.

shifting for multiplication and division may not be clear to everyone, but shifting to pack bytes should be. maybe euphoria will have shift operators one day.