Problem (and Fix!)

new topic     » topic index » view thread      » older message » newer message

This was an interesting one (for me anyway!).
I have a program that uses a hidden window (running XP)and just displays a
  popup
menu at the cursor position. I had a problem with it not reliably closing after
a
selection was made from the menu and I also wanted to reduce the startup time.
I first started using the IPC library to find and close any other running
instance(s)
but then I thought why not just reopen the popup menu in the existing instance.
  This kind of worked but had the problem where when the popup was reopened
if the mouse was clicked elsewhere on the screen the popup didn't close itself
as normal - this is due to the owning (hidden) window not being in the
foreground.
In XP setForeground just makes a window flash on the taskbar as this is deemed
more polite now than bringing up the window. So I searched the web and found 
this...

  Under Windows 95 and NT4, if an inactive application calls SetActiveWindow() 
or SetForegroundWindow() using the HWND of one of its windows, this makes the 
application active. The same applies if it calls SetWindowPos() with HWND_TOP 
and SWP_SHOWWINDOW (no need for HWND_TOPMOST windows). These 3 APIs are
basically
equivalent.
  Under ME and XP, this does not happen. Instead the inactive application has
its button highlighted on the windows taskbar but is not made active. Also if
the inactive application calls SetForegroundWindow(), the same thing happens.
  If SetForegroundWindow() is called from an active application (an app with 
the active window), and is passed the HWND of a window in an inactive
application,
it *can* properly activate the other application and the other window. But if
an inactive application calls SetForegroundWindow(), it can't make itself
active.
This applies under all 32 bit versions of Windows.
Therefore the only reliable system of inter-application activations that works
under all versions of Windows is for the currently active application to call
SetForegroundWindow() using the HWND of a window in the other application.	
   
So now I am using the IPC lib to check if the program is already running, and
   if
so then it requests its HWND, uses this to bring the existing instance 
to the foreground, then tells the existing one to reopen its popup and finally
closes down. example code below.

without warning
include win32lib.ew
include ipc.ew
without trace

atom ExistingHwnd
if not ipc_RegisterProcessName("Test Win") then
    ExistingHwnd = ipc_CallFunc("Test Win","GetHwnd",{})
    if ExistingHwnd != -1 then 
if w32Func(xSetForegroundWindow,{ExistingHwnd}) then -- existing instance set
to foreground
ipc_CallProc("Test Win", "ReOpenPopup", {}) -- ask existing instance to
reopen popup
		end if
	end if  
    abort(1)
end if

constant Main =  createEx( Window, "Test Win", 0, 0, 0, 0, 0, WS_POPUP,
WS_EX_TOOLWINDOW),
		MyPopup = create( Menu, "", Main, 0, 0, 0, 0, 0 ),
		item1 = create(MenuItem, "test", MyPopup, 0, 0, 0, 0, 0)

procedure Main_w32HActivate( integer self, integer event, sequence params )
sequence pos
captureMouse( Main )
pos = getPointerPos()
popup( MyPopup, pos[1], pos[2] )
end procedure
setHandler( Main, w32HActivate, routine_id("Main_w32HActivate") )

function GetHwnd()
	return getHandle(Main)
	end function

procedure ReOpenPopup()
sequence pos
setFocus(Main)
	captureMouse( Main )
	pos = getPointerPos()
	popup( MyPopup, pos[1], pos[2] )
	end procedure

ipc_RegisterFunc("GetHwnd",routine_id("GetHwnd"))
ipc_RegisterProc("ReOpenPopup",routine_id("ReOpenPopup"))

WinMain( Main, Normal)


  Sorry for the long winded post but I was pleased to get it working and
thought someone else may find it useful...

 Pete.

new topic     » topic index » view thread      » older message » newer message

Search



Quick Links

User menu

Not signed in.

Misc Menu