November 25, 2020, 05:27:24 AM

Author Topic: [bb] Splitter Gadget by Jim Teeuwen [ 1+ years ago ]  (Read 545 times)

Offline BlitzBot

  • Jr. Member
  • **
  • Posts: 1
[bb] Splitter Gadget by Jim Teeuwen [ 1+ years ago ]
« on: June 29, 2017, 12:28:41 AM »
Title : Splitter Gadget
Author : Jim Teeuwen
Posted : 1+ years ago

Description : A gadget that allows realtime resizing of gadets with a simple mousedrag. Demo code at the bottom

[FIX 1]
Added an optional Size parameter to the CreateSplitter function. this is the Splitter Size (eg Width) it defaults to 3 pixels, but it was pointed out to me that this is a bit hard to click.

[Fix 2]
KeithJ was kind enough to provide us with a userlib extension, wich enables us to actually change the cursor to some nifty resize arrows. many thanks for this Keith!

To use it, first create a file in the blitzplus Userlibs directory, and name it 'user32.decls'
Open it in notepad and add the following text to the file:

=============================================
.lib "user32.dll"
LoadCursor%( ID, Cursor ):"LoadCursorA"
SetCursor%( ID ):"SetCursor"
=============================================

This creates 2 methods for use to use in blitz. namely LoadCursor() and SetCursor.. the ID values represent constants wich are preset by the windows API. I puzzled a little and found the following constants for different cursors:
=================================
;// Load with SetCursor(LoadCursor(0, IDC_SIZEXX))
Const IDC_SIZENONE            = 32641      ;// No Cursor
Const IDC_SIZENWSE            = 32642      ;// Top left to bottom right
Const IDC_SIZENESW            = 32643      ;// Top right to bottom left
Const IDC_SIZEWE            = 32644      ;// Left to right
Const IDC_SIZENS            = 32645      ;// Top to Bottom
Const IDC_SIZEMOVE            = 32646      ;// Cross (4 directions)
Const IDC_SIZEDENIED         = 32648      ;// Circle with diagonal Line
Const IDC_SIZEHAND            = 32649      ;// Hand cursor
Const IDC_SIZEHOURGLASS         = 32650      ;// Hourglass
Const IDC_SIZEHELP            = 32651      ;// QuestionMark
Const IDC_SIZEMOVENS         = 32652      ;// Move Top to Bottom
Const IDC_SIZEMOVEWE         = 32653      ;// Move Left to right
Const IDC_SIZEMOVENSEW         = 32654      ;// Move 4 directions
Const IDC_SIZEMOVEN            = 32655      ;// Move Up
Const IDC_SIZEMOVES            = 32656      ;// Move Down
Const IDC_SIZEMOVEW            = 32657      ;// Move Left
Const IDC_SIZEMOVEE            = 32658      ;// Move Right
Const IDC_SIZEMOVENW         = 32659      ;// Move Top Left
Const IDC_SIZEMOVENE         = 32660      ;// Move Top Right
Const IDC_SIZEMOVESW         = 32661      ;// Move Bottom Left
Const IDC_SIZEMOVESE         = 32662      ;// Move Bottom Right
Const IDC_SIZECD            = 32663      ;// CD loading Icon

=================================

With the '.decls' file set and the constants ready, we can change the code to incorporate the cursor change. Below is the modified code. in the SplitterEventLoop() method there have been some aditions. namely the calls to SetCursor(LoadCursor(0, IDC_SIZEWE)) and SetCursor(LoadCursor(0, IDC_SIZENS))  for left-to-right and top-to-bottom arrows respectivly


