Mouse-HotSpot Splitter As A SplitterGadget

Share your advanced PureBasic knowledge/code with the community.
BackupUser
PureBasic Guru
PureBasic Guru
Posts: 16777133
Joined: Tue Apr 22, 2003 7:42 pm

Post by BackupUser »

Restored from previous forum. Originally posted by Franco.


This is updated code...
It uses InnerWindowMouseX() and InnerWindowMouseY() - see procedures.
Thanks goes to Berikco for the hint.
Code changed on Win2k-Sp3. Have to test it under WinXP though.


Hope it's useful for some of you.
Any questions or suggestions are welcome :)

Code: Select all

; (c) 2003 - Franco's template - absolutely freeware
; This is a Gadget Splitter
; Should work fine on all Windows Operating Systems
;
; Normally if you have 2 ListViews (or TreeViews etc.) and you want
; change the width of both (one decreases the other increases) you
; use mouse hot spots between the Gadgets. 
; Negative about this is the manually setting of this hotspot. 
; Every time you change the position of your ListViews, you have to
; adapt the hotspot.
; Also sometimes it doesn't work properly...
; (see PureBasic Editor while the Procedure Browser is on the left,
; the Arrow Cursor appears also inside the RichEdit Gadget.
; Also the Gadgets Splitter example in PureBasic v3.00 - nowadays disappeared...)
;
; Now here this "hotspot" works different.
; It is realized as a Gadget = SplitterGadget(...)
; No adaptation is required!
; How is this done?
; 
; You create two gadgets which you want to incorporate in your 
; splitter function. Example:
; ListViewGadget(1,  10, 10, 88, 200)
; or
; ListViewGadget(2,  0, 0, 0, 0) ; I talk about the zeros later...
;
; After that, you have to create the SplitterGadget with:
; SplitterGadget(GadgetNumber.l, PositionX.l, PositionY.l, Width.l, Height.l, LeftGadget.l, RightGadget.l)
;
; The PositionX, PositionY, Width and Height are the maximum area 
; of all incorporated Gadgets. That's why it's possible to do:
; ListViewGadget(2,  0, 0, 0, 0). 
; This values are changed when you call the SplitterGadget.
; For this you have to tell the SplitterGadget which Gadgets to work with.
; This can be done with the parameters LeftGadget and RightGadget.
; That's it!
;
; As you can see, you have to click the toggle button on the SplitterGadget
; and than you can move it. A second click will freeze it at the actual position.
; I know, the use is different than normal hotspots, but I think this approach
; is more elegant - and personally I don't care if I have to click twice.
;
; The Procedures SetSplitterGadget() and WatchSplitterGadget() must be
; incorporated in the event handler as seen in this example. 
;
; The return value of SplitterGadget is the Windows-OS handle of this Gadget.
;
; BTW:
; The cursor changes with the action... nice isn't it?
; And only if it is over the SplitterGadget, nowhere else !
;
; Also this is the newest version with compensation of the Windows Border/Theme.
; Thanks to Berikco for the hint :)
;
; And here it goes:

