Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations gkittelson on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Strange box after issueing ShowWindow API 2

Status
Not open for further replies.

rkolva

Programmer
Jan 16, 2003
127
US
I finally got around to doing something about not allowing the user to run more than one instance of the app at a time. My approach is to iterate processes until I find my exe. Then retrieve the window handle for that ProcessId. Once I have that I use a version of Craig Boyds faq184-4262 code to bring the running process's main window to the foreground and kill the new process. For the most part things work pretty well, still haven't worked out restoring minimized windows yet. But the weird thing is that many times I wind up with a 'box' on the screen that doesn't go away. It's typically in the upper left of the screen and stays on top of everything and anything. It's also whatever happened to be at that spot at the time, desktop, other window, whatever.

Here is roughly the code I'm using:
Code:
FUNCTION MyShowWindow
LPARAMETERS vhWindowHandle AS Integer, viFlag AS Integer

ASSERT !EMPTY(vhWindowHandle) MESSAGE "No arg passed to ProcessClass.ShowWindow"

*IF !THIS.SuppressDebugs THEN
*	DEBUGOUT "ProcessClass.ShowWindow called"
*ENDIF

LOCAL lhForeGroundWindowHandle AS Number, lnForeGroundThreadID AS Number
LOCAL lnTargeWindowThreadID AS Number, llReturn AS Logical 
LOCAL SW_NORMAL AS Integer, liFlag AS Integer 

DECLARE Long BringWindowToTop In Win32API Long
DECLARE Long ShowWindow In Win32API Long, Long
DECLARE INTEGER GetCurrentThreadId IN kernel32 
DECLARE INTEGER GetWindowThreadProcessId IN user32 ;
    INTEGER hWnd, INTEGER @ lpdwProcId  
DECLARE INTEGER GetCurrentThreadId IN kernel32      
DECLARE INTEGER AttachThreadInput IN user32 ;
   INTEGER idAttach, INTEGER idAttachTo, ;
   INTEGER fAttach
DECLARE INTEGER GetForegroundWindow IN user32  
	
   	&& Constants for ShowWindow
*SW_HIDE 		= 0					
SW_NORMAL 		= 1
*SW_SHOWMINIMIZED 	= 2
*SW_SHOWMAXIMIZED 	= 3
*SW_SHOWNOACTIVATE 	= 4
*SW_SHOW 		= 5
*SW_MINIMIZE 		= 6
*SW_SHOWMINNOACTIVE     = 7
*SW_SHOWNA 		= 8
*SW_RESTORE 		= 9
*SW_SHOWDEFAULT 	= 10
llReturn 		= .F.

liFlag 	= IIF(EMPTY(viFlag), SW_NORMAL, CAST( viFlag AS Integer) )

lhForeGroundWindowHandle = GetForegroundWindow() 
lnForeGroundThreadID 	 = GetWindowThreadProcessId( lhForeGroundWindowHandle, 0 ) 
lnTargeWindowThreadID 	 = GetWindowThreadProcessId( vhWindowHandle, 0 ) 
    
IF lnForeGroundThreadID == lnTargeWindowThreadID THEN
	BringWindowToTop( vhWindowHandle )
    ShowWindow( vhWindowHandle, liFlag  )  
ELSE
	AttachThreadInput( lnForeGroundThreadID, lnTargeWindowThreadID, .T. )
    BringWindowToTop( vhWindowHandle )
    ShowWindow( vhWindowHandle, liFlag )   
    AttachThreadInput( lnForeGroundThreadID, lnTargeWindowThreadID, .F. )
ENDIF       

lhForeGroundWindowHandle = GetForegroundWindow() 
IF lhForeGroundWindowHandle == vhWindowHandle THEN
	llReturn = .T.
ENDIF
   
CLEAR DLLS BringWindowToTop, ShowWindow, GetCurrentThreadId, GetWindowThreadProcessId
CLEAR DLLS AttachThreadInput, GetForegroundWindow, GetCurrentThreadId  

RETURN llReturn

Any ideas what that box is and how I handle it?

Thanks,

Ralph Kolva
 
Ralph

This doesn't answer your question but does provide a simple alternative
Code:
[COLOR=blue]LOCAL llQuit[/color][COLOR=green]    
*!* Check for instance(s) of Myapp running[/color][COLOR=blue]
oManager = GETOBJECT([winmgmts:])
cQuery = [select * from win32_process where name='myapp.exe']
oResult = oManager.ExecQuery(cQuery)

IF oResult.Count > 1
    llQuit = .T.
ENDI[/color][COLOR=green]
*!* Clean up[/color][COLOR=blue]
oManager = .NULL.
oResult = .NULL.
RELEASE cQuery, oResult, oManager

IF llQuit[/color][COLOR=green] && Myapp.exe running twice[/color][COLOR=blue]
    QUIT
ENDI[/color]


FAQ184-2483 - answering getting answered.​
Chris [pc2]
PDFcommandertm.net
PDFcommandertm.com
 
Thanks Chris,

Your code is a bit shorter than what I'm currently using to find multiple processes iterating through the CreateToolhelp32Snapshot API function. Are there any detriments to using winmgmts instead of API? If you don't mind I may include your code in my class as well, I will obviously give you credit in the method header.

Once I find the other process I wanted to bring that to the foreground instead of leaving it hidden and just killing the new process. My thinking as this would be more intuitive than making them find the other instance.

Does anybody know if there is another way to bring a process to the foreground other than the ShowWindow API?

Thanks again Chris,

Ralph Kolva
 
Been playing around with WMI since your post Chris. I'm curious and confused. MSDN documentation has the following warning on the WMI Provider class:

Note The Provider class is part of the WMI Provider Framework. The Provider Framework classes are obsolete and not recommended. See Using WMI for the preferred ways to write a WMI COM provider or a WMI provider that uses the .NET Framework System.Management namespaces.

Is the ExecQuery method a part of the Provider class? Should we avoid using this?

Getting to the Process properties is definately cleaner using WMI

Code:
SET DEBUGOUT TO 'properties.txt'

oManager = GETOBJECT([winmgmts:])
cQuery = [select * from win32_process where name='firefox.exe']
oResult = oManager.ExecQuery(cQuery)

FOR EACH oProcess IN oResult 
	FOR EACH oProperty IN oProcess.Properties_ 
		DEBUGOUT  oProperty.name + ":  " + TRANSFORM(oProperty.value)
		
	NEXT 
NEXT

SET DEBUGOUT TO

I think you deserve a star for pointing me towards an interesting aspect of Windows even if it doesn't get me exactly what I was looking for. I'll keep exploring, there has to be another way of getting the other instance to the foreground.

Thanks again,

Ralph Kolva
 
Mike, Ralph

Thanks for the stars

Was unaware, Ralph, of that MSDN documentation on the WMI Provider class, and am not qualified to comment on it.

Assuming you can get the hwnd of the other process, you should be able to use the SetForegroundWindow() WinAPI call to achieve what you want.

FAQ184-2483 - answering getting answered.​
Chris [pc2]
PDFcommandertm.net
PDFcommandertm.com
 
I tried SetForeGroundWindow alone and no luck which isn't surprising given what MSDN states about the change since Win 95. But if I change the call from ShowWindow to SetForeGroundWindow after attaching my process to the foreground process it does eliminate the funky window thing I was getting.

Now I need to work on getting the other process to the foreground if it's been minimized.

So thank's for pointing me to at least try the setForeGroundWindow API and for the more conicse code for finding the processID. I'll try some bench mark tests and see which way I want to go.

Thanks again and the WMI does make a good Faq.

Ralph Kolva
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top