Code :
Code: BlitzBasic
  1. ;//
  2. ;// Name        : Splitter Control
  3. ;// Desc        : BlitzPlus extension,
  4. ;//               A Splitter can simultaniously scale 2 controls,
  5. ;//               By simply dragging the splitter back and forth.
  6. ;//               It serves for resizing purposes, and can be applied for
  7. ;//               Both horizontal and vertical resizing.
  8. ;// Author      : Jim Teeuwen / Defiance
  9. ;//               http://www.transmuter.nl :: blitz@transmuter.nl
  10. ;//
  11. ;//               (c) 2002-2004, Jim Teeuwen. All rights reserved.
  12. ;//
  13.  
  14. Type Splitter
  15.         Field Gadget
  16.         Field FirstControl, SecondControl
  17.         Field Alignment
  18.         Field Group
  19.         Field Size
  20.         Field Canvas
  21. End Type
  22.  
  23. Const SPLITTER_ALIGN_VERTICAL           = 0
  24. Const SPLITTER_ALIGN_HORIZONTAL         = 1
  25.  
  26.  
  27. Function CreateSplitter.Splitter(Group, PrimaryGadget, SecundaryGadget, Alignment = SPLITTER_ALIGN_VERTICAL, Size = 3)
  28.  
  29.         spl.Splitter            = New Splitter
  30.         splFirstControl = PrimaryGadget
  31.         splSecondControl        = SecundaryGadget
  32.         splAlignment            = Alignment
  33.         splGroup                        = Group
  34.         splSize                 = Size
  35.         splGadget                       = CreatePanel(0, 0, splSize, ClientHeight(Group), Group, 0)
  36.        
  37.         If(splAlignment = SPLITTER_ALIGN_VERTICAL) Then
  38.                 SetGadgetLayout(splgadget, 1, 1, 1, 1)
  39.         Else
  40.                 SetGadgetLayout(splgadget, 1, 1, 0, 0)
  41.         End If
  42.        
  43.         splCanvas                       = CreateCanvas(0, 0, GadgetWidth(splGadget), GadgetHeight(splGadget), splGadget)
  44.                 SetGadgetLayout(splCanvas, 1, 1, 1, 1)
  45.                 SetBuffer(CanvasBuffer(splCanvas))
  46.                 Color(100, 100, 112)
  47.                 Rect(0, 0, GadgetWidth(splGadget), GadgetHeight(splGadget))
  48.        
  49.         UpdateSplitter(spl)
  50.        
  51.         If(splSecondControl <> 0) Then
  52.                 If(splAlignment = SPLITTER_ALIGN_VERTICAL) Then
  53.                         SetGadgetShape(splSecondControl, GadgetX(splSecondControl) + splSize, GadgetY(splSecondControl), GadgetWidth(splSecondControl) - splSize, GadgetHeight(splSecondControl))
  54.                 Else
  55.                         SetGadgetShape(splSecondControl, GadgetX(splSecondControl), GadgetY(splSecondControl) + splSize, GadgetWidth(splSecondControl), GadgetHeight(splSecondControl) - splSize)
  56.                 End If
  57.         End If
  58.        
  59.         Return spl
  60.  
  61. End Function
  62.  
  63. Function UpdateSplitter(spl.Splitter)
  64.  
  65.         If(splFirstControl = 0) Then
  66.                 If(splAlignment = SPLITTER_ALIGN_VERTICAL) Then
  67.                         SetGadgetShape(splGadget, 0, 0, splSize, ClientHeight(splGroup))
  68.                 Else
  69.                         SetGadgetShape(splGadget, 0, 0, ClientWidth(splGroup), 3)
  70.                 End If
  71.         Else
  72.                 If(splAlignment = SPLITTER_ALIGN_VERTICAL) Then
  73.                         SetGadgetShape(splGadget, GadgetWidth(splFirstControl), GadgetY(splFirstControl), splSize, GadgetHeight(splFirstControl))
  74.                 Else
  75.                         SetGadgetShape(splGadget, GadgetX(splFirstControl), GadgetHeight(splFirstControl), GadgetWidth(splFirstControl), splSize)
  76.                 End If
  77.         End If
  78.  
  79. End Function
  80.  
  81. Function SplitterEventLoop(spl.Splitter)
  82.  
  83.         If(MouseDown(1)) Then  
  84.                 offsetX                                 = EventX()
  85.                 offsetY                                 = EventY()
  86.  
  87.                 If(splAlignment = SPLITTER_ALIGN_VERTICAL) Then
  88.                         If((GadgetWidth(splFirstControl) + offsetX) < (ClientWidth(splGroup) - splSize) And (GadgetWidth(splFirstControl) + offsetX) > 0) Then
  89.                                 SetGadgetShape(splFirstControl, GadgetX(splFirstControl), GadgetY(splFirstControl), (GadgetWidth(splFirstControl) + offsetX), GadgetHeight(splFirstControl))
  90.                                 SetGadgetShape(splGadget, GadgetWidth(splFirstControl), GadgetY(splFirstControl), splSize, GadgetHeight(splFirstControl))
  91.                                 SetGadgetShape(splSecondControl, GadgetX(splGadget) + splSize, GadgetY(splSecondControl), GadgetWidth(splSecondControl) - offsetX, GadgetHeight(splSecondControl))
  92.                         End If
  93.                 Else
  94.                         If((GadgetHeight(splFirstControl) + offsetY) < (GadgetHeight(splGroup) - splSize) And (GadgetHeight(splFirstControl) + offsetY) > 0) Then
  95.                                 SetGadgetShape(splFirstControl, GadgetX(splFirstControl), GadgetY(splFirstControl), GadgetWidth(splFirstControl), (GadgetHeight(splFirstControl) + offsetX))
  96.                                 SetGadgetShape(splGadget, GadgetX(splFirstControl), GadgetHeight(splFirstControl), GadgetWidth(splFirstControl), splSize)
  97.                                 SetGadgetShape(splSecondControl, GadgetX(splSecondControl), (GadgetY(splGadget) + splSize), GadgetWidth(splSecondControl), GadgetHeight(splSecondControl) - offsetX)
  98.                         End If
  99.                 End If
  100.         End If
  101.  
  102.         If(splAlignment = SPLITTER_ALIGN_VERTICAL) Then
  103.                 SetCursor(LoadCursor(0, IDC_SIZEWE))
  104.         Else
  105.                 SetCursor(LoadCursor(0, IDC_SIZENS))
  106.         End If
  107.        
  108.         UpdateSplitter()
  109.  
  110. End Function
  111.  
  112.  
  113. ;// ### DEMO #####################################################################################
  114.  
  115. SplitterDemo()
  116. Global mySplitter.Splitter
  117.  
  118. ;/* Window Messages */
  119. Const WM_MOUSEMOVE                              = $203
  120. Const WM_RESIZE                                 = $802
  121. Const WM_CLOSE                                  = $803
  122.  
  123. Const IDC_SIZENONE                              = 32641         ;// No Cursor
  124. Const IDC_SIZENWSE                              = 32642         ;// Top left to bottom right
  125. Const IDC_SIZENESW                              = 32643         ;// Top right to bottom left
  126. Const IDC_SIZEWE                                = 32644         ;// Left to right
  127. Const IDC_SIZENS                                = 32645         ;// Top to Bottom
  128. Const IDC_SIZEMOVE                              = 32646         ;// Cross (4 directions)
  129. Const IDC_SIZEDENIED                    = 32648         ;// Circle with diagonal Line
  130. Const IDC_SIZEHAND                              = 32649         ;// Hand cursor
  131. Const IDC_SIZEHOURGLASS                 = 32650         ;// Hourglass
  132. Const IDC_SIZEHELP                              = 32651         ;// QuestionMark
  133. Const IDC_SIZEMOVENS                    = 32652         ;// Move Top to Bottom
  134. Const IDC_SIZEMOVEWE                    = 32653         ;// Move Left to right
  135. Const IDC_SIZEMOVENSEW                  = 32654         ;// Move 4 directions
  136. Const IDC_SIZEMOVEN                             = 32655         ;// Move Up
  137. Const IDC_SIZEMOVES                             = 32656         ;// Move Down
  138. Const IDC_SIZEMOVEW                             = 32657         ;// Move Left
  139. Const IDC_SIZEMOVEE                             = 32658         ;// Move Right
  140. Const IDC_SIZEMOVENW                    = 32659         ;// Move Top Left
  141. Const IDC_SIZEMOVENE                    = 32660         ;// Move Top Right
  142. Const IDC_SIZEMOVESW                    = 32661         ;// Move Bottom Left
  143. Const IDC_SIZEMOVESE                    = 32662         ;// Move Bottom Right
  144. Const IDC_SIZECD                                = 32663         ;// CD loading Icon
  145.  
  146. Function SplitterDemo()
  147.  
  148.         ;// Create a new form with some panels on it.
  149.         ;// We will use the splitter control to be able to resize these panels
  150.         ;// at runtime. The splitter will appear as a darkgray 3-pixel wide line between 2 panels
  151.         ;// To use it., simply click on the splitter and drag it left/right(vertically aligned splitter)
  152.         ;// or up/down (horizontally aligned Splitter)
  153.  
  154.         ;/* frmMain */
  155.         frmMain         = CreateWindow("UI Test", 20, 20, ClientWidth(Desktop()) - 40, ClientHeight(Desktop()) - 40, 0)
  156.                 SetMinWindowSize(frmMain, 320, 240)
  157.                 SetGadgetText(frmMain, "Splitter Control Demo")
  158.                
  159.         ;/* Workspace */
  160.         pnlWorkSpace    = CreatePanel(0, 0, ClientWidth(frmMain) - 193, ClientHeight(frmMain) , frmMain, 0)
  161.                 SetGadgetLayout(pnlWorkSpace, 1, 1, 1, 1)
  162.                 SetGadgetText(pnlWorkSpace, "WorkSpace")
  163.                 SetPanelColor(pnlWorkSpace, 136, 147, 158)
  164.        
  165.         ;/* pnlProperties *.
  166.         pnlProperties   = CreatePanel(GadgetWidth(frmMain) - 200, 0, 200, GadgetHeight(frmMain), frmMain, 0)
  167.                 SetGadgetLayout(pnlProperties, 0, 1, 1, 1)
  168.                 SetGadgetText(pnlProperties, "Properties")
  169.        
  170.         trvProject              = CreateTreeView(0, 0, GadgetWidth(pnlProperties) - 8, GadgetHeight(pnlProperties) / 3, pnlProperties)
  171.                 SetGadgetLayout(trvProject, 1, 1, 1, 0)
  172.                
  173.         ;/* Splitter */
  174.         ;// Here we create the splitter.
  175.         ;// This splitter will 'split' the 2 panels 'pnlWorkSpace' and 'pnlProperties'
  176.         ;// Normally we would add this splitter gadget after the first panel, but we need a valid
  177.         ;// reference to the second Properties panel for this to work. Thus, we create the splitters
  178.         ;// AFTER ALL THE PANELS ARE CREATED!
  179.         ;// This splitter will be Vertically aligned
  180.         ;// Calling the create method takes a few parameters:
  181.         ;//
  182.         ;//     spl = CreateSplitter(group, firstControl, secondControl, alignment)
  183.         ;//
  184.         ;//     group                   : This is the group to wich the splitter is added. works the same as
  185.         ;//                                       adding a normal gadget.
  186.         ;//     firstControl    : This is the first gadget to wich the splitter will apply.
  187.         ;//                                       In our case this is 'pnlWorkSpace'
  188.         ;//     secondControl   : Naturally, this is the second gadget to wich the splitter applies
  189.         ;//                                       You see now why we need to wait with splitter creation till ALL
  190.         ;//                                       the regular controls have been initialised.
  191.         ;//     Alignment               : This is the splitter alignment. Can be either SPLITTER_ALIGN_VERTICAL (default),
  192.         ;//                                       or SPLITTER_ALIGN_HORIZONTAL. WIth the Vertical splitter, your 2 gadgets
  193.         ;//                                       to wich it applies should be left/right of eachother
  194.         ;//                                       With the Horizontal splitter, your 2 gadgets to wich the splitter applies
  195.         ;//                                       should be above/underneath eachother.
  196.         ;//
  197.         ;// You do not have to care about the positioning of the 2 gadgets, this will all be handled
  198.         ;// by the Splitter code.
  199.         mySplitter.Splitter     = CreateSplitter(frmMain, pnlWorkSpace, pnlProperties, SPLITTER_ALIGN_VERTICAL)
  200.        
  201.        
  202.         ;// now we enter the main eventloop for the form and check for messages
  203.         ;// The messages we want to handle for the splitter are:
  204.         ;// WM_RESIZE and WM_MOUSEMOVE
  205.         Repeat
  206.        
  207.                 Select(WaitEvent())
  208.                         Case WM_CLOSE           ;// $803 Form close event
  209.                                 End
  210.                        
  211.                         Case WM_RESIZE          ;// $802
  212.                                 ;// Update the splitter
  213.                                 UpdateSplitter(mySplitter)
  214.        
  215.                         Case WM_MOUSEMOVE       ;// $203
  216.                                 ;// Handle the movement
  217.                                 ;// Note that only the Canvas gadget will detect MouseMove events, so I
  218.                                 ;// added a special Canvas that streches the entire surface of the splitter
  219.                                 ;// This will detect the Mouseevents for us. we have to determine here of the
  220.                                 ;// mousemove event was fired by our splitter
  221.                                 Select(EventSource())
  222.                                         Case mySplitterCanvas
  223.                                                 SplitterEventLoop(mySplitter)
  224.  
  225.                                 End Select
  226.                        
  227.                 End Select
  228.        
  229.         Forever
  230.        
  231.         ;// Ready! Now start the app and notice the small darkgray line between the 2 panels
  232.         ;// just click on it and drag the line Left/right while holding the mousebutton to see
  233.         ;// the Splitter in action!
  234.  
  235. End Function


Comments : none...

 

SimplePortal 2.3.6 © 2008-2014, SimplePortal