Set Multiple

Peterg
Posts: 62
Joined: Mon Nov 28, 2005 5:36 pm
Location: Oxford UK
Contact:

Set Multiple

Post by Peterg »

Hi all
If I call SetMultiple(.F.) at the tope of my main function this does not prevent my app from running more than once on the same PC

Is there something else that I should be doing

Thanks
Peter
User avatar
driessen
Posts: 1239
Joined: Mon Oct 10, 2005 11:26 am
Location: Genk, Belgium

Post by driessen »

Peter,

You could add this code at the beginning of your main function :

Code: Select all

IF IsExeRunning(cFileName(HB_ARGV(0)))
   MsgAlert("Your application is already running !","Attention")
   Quit
ENDIF
This function tests if your current application is already running on your system.

Good luck.
Last edited by driessen on Thu Nov 22, 2007 3:41 pm, edited 1 time in total.
Regards,

Michel D.
Genk (Belgium)
_____________________________________________________________________________________________
I use : FiveWin for (x)Harbour v. 21.01 - Harbour 3.2.0 (October 2020) - xHarbour Builder (January 2020) - Bcc7
Peterg
Posts: 62
Joined: Mon Nov 28, 2005 5:36 pm
Location: Oxford UK
Contact:

Post by Peterg »

Many thanks that works well
User avatar
Otto
Posts: 4470
Joined: Fri Oct 07, 2005 7:07 pm
Contact:

Post by Otto »

What do you pass as cFileName - the name of the EXE or the Title of the window? Does it work if the exe is minimized?
Regards,
Otto
User avatar
Antonio Linares
Site Admin
Posts: 37481
Joined: Thu Oct 06, 2005 5:47 pm
Location: Spain
Contact:

Post by Antonio Linares »

Otto,

The parameter is HB_ARGV(0) which it is the name and path of the EXE
regards, saludos

Antonio Linares
www.fivetechsoft.com
User avatar
Enrico Maria Giordano
Posts: 7355
Joined: Thu Oct 06, 2005 8:17 pm
Location: Roma - Italia
Contact:

Post by Enrico Maria Giordano »

Otto wrote:What do you pass as cFileName
Please note that cFileName() is a function.

EMG
User avatar
James Bott
Posts: 4654
Joined: Fri Nov 18, 2005 4:52 pm
Location: San Diego, California, USA
Contact:

Post by James Bott »

This works similar to the old 16bit way; if the EXE is already running it maximizes it and brings it to the foreground.

James

9/15/2005 5:28 PM
Run only 1 instance of an exe

Code: Select all

// Author: "hua" <tomyam At rocketmail Dot com>

 function main()
  if AlreadyRunning()
     return
  endif
  .
  .
return
/**************************************************************************

  If an exe is already running, bring window to front and maximize it.

  NOTE: Though the exe is the same, but if it's being run from a different
        path, they're considered different exe when using this routine.
*********/
#include "fivewin.ch"
#define GW_HWNDFIRST     0
#define GW_HWNDLAST         1
#define GW_HWNDNEXT         2
#define GW_HWNDPREV         3
#define GW_OWNER         4
#define GW_CHILD         5

#define SW_SHOWMAXIMIZED 3

function AlreadyRunning()
  local lRet := .f., cMod := hb_Argv( 0 ), hWnd
  if isExeRunning( cFileName( cMod ) )
     hWnd := findWindowByModuleFilename( cMod )
     setForeGroundWindow(hWnd)
     showWindow( hWnd, SW_SHOWMAXIMIZED)
     lRet := .t.
  endif
return lRet
//----------------------------------------------------------------------
static function FINDWINDOWBYMODULEFILENAME( cModuleFileName )

    LOCAL hWnd := getForegroundWindow(), cFile, hRet

    while hWnd != 0
        cFile := getWindowModuleFilename( hWnd )
        cFile := left(cFile, len(cFile)-1) // remove null-termination char
        IF cFile == cModuleFileName
           hRet := hWnd
           exit
        ENDIF

        hWnd := getWindow( hWnd, GW_HWNDNEXT )
    enddo
return hRet
//--------------------------------------------------------------------------
DLL32 FUNCTION GETFOREGROUNDWINDOW() AS LONG;
      PASCAL FROM "GetForegroundWindow" LIB "user32.dll"
//--------------------------------------------------------------------------
#pragma BEGINDUMP

#include "windows.h"
#include "hbapi.h"