Procedure DualSplitterGadget(GadgetNumber.l, PositionX.l, PositionY.l, Width.l, Height.l, LeftGadget.l, RightGadget.l)
  Shared Splitter_Toggle, Splitter_HandCursor.l, Splitter_ArrowCursor.l
  Shared Splitter_GadgetX1, Splitter_GadgetX2
  
  RoomBetweenGadgets.l = 4
  
  SplitterGadgetWidth.l = 4
  SplitterGadgetHeight.l = Height - (RoomBetweenGadgets * 2)
  SplitterGadgetX.l = PositionX + Width/2 - SplitterGadgetWidth/2
  SplitterGadgetY.l = PositionY + 4

  LeftGadgetWidth.l = SplitterGadgetX - 4 - PositionX
  ResizeGadget(LeftGadget, PositionX, PositionY, LeftGadgetWidth, Height) 

  RightGadgetX.l = SplitterGadgetX + SplitterGadgetWidth + RoomBetweenGadgets
  RightGadgetWidth.l = PositionX + Width - RightGadgetX
  ResizeGadget(RightGadget, RightGadgetX, PositionY, RightGadgetWidth, Height) 
  
  SplitterID.l = ButtonGadget(GadgetNumber, SplitterGadgetX, SplitterGadgetY, SplitterGadgetWidth, SplitterGadgetHeight,"",#PB_Button_Toggle)
  SetClassLong_(SplitterID,#GCL_HCURSOR,0)

  Splitter_ArrowCursor = LoadCursor_(0, #IDC_SIZEWE)
  Splitter_HandCursor = LoadCursor_(0, 32649); #IDC_HAND not recognized by PureBasic

  Splitter_Toggle = 0

  Splitter_GadgetX1.l = PositionX
  Splitter_GadgetX2.l = PositionX + Width

  ProcedureReturn SplitterID

EndProcedure

Procedure SetDualSplitterGadget()
  Shared Splitter_Toggle

  If Splitter_Toggle = 0
    Splitter_Toggle = 1
  ElseIf Splitter_Toggle = 1
    Splitter_Toggle = 0
  EndIf 

EndProcedure

Procedure InnerWindowMouseX()
  ProcedureReturn WindowMouseX() - GetSystemMetrics_(#SM_CYSIZEFRAME)
EndProcedure

Procedure InnerWindowMouseY()
  ProcedureReturn WindowMouseY() - GetSystemMetrics_(#SM_CYCAPTION) - GetSystemMetrics_(#SM_CYSIZEFRAME)
EndProcedure

Procedure WatchDualSplitterGadget()
  Shared Splitter_HandCursor, Splitter_ArrowCursor, Splitter_Toggle
  Shared Splitter_GadgetX1, Splitter_GadgetX2

  If Splitter_Toggle = 0 And ChildWindowFromPoint_(WindowID(),InnerWindowMouseX(),InnerWindowMouseY()) = GadgetID(2)
    SetCursor_(Splitter_HandCursor) 
  ElseIf Splitter_Toggle = 1 And InnerWindowMouseX() > Splitter_GadgetX1 And InnerWindowMouseX()
BackupUser
PureBasic Guru
PureBasic Guru
Posts: 16777133
Joined: Tue Apr 22, 2003 7:42 pm

Post by BackupUser »

Restored from previous forum. Originally posted by freak.

Very good one, thanks for that. :)
BackupUser
PureBasic Guru
PureBasic Guru
Posts: 16777133
Joined: Tue Apr 22, 2003 7:42 pm

Post by BackupUser »

Restored from previous forum. Originally posted by Franco.

You're welcome!

Have a nice day...

Franco
BackupUser
PureBasic Guru
PureBasic Guru
Posts: 16777133
Joined: Tue Apr 22, 2003 7:42 pm

Post by BackupUser »

Restored from previous forum. Originally posted by Fangbeast.

Simply Brilliant. I remember asking Fred last year for shared/resizeable borders and he sait it was too hard for now, this is a great solution.

Can you have more than one splitter gadget this way across two gadgets? I:e. two vertical with a splitter and one horizontal shareing a splitter with the two vertical?

regards.



Fangles woz ear orright den?
BackupUser
PureBasic Guru
PureBasic Guru
Posts: 16777133
Joined: Tue Apr 22, 2003 7:42 pm

Post by BackupUser »

Restored from previous forum. Originally posted by Danilo.

The Editor-ProcBrowser-Resize is very nice and
works like in all other applications.

The arrow appears if you are between the 2 gadgets
and while you press the left mousebutton and move
the mouse, you can resize the 2 gadgets.
This way is used in all apps that use such splitter resize.

The above code shows a new non-standard way for
a splitter, but IMHO nobody will do it like this
in a real application.
Press and release mouse button to get in splitter-mode
and press and release again to go out of this mode
is just weird, IMHO.

Nothing against your code, Franco! I only want to say
that i´ve never seen this way before and interfaces
for apps should all work in the same standard way.
So every user can handle all applications.
(In your example i pressed mouse button, moved mouse around
and thought your stuff doesnt work because nothing got resized :wink:)

> ; Also sometimes it doesn't work properly...
> ; (see PureBasic Editor while the Procedure Browser is on the left,
> ; the Arrow Cursor appears also inside the RichEdit Gadget.

This doesnt mean the splitter doesnt work. The splitter
part itself works nice and like it should.
You didnt like the 'feature' that you see the splitter
cursor also in the RichEdit window, so i removed it now. :wink:
(next Editor)


cya,
...Danilo
(registered PureBasic user)
BackupUser
PureBasic Guru
PureBasic Guru
Posts: 16777133
Joined: Tue Apr 22, 2003 7:42 pm

Post by BackupUser »

Restored from previous forum. Originally posted by Rings.

works fine also unter NT.nice snippet anyway

Its a long way to the top if you wanna .....CodeGuru
BackupUser
PureBasic Guru
PureBasic Guru
Posts: 16777133
Joined: Tue Apr 22, 2003 7:42 pm

Post by BackupUser »

Restored from previous forum. Originally posted by fred.

Yes, good way to do easy a splitter stuff. As I've told earlier, it's not as easy to do under Windows (nothing in the API to make it standard). On GTK (linux) it's much easier :).

Fred - AlphaSND
BackupUser
PureBasic Guru
PureBasic Guru
Posts: 16777133
Joined: Tue Apr 22, 2003 7:42 pm

Post by BackupUser »

Restored from previous forum. Originally posted by Fangbeast.
Originally posted by fred

As I've told earlier, it's not as easy to do under Windows (nothing in the API to make it standard). On GTK (linux) it's much easier :).

Fred - AlphaSND
See Fred, I remembered :)

Fangles woz ear orright den?
BackupUser
PureBasic Guru
PureBasic Guru
Posts: 16777133
Joined: Tue Apr 22, 2003 7:42 pm

Post by BackupUser »

Restored from previous forum. Originally posted by Franco.
Originally posted by Danilo

The above code shows a new non-standard way for
a splitter, but IMHO nobody will do it like this
in a real application.
A non standard way? Excellent!
It's not from M$ so it can't be accepted...
Press and release mouse button to get in splitter-mode
and press and release again to go out of this mode
is just weird, IMHO.
I'm glad that it's only YHO :)
Nothing against your code, Franco! I only want to say
that i´ve never seen this way before and interfaces
for apps should all work in the same standard way.
So every user can handle all applications.
(In your example i pressed mouse button, moved mouse around
and thought your stuff doesnt work because nothing got resized :wink:)
I'm glad you found out how this gadget works.
It shows me that you can adapt too. :)

Why should every program act like others?
Are users that dumb :)

Because Micro$oft didn't release this style of doing things - it's wrong :)
So Linux should switch to a double click by default:)

