Begging bowl time for José Roca <smile>

Windows specific questions.
Post Reply
deltarho[1859]
Posts: 4310
Joined: Jan 02, 2017 0:34
Location: UK
Contact:

Begging bowl time for José Roca <smile>

Post by deltarho[1859] »

@Josep Roca

Hi, José, I am experiencing one of my hair pulling out periods again and hoping you can help me out.

I am using this Function

Code: Select all

Function InstanceTest() As Long
Dim hMutex As Handle
Dim ThisApp As Wstring * Max_Path
Dim LastError As Long
 
  ThisApp = "WinFBE64-2.1.3" ' tried "WinFBE64-2.1.3.exe" to no avail
 
  hMutex = CreateMutexW( ByVal Null, ByVal Null, VarPtr(ThisApp) )
  LastError = GetLastError
  If hMutex <> 0 Then
    If LastError = Error_Already_Exists Then
      Function = FALSE
    Else
      Function = TRUE
    End If
  Else
    ThisApp = "Mutex Create failed with error code" + Str(LastError)
    Messagebox( Byval NULL, ThisApp, "Cswitches2", MB_OK )
    Function = FALSE
  End If
End Function

In WndProc I have

Code: Select all

Select Case uMsg
 
  Case WM_CREATE
    SetTimer( hDlg, IDC_Timer, 5000, null ) ' 5000 to allow me to watch
 
  Case WM_TIMER
    If InstanceTest = 0 Then
      Print "Here"
      Sleep 1000                            ' 1000 to allow me to watch
      KillTimer hDlg, IDC_Timer
      PostQuitMessage(0)
      Exit Function
    End If
The problem I have is that I get "Here" in the console window whether "WinFBE64-2.1.3" is running or not.

What I want is for my application to close when "WinFBE64-2.1.3" closes and not before.

When running "WinFBE64-2.1.3.exe" shows in "Process Explorer"

On the face of it, it would seem that there is something wrong with InstanceTest() but I cannot see it.
Josep Roca
Posts: 564
Joined: Sep 27, 2016 18:20
Location: Valencia, Spain

Re: Begging bowl time for José Roca <smile>

Post by Josep Roca »

Apparently you think that creating a mutex with the name of the editor will allow you to know if it is running or not, but this will fail if the editor has not created an identical mutex and it is keeping it active.

As the editor uses "WinFBE_Class" as its class name, the easiest way is to use FindWindowW:

