It is currently Sat Dec 05, 2020 7:00 pm

All times are UTC + 1 hour




Post new topic Reply to topic  [ 14 posts ] 
Author Message
 Post subject: Detect Close button click on other windows
PostPosted: Sat Jan 25, 2020 2:05 pm 
Offline
Addict
Addict

Joined: Thu Apr 18, 2019 8:17 am
Posts: 1099
Hi, does anyone know how to detect a Close button click on a third-party window, to cancel the click and then do something to that window first instead? I want to make a window animate in a specific way before closing, so I need to detect when Close is clicked to cancel the #WM_CLOSE message to it, animate it, then send my own #WM_CLOSE message to do the actual close.


Top
 Profile  
Reply with quote  
 Post subject: Re: Detect Close button click on other windows
PostPosted: Sat Jan 25, 2020 4:18 pm 
Offline
PureBasic Expert
PureBasic Expert

Joined: Sun Apr 12, 2009 6:27 am
Posts: 3739
1- Create a Transparent window with the size of the Close button
2- Create a watchdog Thread
3- Keep detecting the position of the third-party window(if you can :) )
4- keep moving the transparent window on top of the third-party window Close Button

Now you can know when the third-party Close button just clicked
From here do what you want to do then Close that Window

Good luck

# 2:
- You can use Low Level Mouse Hook to intercept Left & Right Mouse Button down & Button up
- Once it is detected raise a flag and get the Cursor position
- If the Cursor position within the Close Button area do what you want to do
- Else let it go

_________________
Egypt my love


Top
 Profile  
Reply with quote  
 Post subject: Re: Detect Close button click on other windows
PostPosted: Sun Jan 26, 2020 2:46 am 
Offline
Addict
Addict