BTW: Have you ever used a SaveFileRequester under XP?
If you stay to long with the cursor over a file your SaveFileName is changed automatically, and the message appeares:
"Do you want to overwrite file XXX?"
No you wanted to create a sub directory first - but you are to slow...
Under Win98/Win2000 you have to click the "Save" button to exit the Requester.

Automatism is good - but automatism overflow is worse.
But everybody likes it anyway because millions of flys can't be wrong - can't they :)


Have a nice day...

Franco
BackupUser
PureBasic Guru
PureBasic Guru
Posts: 16777133
Joined: Tue Apr 22, 2003 7:42 pm

Post by BackupUser »

Restored from previous forum. Originally posted by Fangbeast.

Franco, never mind the Klingons in the conference (grin), I quite like your idea and it is a good one for people who fidlle a lot, cannot control their hands properly (as with people with muscle disability) and those of us with tired hands:):):). Those of us with thick brains would like to know if this is easily extended to more than just two gadgets such as the two vertical gadgets that you have and a horizontal one sharing both their bottom edges?

:)

Fangles woz ear orright den?
BackupUser
PureBasic Guru
PureBasic Guru
Posts: 16777133
Joined: Tue Apr 22, 2003 7:42 pm

Post by BackupUser »

Restored from previous forum. Originally posted by Franco.
Originally posted by Fangbeast

Those of us with thick brains would like to know if this is easily extended to more than just two gadgets such as the two vertical gadgets that you have and a horizontal one sharing both their bottom edges?
Fangles, yes this is easily done.
Hope this is what you had in mind :)
BTW: This code is not fully tested, hope it works fine.


This is updated code...
It uses InnerWindowMouseX() and InnerWindowMouseY() - see procedures.
Thanks goes to Berikco for the hint.
Code changed on Win2k-Sp3. Have to test it under WinXP though.

Code: Select all


