Page 1 of 1

Running program needs name of clicked file icon

Posted: Fri Feb 20, 2009 10:19 am
by RichardL
When a user clicks on an icon of a particular file type I wanted my program to run and process the file. Achieved.

I can only have one instance of the program running otherwise the many communications systems linked into it will fall over. Achieved.

Now, to be very tidy I would like my already running program to become aware of the user clicking on a file of the type that would normally have launched it.

I have written a skeleton program to experiment with and that can be used as follows:

Compile Test.pb to c:\temp\Test.exe
Make a shortcut to test.exe on the desktop
Run test.exe from the shortcut, window opens OK.
Run again from the icon, declined as designed, with a courteous message.
Close first instance of test.exe

Associate a file type with test.pb by right clicking on a representative file icon on the desktop and selecting ‘open with’ then ‘Choose file’, selecting ‘c:\Test.exe’ and ‘Always use…’
Click on the file icon and Test.exe opens OK and is aware of the file to be processed.
Click on file icon again and a second instance of test.exe knows of the file OK and declines to proceed.

Question:
How can the first (only one allowed) instance of the program be aware of a second ‘associated-file’ being clicked on?

This is not a critical path problem, but it’s got me bugged and I am going round in circles :? trying to think of a solution, probably involving the Process library.

Any suggestions are most welcome.
RichardL

Code: Select all

; <Test.pb> Purebasic 4.30

File$ = Trim(ProgramParameter())

;/ Prevent more than one instance of this program from running
Prog$ = "Test.exe"
If CreateMutex_(0,1,Prog$)=0 Or GetLastError_()<>0 
  Beep_(3000,100)
  MessageRequester("Please be advised...","<"+Prog$+"> is already running."+Chr(10)+"Sorry <"+File$+"> will be ignored")
  ; *************************************************************
  ; Could the new File$ be passed to the already running program?
  ; *************************************************************
  End 
EndIf

;/ Declarations
Declare.l myCallback(WindowID, message, wParam, lParam)

;/ Lots of initialising, reading INI files etc goes here
SetWindowCallback(@myCallback())

;/ Make input dialogue etc
MyWindow = OpenWindow(#PB_Any,100,100,500,200,"Test window")
Call = TextGadget(#PB_Any,30,30,150,20,"")


;/ Look for a data file name passed to the program 
; ; This will happen if:- 
; (a) A file type has previously been associated with this program.
; (b) User clicked on a file of the specified type
; 
If File$
  MessageRequester("I have a file to process","File name <"+File$+">")
  ; Process the file here, just like it was loaded with the menu option File/Load
EndIf


;/ Simplified main event loop, waiting for Asyn comms and user events

SetGadgetText(Call,"Anyone there?")
Quit = #False
Repeat
  
  ; Wait for comms inputs or user inputs
  Repeat
    ; Check for remote radio input
    If MMMonFlag.l 
      ; Process serial port 1 comms here
    EndIf
    
    ; Check for local data serial input
    If TM_MonitorFlag.l         
      ; Process local data input here
    EndIf
    
    ; Check for keyboard mouse etc....
    Delay(1)                    ; Allow other applications... Windows Task Manager shows apprx 0% CPU loading!
    EventID.l = WindowEvent()   ; Check for a Window event, NO WAIT
    
  Until EventID
  

  Select EventID
      
    Case #PB_Event_CloseWindow
      If EventWindow()= MyWindow
        Quit = #True
      EndIf
      
      ; ************************************************
      ; How do I detect a user clicking on another file
      ; of the same type that was detected at start up?
      ; ************************************************
      
    Case #WM_DROPFILES   ; File dropped on app
      
      
  EndSelect
  
Until Quit 

;/ Save INI file etc...
End

Procedure.l myCallback(WindowID, message, wParam, lParam) 
  Static PrimeRedraw.l
  
  Result = #PB_ProcessPureBasicEvents 
  Select message
      
      ; ******************************
      ; Or maybe something can go here
      ; ******************************
      
  EndSelect
  
  ProcedureReturn Result
EndProcedure



Posted: Fri Feb 20, 2009 11:05 am
by srod
#WM_COPYDATA is a relatively easy way for the second instance of your program to forward any command line parameters etc. All you need do is secure the handle of the main window in the already running first instance. For this, see Freak's remarks in the following thread : http://www.purebasic.fr/english/viewtop ... wmcopydata

Netmaestro posted an excellent example of using #WM_COPYDATA : http://www.purebasic.fr/english/viewtop ... wmcopydata

Posted: Fri Feb 20, 2009 5:13 pm
by RichardL
Thank you Stephen,

I managed to get a working system using the #WM_COPYDATA method. Neat, sweet and petite!

It was not as simple as it could have been because the name of the window gets fiddled with so it includes things like user site and timezone.
Fortunately the name always starts with a recognizable feature. I got this sorted using EnumWindows()....

Success :D :D

RichardL