HB_FUNC( GETWINDOWMODULEFILENAME ) // ( hWnd ) --> cFileName
{
    char szFileName[ 256 ];

    UINT wChar = GetWindowModuleFileName( ( HWND ) hb_parnl( 1 ),
szFileName, 256 );

    hb_retclen( szFileName, wChar );
}

#pragma ENDDUMP
User avatar
Otto
Posts: 4470
Joined: Fri Oct 07, 2005 7:07 pm
Contact:

Post by Otto »

Thanks to all. Thank you James.

I was too quick with my question.
What I search is a method to bring the running prg to the forground.

At the moment I do the task the following way but I thought there would be a better method without a fix coded Window title - as I check for a previous exe before I create the main window.


if IsExeRunning( cFileName( HB_ARGV( 0 ) ) )
ShowApplication()
else
/*
Main Programm
********** -> On first start of the program I write oWnd:cTitle() to a ini-file.
*/
endif

Then I test with IsExeRunning and if YES
I call function ShowApplication
in the FindWnd() function I use the Window-title which is stored in the Ini-file.

I will try as James suggested with FINDWINDOWBYMODULEFILENAME in stet of FindWnd().
User avatar
Richard Chidiak
Posts: 946
Joined: Thu Oct 06, 2005 7:05 pm
Location: France
Contact:

Post by Richard Chidiak »

Otto

This is a sample

#include "FiveWin.ch"

#define GW_CHILD 5
#define GW_HWNDNEXT 2

function Main()

local oWnd

if IsExeRunning( cFileName( HB_ARGV( 0 ) ) )
ShowApplication()
else
DEFINE WINDOW oWnd TITLE "Test"

ACTIVATE WINDOW oWnd
endif

return nil

function ShowApplication()

local hWnd := FindWnd( cFileNoExt( HB_ARGV( 0 ) ) )

if hWnd != nil
SetForeGroundWindow( hWnd )
endif

return nil

function FindWnd( cTitle )

local hWnd := GetWindow( GetDesktopWindow(), GW_CHILD )

while hWnd != 0
if Upper( cTitle ) $ Upper( GetWindowText( hWnd ) )
return hWnd
endif

hWnd = GetWindow( hWnd, GW_HWNDNEXT )
end

return nil
http://www.cbati.com

Uestudio
Fwh 13.05 Harbour 3.2 MSVC 2013
User avatar
Otto
Posts: 4470
Joined: Fri Oct 07, 2005 7:07 pm
Contact:

Post by Otto »

Thank you Richard. Does this work on minimized?
I tested your code but it does not bring a minimized window to the foreground.
This is my test:
FindWnd1 is your code

FindWnd1
hWnd = 36700336 and cTitle = xRechnung
FindWnd the way with INI-file
hWnd=38732612 and cTitle = W i n H o t e l * 2007-Juni Demo - Computer-Nr: 5
This way it works. I use Vista.

function FindWnd1( cTitle )
local hWnd := GetWindow( GetDesktopWindow(), GW_CHILD )
msginfo(cTitle )
while hWnd != 0
if Upper( cTitle ) $ Upper( GetWindowText( hWnd ) )
return hWnd
endif
hWnd = GetWindow( hWnd, GW_HWNDNEXT )
end
return nil


function FindWnd( cTitle )
local hWnd := GetWindow( GetDesktopWindow(), GW_CHILD )
msginfo(cTitle )
while hWnd != 0
if Upper( cTitle ) $ Upper( GetWindowText( hWnd ) )
return hWnd
endif
hWnd = GetWindow( hWnd, GW_HWNDNEXT )
end
return nil
User avatar
James Bott
Posts: 4654
Joined: Fri Nov 18, 2005 4:52 pm
Location: San Diego, California, USA
Contact:

Post by James Bott »

I found a bug in the code I posted above. This line:

Code: Select all

        cFile := left(cFile, len(cFile)-1) // remove null-termination char 
Apparently there is no null-termination character so it is truncating the name by one character and this the funcion is returning hWnd as nil always. I fixed it like this:

Code: Select all

if right( cFile, 1) == chr(0)
   cFile := left(cFile, len(cFile)-1) // remove null-termination char 
endif
So hWnd is found.

However setForegroundWindow() window doesn't appear to do anything. I researched this via Google and it seems that you have to call allowSetForegroundWindow() first, but xHarbour does not have this function. I found it in xHarbour\contrib\what32\source\_winwnd.c and I cut and pasted it into the test program. But still no luck. Anyone have any ideas?

James

Code: Select all

#pragma BEGINDUMP