Joined: Thu Apr 18, 2019 8:17 am
Posts: 1099
Hi Rashad. Your first method is what I've currently got going, but it has the drawback that sometimes a user will click the Close button of an inactive background window, so my fake little window isn't going to be over it (it's only over the active window). I don't want to parse all open windows and stick a fake one over them all, hence this coding question.

The mouse hook idea sounds good, but I'm worried that it won't (or can't) intercept a Close click to an inactive window as well. I'll experiment and see.


Top
 Profile  
Reply with quote  
 Post subject: Re: Detect Close button click on other windows
PostPosted: Sun Jan 26, 2020 2:52 am 
Offline
PureBasic Expert
PureBasic Expert

Joined: Sun Apr 12, 2009 6:27 am
Posts: 3739
Hi BarryG
The Global Hook will do the job(I hope)
Go with it :D
Code:
Global hhkLLMouse

Procedure MouseHook(nCode, wParam, lParam)
    *p.MOUSEHOOKSTRUCT = lParam
      Select wParam
        Case #WM_LBUTTONDOWN , #WM_RBUTTONDOWN
          x = *p\pt\x
          y = *p\pt\y
          If x > 1700 And x < 1850
            ProcedureReturn 1
          Else
            Debug x
            Debug y
          EndIf
      EndSelect
  ProcedureReturn CallNextHookEx_(0, nCode, wParam, lParam)
EndProcedure

OpenWindow(0, 0, 0, 300, 100, "Global Hook", #PB_Window_SystemMenu|#PB_Window_ScreenCentered)

hhkLLMouse = SetWindowsHookEx_(#WH_MOUSE_LL, @MouseHook(), GetModuleHandle_(0), 0)

Repeat
  Select WaitWindowEvent (10)
    Case #PB_Event_CloseWindow
      UnhookWindowsHookEx_(hhkLLMouse)
      Quit = 1

  EndSelect 
Until Quit = 1
 UnhookWindowsHookEx_(hhkLLMouse)
End

_________________
Egypt my love


Top
 Profile  
Reply with quote  
 Post subject: Re: Detect Close button click on other windows
PostPosted: Sun Jan 26, 2020 3:02 am 
Offline
PureBasic Bullfrog
PureBasic Bullfrog
User avatar

Joined: Wed Jul 06, 2005 5:42 am
Posts: 8144
Location: Fort Nelson, BC, Canada
RASHAD: It's an unowned 3rd party window. Different ballgame.

Here's how I would do it:

A global hook is necessary if you want to tap into the event queue of an unowned window. This requires a hook procedure located in a compiled DLL. I know it's a pain but there really is no way around this.

Place the following 3 programs in the same folder.

Main Program:
Code:
Global hook.l, hooklib, address.l, hwndTarget.l

Procedure WinProc(hWnd, msg, wParam, lParam)
  result = #PB_ProcessPureBasicEvents
  Select msg
    Case #WM_USER+100
      hwndTarget = lParam
      UnhookWindowsHookEx_(Hook)
      ; Stupid animation
      For i=1 To 10
        Delay(40)
        GetWindowRect_(hwndTarget, @wr.RECT)
        MoveWindow_(hwndTarget, wr\left-10, wr\top, wr\right-wr\left, wr\bottom-wr\top, #True)
        Delay(40)
        GetWindowRect_(hwndTarget, @wr.RECT)
        MoveWindow_(hwndTarget, wr\left+10, wr\top, wr\right-wr\left, wr\bottom-wr\top, #True)
      Next
      SendMessage_(hwndTarget, #WM_SYSCOMMAND, #SC_CLOSE, 0)
      While IsWindow_(hwndTarget)
        Delay(1)
      Wend
      Hook = SetWindowsHookEx_(#WH_CBT, address, LibraryID(hooklib), 0)     
  EndSelect
  ProcedureReturn result
EndProcedure

OpenWindow(0,0,0,320,240,"Calling Window",#PB_Window_SystemMenu)
SetWindowCallback(@WinProc())

hooklib = OpenLibrary(#PB_Any, "wh_winproc.dll")
If hooklib
  address = GetFunction(hooklib, "CBTProc")
  Hook = SetWindowsHookEx_(#WH_CBT, address, LibraryID(hooklib), 0)
Else
  MessageRequester("oops!", "Could not open hook dll... quitting.")
EndIf

Repeat
  EventID = WaitWindowEvent()
Until EventID = #PB_Event_CloseWindow

UnhookWindowsHookEx_(Hook)

End


Compiled DLL:
Code:
ProcedureDLL AttachProcess(instance)
  Global Caller = FindWindow_(0, "Calling Window")
EndProcedure

ProcedureDLL CBTProc(nCode, wParam, lParam)
  hwndTarget = FindWindow_(0, "Testing123")
  If nCode = #HCBT_SYSCOMMAND
    If wParam = #SC_CLOSE
      If hwndTarget = GetForegroundWindow_()
        PostMessage_(Caller, #WM_USER+100, 0, hwndTarget)
        ProcedureReturn 1
       EndIf
    EndIf
  Else
    ProcedureReturn CallNextHookEx_(0, nCode, wParam, lParam)
  EndIf
EndProcedure


Unowned window to test with:
Code:
OpenWindow(0,0,0,320,240,"Testing123",#PB_Window_SystemMenu|#PB_Window_ScreenCentered)
StickyWindow(0,1)

Repeat
  EventID = WaitWindowEvent()
Until EventID = #PB_Event_CloseWindow


1. Compile the second code as a shared dll
2. Run the third code
3. Run the first code
4. Close the window titled "Testing123".

The main code watches for the close of the test window using the hook proc in the dll. When the hook proc detects the close attempt, it signals the main program which then:
1. Disables the hook
2. Animates the test window (can't use Animate window here if you don't own the window)
3. Closes the test window
4. Reinstalls the hook for next time

Any questions, just ask. If I'm not around RASHAD or srod or someone will know what's up.

_________________
Veni, vidi, vici.


Top
 Profile  
Reply with quote  
 Post subject: Re: Detect Close button click on other windows
PostPosted: Sun Jan 26, 2020 3:37 am 
Offline
Addict
Addict

Joined: Thu Apr 18, 2019 8:17 am
Posts: 1099
Thanks for pointing me in the right direction, Netmaestro. However, if I try to use another third-party window, like "Untitled - Notepad", it doesn't work. Yes, I've changed the window name in the DLL code.

Also, if I remove StickyWindow() from the "Testing123" window code, it doesn't close that window after animating, until I move the mouse on it. Not all windows will be sticky, but I should be able to work out a way to fix that.


Top
 Profile  
Reply with quote  
 Post subject: Re: Detect Close button click on other windows
PostPosted: Sun Jan 26, 2020 3:47 am 
Offline
PureBasic Bullfrog
PureBasic Bullfrog
User avatar

Joined: Wed Jul 06, 2005 5:42 am
Posts: 8144
Location: Fort Nelson, BC, Canada
To make it close in all cases, change the SendMessage in the mainprogram to PostMessage:
Code:
PostMessage_(hwndTarget, #WM_SYSCOMMAND, #SC_CLOSE, 0)

Should fix that part anyway. For the calculator make sure you have a hwnd for it before proceeding further.

_________________
Veni, vidi, vici.


Top
 Profile  
Reply with quote  
 Post subject: Re: Detect Close button click on other windows
PostPosted: Sun Jan 26, 2020 4:00 am 
Offline
Addict
Addict

Joined: Thu Apr 18, 2019 8:17 am
Posts: 1099
I changed your DLL code to the following so that no window title is needed to be checked, and it works great for the "Testing123" window, but not for any other windows. I don't know why, because it's definitely getting a valid hwnd for the "Testing123" window. Why would the hwnd of any other non-PureBasic window (Notepad) fail?

The hwnd for Notepad (not Calculator) is just hwndTarget, isn't it? That's what the "Testing123" window returns.

Code:
ProcedureDLL AttachProcess(instance)
  Global Caller = FindWindow_(0, "Calling Window")
EndProcedure

ProcedureDLL CBTProc(nCode, wParam, lParam)
  hwndTarget = GetForegroundWindow_()
  If hwndTarget <> Caller And nCode = #HCBT_SYSCOMMAND And wParam = #SC_CLOSE
    PostMessage_(Caller, #WM_USER+100, 0, hwndTarget)
    ProcedureReturn 1
  Else
    ProcedureReturn CallNextHookEx_(0, nCode, wParam, lParam)
  EndIf
EndProcedure


Top
 Profile  
Reply with quote  
 Post subject: Re: Detect Close button click on other windows
PostPosted: Sun Jan 26, 2020 4:30 am 
Offline
PureBasic Bullfrog
PureBasic Bullfrog
User avatar

Joined: Wed Jul 06, 2005 5:42 am
Posts: 8144
Location: Fort Nelson, BC, Canada
If you're on a 64bit OS and running x86 PB the dll won't inject into the calculator. Beyond that, I don't know.

_________________
Veni, vidi, vici.


Top
 Profile  
Reply with quote  
 Post subject: Re: Detect Close button click on other windows
PostPosted: Sun Jan 26, 2020 4:32 am 
Offline
Addict
Addict

Joined: Thu Apr 18, 2019 8:17 am
Posts: 1099
That's probably it, then, because that's the case. Your code works with all my PureBasic apps, but not any third-party apps. I'll keep trying. Thanks for your help!


Top
 Profile  
Reply with quote  
 Post subject: Re: Detect Close button click on other windows
PostPosted: Sun Jan 26, 2020 6:11 am 
Offline
PureBasic Expert
PureBasic Expert

Joined: Sun Apr 12, 2009 6:27 am
Posts: 3739
Hi NM
Very glad to see you around :D
I hope you are doing good
Best wishes to you

I know that it is Third party application

@BarryG
I hope it will satisfy your needs

Code:
Global hhkLLMouse,hwnd,tx,ty,flag

RunProgram("notepad.exe")
Repeat
  hwnd = FindWindow_(0,"Untitled - Notepad")
Until hwnd

Procedure MouseHook(nCode, wParam, lParam)
    *p.MOUSEHOOKSTRUCT = lParam
      Select wParam
        Case #WM_LBUTTONDOWN , #WM_RBUTTONDOWN
          x = *p\pt\x
          y = *p\pt\y
          If x > tx  And x < tx+50 And y > ty And y < ty+30
            flag = 1
            ProcedureReturn 1         
          Else
            ;Debug x
            ;Debug y
          EndIf
      EndSelect
  ProcedureReturn CallNextHookEx_(0, nCode, wParam, lParam)
EndProcedure

Procedure watchdog(par)
  Repeat
    Delay(100)
    GetWindowRect_(hwnd,r.RECT)
    tx = r\right - 50
    ty = r\top
    If flag = 1
       flag = 0
      result = MessageRequester("GO","You are on Target",#PB_MessageRequester_YesNo)
      If result = #PB_MessageRequester_Yes
        SendMessage_(hwnd, #WM_SYSCOMMAND, #SC_CLOSE, 0)
        Quitt = 1
      EndIf
    EndIf
  Until Quitt = 1
EndProcedure

OpenWindow(0, 0, 0, 300, 100, "Global Hook", #PB_Window_SystemMenu|#PB_Window_ScreenCentered)

thread = CreateThread(@watchdog(),30)

hhkLLMouse = SetWindowsHookEx_(#WH_MOUSE_LL, @MouseHook(), GetModuleHandle_(0), 0)

Repeat
  Select WaitWindowEvent (10)
    Case #PB_Event_CloseWindow
      UnhookWindowsHookEx_(hhkLLMouse)
      Quit = 1

  EndSelect
Until Quit = 1
 UnhookWindowsHookEx_(hhkLLMouse)
End

_________________
Egypt my love


Top
 Profile  
Reply with quote  
 Post subject: Re: Detect Close button click on other windows
PostPosted: Sun Jan 26, 2020 7:45 am 
Offline
Addict
Addict

Joined: Thu Apr 18, 2019 8:17 am
Posts: 1099
Doesn't work Rashad; it only appears to because our process launched Notepad. It won't work with existing Notepads.

Netmaestro's solution works but apparently not with my 32-bit app on my 64-bit PC. I don't really want to use the 64-bit version of PureBasic if I can help it, because it reduces my customer base (a lot still use 32-bit Windows, and even I do on an old laptop or two), as well as breaking a few procedures that I can't update to 64-bit code right now.


Top
 Profile  
Reply with quote  
 Post subject: Re: Detect Close button click on other windows
PostPosted: Sun Jan 26, 2020 8:05 am 
Offline
PureBasic Expert
PureBasic Expert

Joined: Sun Apr 12, 2009 6:27 am
Posts: 3739
Just comment
Code:
   ;RunProgram("notepad.exe")


And it will work with existing running Notepad
Be sure you got the right handle
Because the Notepad Title Text depends on the opened file :wink:

Tested with PB 5.71 x86-x64 - Windows 10 x64

_________________
Egypt my love


Last edited by RASHAD on Sun Jan 26, 2020 8:10 am, edited 1 time in total.

Top
 Profile  
Reply with quote  
 Post subject: Re: Detect Close button click on other windows
PostPosted: Sun Jan 26, 2020 8:10 am 
Offline
Addict
Addict

Joined: Thu Apr 18, 2019 8:17 am
Posts: 1099
RASHAD wrote:
it will work with existing running Notepad
Be sure you got the right handle

Oops, you're right! I didn't have hWnd set correctly. Thank you.


Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 14 posts ] 

All times are UTC + 1 hour


Who is online

Users browsing this forum: No registered users and 31 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
Jump to:  

 


Powered by phpBB © 2008 phpBB Group
subSilver+ theme by Canver Software, sponsor Sanal Modifiye