1. Tomáš Podzimek
  2. PowerBuilder
  3. Wednesday, 10 April 2024 08:47 AM UTC

Hi all,

is it possible to trigger an event on the tabpage after pressing the middle mouse button (scroll wheel) - e.g. to close it - as in the browser?

I can't find a way...

Regards,

Tomáš

Accepted Answer
John Fauss Accepted Answer Pending Moderation
  1. Wednesday, 10 April 2024 15:01 PM UTC
  2. PowerBuilder
  3. # Permalink

* * * Edited * * * Revised to close the tab that the middle/wheel button clicks instead of the current tab.

Hi, Tomáš -

I was able to get this to work by adding two events to the tab control. Also needed are two Windows API-compatible structures and three external function declarations for Windows API functions:

A Windows API-compatible POINT structure is needed first. I've called it s_point:

type s_point from structure
   long   x
   long   y
end type

Next, another Windows-compatible TCHITTESTINFO (Tab Control Hit Test Info) structure I've named s_tchittestinfo:

type s_tchittestinfo from structure
   s_point   pt
   unsignedlong   flags
end type

Also needed are three external function declarations for some Windows API functions:

FUNCTION Boolean GetCursorPos ( &
   REF s_point lpPoint &
   ) LIBRARY "user32.dll"

FUNCTION Boolean ScreenToClient ( &
   Longptr     hWnd, &
   REF s_point lpPoint &
   ) LIBRARY "user32.dll"

FUNCTION Longptr TabCtrl_HitTest ( &
   Longptr             hWnd, &
   UnsignedLong        Msg, &
   Longptr             wParam, &
   REF s_tchittestinfo lParam &
   ) LIBRARY "user32.dll" ALIAS FOR "SendMessageW"

Now to the code. You need a Boolean instance variable:

Boolean ib_mbuttondown = False

Create a tab control user event named mbuttondown mapped to pbm_mbuttondown:

// Keeps track of user pressing the middle mouse button on/over a tab, in order
// that the MButtonUp event will know it is OK to close the tab that is clicked.

ib_mbuttondown = True
Return 0

Lastly, create a tab control user event named mbuttonup mapped to pbm_mbuttonup:

// There is no mapped "middle mouse button click" event available, only down/up events.

// This script ignores a middle mouse button up event UNLESS the user also caused a
// middle mouse button down event. This prevents the up event from taking any action if
// the user presses the middle mouse button down somewhere else, moves the mouse over a
// tab in the tab control, then releases the middle mouse button.

Constant UnsignedLong TCM_HITTEST = 4877 // Message ID for tab control "hit test" message.

Boolean lb_rc
Integer li_num_tabs, li_tab_2b_closed, li_tab_2b_selected
Longptr lp_rc
s_tchittestinfo lstr_hti  // This structure contains a WinAPI "point" structure.

// Do nothing if the user did not press the middle mouse button down over a tab.
If Not ib_mbuttondown Then Return 0

ib_mbuttondown = False

// Don't close the last/only tab page.
li_num_tabs = UpperBound(This.Control[])
If li_num_tabs < 2 Then Return 0

// Determine which tab the cursor is currently over (if any). To accomplish this,
// use Windows API functions to (1) Obtain the cursor's position in screen coordinates,
// (2) convert that point to client (i.e., tab control) coordinates, and (3) perform a
// "hit test" that will tell us the tab index the cursor is over.
lb_rc = GetCursorPos(lstr_hti.pt)
lb_rc = ScreenToClient(Handle(This),lstr_hti.pt)
lp_rc = TabCtrl_HitTest(Handle(This),TCM_HITTEST,0,lstr_hti)

// A return code of -1 means the cursor is not over a tab, so take no action.
If lp_rc = -1 Then Return 0

// In Windows, the tab index begins with zero, but in PB the tab index begins with one.
li_tab_2b_closed = lp_rc + 1

// Assume the current tab will remain the current tab after one is closed.
li_tab_2b_selected = This.SelectedTab

// Determine which tab page should be selected after the requested tab page is closed.
If li_tab_2b_closed = This.SelectedTab Then
   // The current tab is to be closed. After it is closed, the tab that is to the
   // immediate right will become the current tab (thus, the tab index will not change).
   //
   // However, it there is not a tab to the immediate right, the tab to the immediate
   // left needs to become the selected/current tab.
   If li_tab_2b_selected = li_num_tabs Then li_tab_2b_selected --
ElseIf li_tab_2b_closed < li_tab_2b_selected Then
   // The tab to be closed is to the left of the current tab. The current tab will remain
   // the current tab, but its tab index will decrease by 1.
   li_tab_2b_selected --
End If

// Close the requested tab page and select the same or different tab. If you do not perform
// the SelectTab, then an empty tab control might be displayed.
This.CloseTab(This.Control[li_tab_2b_closed])
This.SelectTab(li_tab_2b_selected)

Return 0

At runtime, if you click the middle mouse button (wheel) while the cursor is over any of the tabs, the clicked tab page will be closed.

I hope this does what you are looking for.

Best regards, John

Comment
There are no comments made yet.
John Fauss Accepted Answer Pending Moderation
  1. Thursday, 11 April 2024 23:27 PM UTC
  2. PowerBuilder
  3. # 1

I have figured out how to determine which tab the cursor is over when the middle/wheel button is clicked, so I have updated my earlier response to reflect the necessary code changes. The code is not difficult, but finding the right WinAPI calls to utilize and coding to use them was a challenge.

Enjoy!

 

Comment
  1. Tomáš Podzimek
  2. Friday, 12 April 2024 16:17 PM UTC
Exquisite, 10 out of 10. You seem to like challenges, good for me :).

Thanks a lot.

Regards,

Tomáš
  1. Helpful
  1. John Fauss
  2. Friday, 12 April 2024 16:32 PM UTC
You're welcome. Yes, I do enjoy a challenge ;)
  1. Helpful
There are no comments made yet.
Tomáš Podzimek Accepted Answer Pending Moderation
  1. Thursday, 11 April 2024 07:16 AM UTC
  2. PowerBuilder
  3. # 2

Hi John,

An excellent piece of code, thank you very much! It works as you say - it closes the currently selected tab page.
I will try to tweak it to close the tab under the mouse cursor - not necessarily the selected one.

Best regards,

Tomáš

Comment
There are no comments made yet.
  • Page :
  • 1


There are no replies made for this question yet.
However, you are not allowed to reply to this question.
We use cookies which are necessary for the proper functioning of our websites. We also use cookies to analyze our traffic, improve your experience and provide social media features. If you continue to use this site, you consent to our use of cookies.