#ifndef ASFW_ANY
  #define ASFW_ANY    ((DWORD)-1)
#endif

HB_FUNC( ALLOWSETFOREGROUNDWINDOW )
{

   HINSTANCE h = LoadLibraryEx( "user32.dll", NULL, 0 );
   BOOL bASFWRet = (BOOL) FALSE ;
   DWORD dwProcessId = ISNIL( 1 ) ? ASFW_ANY : (DWORD) hb_parnl( 1 );

   if( h )
   {
      typedef BOOL (WINAPI *xbAllowSetForegroundWindow)( DWORD dwProcessId );
      xbAllowSetForegroundWindow pfnASFW = (xbAllowSetForegroundWindow)
      GetProcAddress( h, "AllowSetForegroundWindow") ;

      if( pfnASFW )
      {
         bASFWRet = (BOOL) pfnASFW( dwProcessId ) ;
      }

      FreeLibrary( h );
   }

   hb_retl( bASFWRet );
}
#pragma ENDDUMP
User avatar
James Bott
Posts: 4654
Joined: Fri Nov 18, 2005 4:52 pm
Location: San Diego, California, USA
Contact:

Post by James Bott »

I forgot to mention that oWnd:hWnd and findWindowByModuleFilename( cMod ) don't have the same value. I would think that they should. Perhaps we are sending the wrong hWnd to setForeground()?

James
User avatar
Enrico Maria Giordano
Posts: 7355
Joined: Thu Oct 06, 2005 8:17 pm
Location: Roma - Italia
Contact:

Post by Enrico Maria Giordano »

Otto wrote:What do you pass as cFileName - the name of the EXE or the Title of the window? Does it work if the exe is minimized?
Regards,
Otto
Try this:

Code: Select all

#include "Fivewin.ch"


FUNCTION MAIN()

    LOCAL oWnd

    LOCAL cTitle := "This is a test"

    IF ISEXERUNNING( CFILENAME( HB_ARGV( 0 ) ) )
        SHOWWINDOW( FINDWINDOW( 0, cTitle ), 9 )
        SETFOREGROUNDWINDOW( FINDWINDOW( 0, cTitle ) )
        RETURN NIL
    ENDIF

    DEFINE WINDOW oWnd;
           TITLE cTitle

    ACTIVATE WINDOW oWnd

    RETURN NIL
EMG
User avatar
James Bott
Posts: 4654
Joined: Fri Nov 18, 2005 4:52 pm
Location: San Diego, California, USA
Contact:

Post by James Bott »

Enrico,

Your function works. I note that FindWindow() and oWnd:hWnd have the same value. I don't know why the findWindowByModuleFilename( cMod ) in the code I posted doesn't return the same value as oWnd:hWnd.

There are issues when using the window title. If you have a folder open with the same name, then it can get confused. I expect this is not a big issue as normally a user wouldn't have the folder open, but it did happen to me when testing.

Also, what if you are running a MDI application and the name changes when you open a MDI child. Does it still find a match even though the complete titles are different?

James
User avatar
Enrico Maria Giordano
Posts: 7355
Joined: Thu Oct 06, 2005 8:17 pm
Location: Roma - Italia
Contact:

Post by Enrico Maria Giordano »

Try this other:

Code: Select all

#include "Fivewin.ch"


FUNCTION MAIN()

    LOCAL oWnd

    LOCAL cTitle := "This is a test"

    IF ISEXERUNNING( CFILENAME( HB_ARGV( 0 ) ) )
        SHOWWINDOW( FINDWND( cTitle ), 9 )
        SETFOREGROUNDWINDOW( FINDWND( cTitle ) )
        RETURN NIL
    ENDIF

    DEFINE WINDOW oWnd;
           TITLE "Prefix - " + cTitle + " - Postfix"

    ACTIVATE WINDOW oWnd

    RETURN NIL


#define GW_HWNDFIRST 0
#define GW_HWNDLAST  1
#define GW_HWNDNEXT  2
#define GW_HWNDPREV  3
#define GW_OWNER     4
#define GW_CHILD     5


FUNCTION FINDWND( cTitle )

    LOCAL hWnd := GETWINDOW( GETDESKTOPWINDOW(), GW_CHILD )

    WHILE hWnd != 0
        IF UPPER( cTitle ) $ UPPER( GETWINDOWTEXT( hWnd ) )
            RETURN hWnd
        ENDIF

        hWnd = GETWINDOW( hWnd, GW_HWNDNEXT )
    ENDDO

    RETURN NIL
EMG
Post Reply