IF FindWindowW("WinFBE_Class", NULL) <> NULL THEN ''' it is running

BTW the place to put PostQuitMessage(0) is in the processing of the WM_DESTROY message, so remove it from WM_TIMER and place it in WM_DESTROY. To end the program, instead of using PostQuitMessage(0) in WM_TIMER, use DestroyWindow(hDlg). DestroyWindow will destroy the main window and child controls and send a WM_DESTROY message.
Last edited by Josep Roca on Apr 25, 2020 22:30, edited 1 time in total.
jj2007
Posts: 2326
Joined: Oct 23, 2016 15:28
Location: Roma, Italia
Contact:

Re: Begging bowl time for José Roca <smile>

Post by jj2007 »

Josep Roca wrote:To end the program, instead of using PostQuitMessage(0) in WM_TIMER, use DestroyWindow(hDlg)
DestroyWindow is a bit rude. Normally, I use Sendmessage(hWnd, WM_CLOSE, 0, 0). Thus, the program can show a MessageBox in case there is something to save before closing.
deltarho[1859]
Posts: 4310
Joined: Jan 02, 2017 0:34
Location: UK
Contact:

Re: Begging bowl time for José Roca <smile>

Post by deltarho[1859] »

Wow!

I looked at FindWindow but I didn't know what lpClassName was.

Thanks, José

I was going to ask about PostQuitMessage because I was not happy with what I did there.
jj2007 wrote:in case there is something to save before closing.
I actually trap SC_CLOSE and check if the window has been moved and if it has then its new location is saved. However, that covers the window's close button, so I repeated the code in WM_CLOSE, which I had not used, to collect your message.

Thanks, Jochen.

When WinFBE opens it invokes 'SetCompilerSwitchesII' and 'SetCompilerPathsII' by Paul's additional action added to WinFBE 2.07 and later. However, on closing WinFBE I had to close the other two exes as with everyone else who use those user tools. Now we don't - they both close automatically when WinFBE closes. Fantastic!

I come up with some good ideas but often they are beyond my capabilities to code. After pulling my hair out for some time within just over an hour of 'throwing the towel in' and coming here I could do what I wanted in a matter of minutes.

Paul should be pleased because your help has just given WinFBE another 'leg up'.

I now have a couple of updates to publish - but not before a cup of tea. Image

Thanks again, guys.
jj2007
Posts: 2326
Joined: Oct 23, 2016 15:28
Location: Roma, Italia
Contact:

Re: Begging bowl time for José Roca <smile>

Post by jj2007 »

deltarho[1859] wrote:I looked at FindWindow but I didn't know what lpClassName was.
Have a look at WinID: https://dennisbabkin.com/winid/

Tiny little helper, extremely useful for Windows GUI programming.
deltarho[1859]
Posts: 4310
Joined: Jan 02, 2017 0:34
Location: UK
Contact:

Re: Begging bowl time for José Roca <smile>

Post by deltarho[1859] »

Thanks, Jochen.

WinID has just told me that WinFBE uses "WinFBE_Class" as its class name. Nice one!
Josep Roca
Posts: 564
Joined: Sep 27, 2016 18:20
Location: Valencia, Spain

Re: Begging bowl time for José Roca <smile>

Post by Josep Roca »

jj2007 wrote:
Josep Roca wrote:To end the program, instead of using PostQuitMessage(0) in WM_TIMER, use DestroyWindow(hDlg)
DestroyWindow is a bit rude. Normally, I use Sendmessage(hWnd, WM_CLOSE, 0, 0). Thus, the program can show a MessageBox in case there is something to save before closing.
Me too, but according David's post he wanted to end the application inconditionally if the editor wasn't running.
adeyblue
Posts: 300
Joined: Nov 07, 2019 20:08

Re: Begging bowl time for José Roca <smile>

Post by adeyblue »

You also don't need to poll in a timer - SetWinEventHook(EVENT_OBJECT_DESTROYED, EVENT_OBJECT_DESTROYED, ...) will get you a notification when the apps process/thread destroys windows (including children, so you'll need to check the notification is for the main window).
deltarho[1859]
Posts: 4310
Joined: Jan 02, 2017 0:34
Location: UK
Contact:

Re: Begging bowl time for José Roca <smile>

Post by deltarho[1859] »

José wrote:Me too, but according David's post he wanted to end the application inconditionally if the editor wasn't running.
What happened there was if whether WinFBE was running or not got sorted my next issue was to remove the PostQuitMessage(0) because it was a stop gap and I did not want to have two issues looked at. On reflection, the opening post could have been written better. However, Jochen came in quickly whilst I was checking out your post, José, and answered my next question before I asked it. Image

@adeyblue

That looks like a sledgehammer to crack a nut. This is what I ended up with:

Code: Select all

Case WM_CREATE
  SetTimer( hDlg, IDC_Timer, 250, null )
  
Case WM_TIMER  
  IF FindWindowW("WinFBE_Class", NULL) = NULL THEN ' it is not running
    KillTimer hDlg, IDC_Timer
    SendMessage(hDlg, WM_CLOSE, 0, 0)
    Exit Function
  End If
The 250ms will my longest wait and the expected value, statistically, will be 125ms. It looks OK, so I won't bother to do any tweaking.
Josep Roca
Posts: 564
Joined: Sep 27, 2016 18:20
Location: Valencia, Spain

Re: Begging bowl time for José Roca <smile>

Post by Josep Roca »

For clarification: DestroyWidow is what ends the application by destroying the main window and its child controls (and other things) and PostQuitMessage(0) is sent to exit the message pump (otherwise, the application will remain in memory performing an infinite loop). With dialogs you use EndDialog (SDK) or DIALOG END (PowerBasic).

When you send a WM_CLOSE message and you process it in the main callback procedure, you have the choices of ignore it, abort it, display a confirmation message or call DestroyWindow.

If you ignore it or you don't call DestroyWindow when processing it, DefWindowProc will call DestroyWindow for you.
jj2007
Posts: 2326
Joined: Oct 23, 2016 15:28
Location: Roma, Italia
Contact:

Re: Begging bowl time for José Roca <smile>

Post by jj2007 »

Josep Roca wrote:When you send a WM_CLOSE message and you process it in the main callback procedure, you have the choices of ignore it, abort it, display a confirmation message or call DestroyWindow.

If you ignore it or you don't call DestroyWindow when processing it, DefWindowProc will call DestroyWindow for you.
Right. The WM_CLOSE handler is where you can ask if you want to save that crap you've entered, yes or no? And you can cancel to reflect once more. So typically there will be a MessageBox(hWnd, "Save your data?", "Exit:", MB_YESNOCANCEL). If you click Yes, action to save must follow before letting DefWindowProc do its job, if you click Cancel, you must return instead of passing WM_CLOSE to DefWindowProc.
Post Reply