; (c) 2003 - Franco's template - absolutely freeware
; This is a Gadget Splitter for three Gadgets!
; The Gadgets are populated West, East and South.
; Should work fine on all Windows Operating Systems
;
; You create three gadgets which you want to incorporate in your 
; splitter function. Example:
; ListViewGadget(1,  10, 10, 88, 200)
; or
; ListViewGadget(2,  0, 0, 0, 0) ; I talk about the zeros later...
;
; After that, you have to create the SplitterGadget with:
; TripleSplitterGadget(HorizontalGadgetNumber.l, VerticalGadgetNumber.l,PositionX.l, PositionY.l, Width.l, Height.l, WestGadget.l, EastGadget.l, SouthGadget.l)
;
; The PositionX, PositionY, Width and Height are the maximum area 
; of all incorporated Gadgets. That's why it's possible to do:
; ListViewGadget(2,  0, 0, 0, 0). 
; This values are changed when you call the SplitterGadget.
; For this you have to tell the SplitterGadget which Gadgets to work with.
; This can be done with the parameters WestGadget, EastGadget and SouthGadget.
; That's it!
;
; As you can see, you have to click the toggle button on the SplitterGadget
; and than you can move it. A second click will freeze it at the actual position.
; I know, the use is different than normal hotspots, but I think this approach
; is more elegant - and personally I don't care if I have to click twice.
;
; The Procedures SetTripleSplitterGadgetH(), SetTripleSplitterGadgetV() and 
; WatchTripleSplitterGadget() must be incorporated in the event handler as seen in this example. 
;
; The SplitterGadget has no return value yet 
 ;(because didn't know what - there are 2 new Buttons in there).
;
; BTW:
; The cursor changes with the action... nice isn't it?
; And only if it is over the SplitterGadget, nowhere else !
;
; Also this is the newest version with compensation of the Windows Border/Theme.
; Thanks to Berikco for the hint :)
;
; And here it goes:

Procedure TripleSplitterGadget(GadgetNumberH.l, GadgetNumberV.l,PositionX.l, PositionY.l, Width.l, Height.l, WestGadget.l, EastGadget.l, SouthGadget.l)
  Shared Splitter_ToggleH.l,  Splitter_ToggleV.l,Splitter_HandCursor.l, Splitter_ArrowCursorH.l, Splitter_ArrowCursorV.l
  Shared Splitter_GadgetX1.l, Splitter_GadgetX2.l, Splitter_GadgetY1.l, Splitter_GadgetY2.l

  RoomBetweenGadgets.l = 4

  SplitterGadgetWidthH.l = 4
  SplitterGadgetHeightH.l = Height/2 - (RoomBetweenGadgets * 2) - 6
  SplitterGadgetHX.l = PositionX + Width/2 - SplitterGadgetWidthH/2
  SplitterGadgetHY.l = PositionY + 4

  SplitterGadgetHeightV.l = 4
  SplitterGadgetWidthV.l = Width - 8
  SplitterGadgetVX.l = PositionX + 4
  SplitterGadgetVY.l = PositionY + Height/2-2

  
  ; WestGadget
  WestGadgetWidth.l = SplitterGadgetHX - 4 - PositionX
  WestGadgetHeight.l = Height / 2 - 6
  ResizeGadget(WestGadget, PositionX, PositionY, WestGadgetWidth, WestGadgetHeight) 
  
  ; EastGadget
  EastGadgetX.l = SplitterGadgetHX + SplitterGadgetWidthH + RoomBetweenGadgets
  EastGadgetWidth.l = PositionX + Width - EastGadgetX
  EastGadgetHeight.l = Height / 2 - 6
  ResizeGadget(EastGadget, EastGadgetX, PositionY, EastGadgetWidth, EastGadgetHeight) 
  
  ; SouthGadget
  SouthGadgetY.l = SplitterGadgetVY + SplitterGadgetHeightV + RoomBetweenGadgets
  SouthGadgetHeight.l = PositionY + Height - SouthGadgetY
  ResizeGadget(SouthGadget, PositionX, SouthGadgetY, Width, SouthGadgetHeight) 
  
  ;HorizontalSplitter
  SplitterIDH = ButtonGadget(GadgetNumberH, SplitterGadgetHX, SplitterGadgetHY, SplitterGadgetWidthH, SplitterGadgetHeightH, "",#PB_Button_Toggle)
  
  ;VerticalSplitter
  SplitterIDV = ButtonGadget(GadgetNumberV, SplitterGadgetVX , SplitterGadgetVY, SplitterGadgetWidthV, SplitterGadgetHeightV, "",#PB_Button_Toggle)

  SetClassLong_(SplitterIDH,#GCL_HCURSOR,0)
  SetClassLong_(SplitterIDV,#GCL_HCURSOR,0)

  Splitter_ArrowCursorH = LoadCursor_(0, #IDC_SIZEWE)
  Splitter_ArrowCursorV = LoadCursor_(0, #IDC_SIZENS)
  Splitter_HandCursor = LoadCursor_(0, 32649); #IDC_HAND not recognized by PureBasic

  Splitter_Toggle = 0

  Splitter_GadgetX1.l = PositionX
  Splitter_GadgetX2.l = PositionX + Width
  Splitter_GadgetY1.l = PositionY
  Splitter_GadgetY2.l = PositionY + Height

  ;ProcedureReturn SplitterID

EndProcedure

Procedure SetTripleSplitterGadgetH()
  Shared Splitter_ToggleH

  If Splitter_ToggleH = 0
    Splitter_ToggleH = 1
  ElseIf Splitter_ToggleH = 1
    Splitter_ToggleH = 0
  EndIf 

EndProcedure

Procedure SetTripleSplitterGadgetV()
  Shared Splitter_ToggleV

  If Splitter_ToggleV = 0
    Splitter_ToggleV = 1
  ElseIf Splitter_ToggleV = 1
    Splitter_ToggleV = 0
  EndIf 

EndProcedure

Procedure InnerWindowMouseX()
  ProcedureReturn WindowMouseX() - GetSystemMetrics_(#SM_CYSIZEFRAME)
EndProcedure

Procedure InnerWindowMouseY()
  ProcedureReturn WindowMouseY() - GetSystemMetrics_(#SM_CYCAPTION) - GetSystemMetrics_(#SM_CYSIZEFRAME)
EndProcedure

Procedure WatchTripleSplitterGadget()
  Shared Splitter_HandCursor, Splitter_ToggleH, Splitter_ToggleV, Splitter_ArrowCursorH, Splitter_ArrowCursorV
  Shared Splitter_GadgetX1.l, Splitter_GadgetX2.l, Splitter_GadgetY1.l, Splitter_GadgetY2.l

  If Splitter_ToggleH = 0 And ChildWindowFromPoint_(WindowID(),InnerWindowMouseX(),InnerWindowMouseY()) = GadgetID(3)
    SetCursor_(Splitter_HandCursor) 
  ElseIf Splitter_ToggleH = 1 And InnerWindowMouseX() > Splitter_GadgetX1 And InnerWindowMouseX()  Splitter_GadgetY1 And InnerWindowMouseY()
BackupUser
PureBasic Guru
PureBasic Guru
Posts: 16777133
Joined: Tue Apr 22, 2003 7:42 pm

Post by BackupUser »

Restored from previous forum. Originally posted by Andre.

@Franco: Works fine under WinXP home SP 1. Nice work

Regards
André

*** German PureBasic Support ***
BackupUser
PureBasic Guru
PureBasic Guru
Posts: 16777133
Joined: Tue Apr 22, 2003 7:42 pm

Post by BackupUser »

Restored from previous forum. Originally posted by Fangbeast.

Franco, that's just wonderful. I started doing real apps in PureBasic when I came across your templates early last year, would not have done as much without them.

This new example of yours shows you what can be done with a bit of imagination and lateral thinking.

Like Andre, I have tested it on Windows XP and it works very well and with your permission, I might start putting it into some of my junk and make it really useful!!!

(Now I also have to work on form resizing code and an automatic way to resize gadgets when bigger fonts are detected. One of my testers is using 120 DPI fonts and he is whinging he cannot read my apps. I fell down laughing again and hurt myself) :):):)


Fangles woz ear orright den?
BackupUser
PureBasic Guru
PureBasic Guru
Posts: 16777133
Joined: Tue Apr 22, 2003 7:42 pm

Post by BackupUser »

Restored from previous forum. Originally posted by freak.

It doesn't work right here (Win2k Sp3). When moving the horizontal splitter, I can't release it any more. When i click the Mouse Button, only the first Element of the bottom ListView get's activated, but the splitter is not released.

Is there something wrong when calculating the mouse position?

Timo
BackupUser
PureBasic Guru
PureBasic Guru
Posts: 16777133
Joined: Tue Apr 22, 2003 7:42 pm

Post by BackupUser »

Restored from previous forum. Originally posted by Franco.
Originally posted by Fangbeast

This new example of yours shows you what can be done with a bit of imagination and lateral thinking.
Thanks for your kind words mate.
Like Andre, I have tested it on Windows XP and it works very well and with your permission, I might start putting it into some of my junk and make it really useful!!!
The header of the sample code says:
; (c) 2003 - Franco's template - absolutely freeware
With this in mind: permission granted :)

BTW: If you can sell your software and reach $1,000,000.00 (american dollars) profit - don't forget me :)

Have a nice day...

Franco
Post Reply