• Welcome to Jose's Read Only Forum 2023.
 

Splitter Window

Started by Zlatko Vid, February 04, 2022, 10:12:48 PM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

Zlatko Vid

I can't find any splitter window example in all codes i have
i have something from other compiler and C but not in Oxygenbasic.
So i decided that i need one to split in my case listbox (listview) control from
scintilla control in AurelEdit in first place .
Splitter window is just window in most cases child window of main and his main purpose
is to divide two controls or more in same time changing they size .

'########################################################################
'create splitter window
spx = 171 : spy = 58 : spw = 8 : sph = 414
INT spStyle = WS_VISIBLE | WS_CHILD | WS_SYSMENU | WS_BORDER
splitWin = SETWINDOW("",spx,spy,spw,sph, win, spStyle)


then under WM_SIZE:
in my case splitter window is vertical but can be horizontal too
'set splitter window vertical size
MoveWindow(splitWin,spx, 58, 8,(h-76)-6 , 1 )

Zlatko Vid

What i have found so far is old XBlite code
with subclassed static control as splitter bar

FUNCTION  StaticProc (hWnd, msg, wParam, lParam)

SPLITTERDATA spdata
STATIC splitterX0, splitterY0
SHARED hCursorH, hCursorV
SHARED moveX, moveY
RECT rect
STATIC fTrackMouse
TRACKMOUSEEVENT tme

hWndParent = GetParent (hWnd)
pData = GetWindowLongA (hWndParent, $$GWL_USERDATA) ' get splitter data
IF pData THEN RtlMoveMemory (&spdata, pData, SIZE(SPLITTERDATA)) ' copy data into local struct spdata

SELECT CASE msg

CASE $$WM_LBUTTONDOWN:
style = spdata.style ' get horz or vert splitter style
IF style = $$SS_HORZ THEN
SetCursor (hCursorH) ' set cursor
ELSE
SetCursor (hCursorV)
END IF

SetCapture (hWnd) ' capture the mouse to static control

splitterX0 = LOWORD (lParam) ' get initial x mouse position
splitterY0 = HIWORD (lParam)

CASE $$WM_LBUTTONUP:
ReleaseCapture () ' release the mouse
hSplitter = GetParent (hWnd)
SendMessageA (GetParent (hSplitter), $$WM_SPITTER_BAR_MOVED, 0, 0)

CASE $$WM_MOUSELEAVE:
fTrackMouse = 0
SetCursor (LoadCursorA (0, $$IDC_ARROW)) ' change cursor back to standard arrow

CASE $$WM_MOUSEMOVE:
style = spdata.style

IF style = $$SS_HORZ THEN
last = SetCursor (hCursorH) ' change cursor
ELSE
last = SetCursor (hCursorV)
END IF

IFZ fTrackMouse THEN
tme.cbSize = SIZE(tme)
tme.dwFlags = $$TME_LEAVE
tme.hwndTrack = hWnd
ret = TrackMouseEvent (&tme)
fTrackMouse = $$TRUE
END IF

IF (wParam & $$MK_LBUTTON) THEN ' left button down (drag)

IF style = $$SS_HORZ THEN
moveX = LOWORD (lParam) - splitterX0 ' get delta x mouse position
IFZ moveX THEN RETURN
ELSE
moveY = HIWORD (lParam) - splitterY0
IFZ moveY THEN RETURN
END IF

GetClientRect (hWndParent, &rect) ' get parent size and send WM_SIZE message to splitter control
SendMessageA (hWndParent, $$WM_SIZE, 0, MAKELONG(rect.right, rect.bottom))
END IF

CASE ELSE :
RETURN CallWindowProcA (#old_proc, hWnd, msg, wParam, lParam)

END SELECT

END FUNCTION

Zlatko Vid

Also
I found one from PowerBasic Garry Beene snippets.
I complile it with PB10.3 and work well.

'Compilable Example:
#COMPILER PBWIN 9, PBWIN 10
#COMPILE EXE
#DIM ALL
#DEBUG ERROR ON     'catch array/pointer errors - OFF in production
#DEBUG DISPLAY ON   'display untrapped errors   - OFF in production
#INCLUDE "Win32api.inc"
#RESOURCE "gbsnippets.pbr"

%IDC_Left = 500 : %IDC_Right = 501 : %IDC_Bottom = 502
%IDC_LabelH = 532 : %IDC_LabelV = 533 : %IDC_StatusBar = 536 : %IDM_Alternate = 534
%IDC_Toolbar = 537 : %IDM_ShowBottom = 600 : %IDM_Fixed = 601 : %IDT_New = 602
%ID_ImageList = 700 : %IDT_X = 701 : %IDT_Y = 702 : %IDT_Z = 703

' Global Variables: handles =============================================================
GLOBAL hDlg AS DWORD, hTree AS DWORD, hList AS DWORD, hMenu AS DWORD
GLOBAL SplitVInWork AS LONG, SplitHInWork AS LONG, ShowBottom&, hMenuOptions AS DWORD
GLOBAL XSplit AS SINGLE, YSplit AS SINGLE, AlternateLayout&, hLst AS DWORD
GLOBAL HBarLeft AS LONG, VBarTop AS LONG, FixedSplitterBar&

' Main Function =======================================================================

FUNCTION PBMAIN()
   DIALOG NEW PIXELS, 0, "Splitter Text",300,300,410,340, %WS_OVERLAPPEDWINDOW OR %WS_CLIPCHILDREN TO hDlg
   CONTROL ADD STATUSBAR, hDlg, %IDC_StatusBar, "",0,0,0,0     'xy, xxyy ignored, %ccs_bottom by default

   CONTROL ADD TOOLBAR, hDlg, %IDC_Toolbar, "Toolbar",0,0,0,0                    'xy, xxyy, txt$ ignored, %ccs_top by default
   'create imagelist for Toolbar
   IMAGELIST NEW ICON 16,16,32,3 TO hLst
   IMAGELIST ADD ICON hLst, "x"              '1
   IMAGELIST ADD ICON hLst, "y"              '2
   IMAGELIST ADD ICON hLst, "z"              '3
   'attach imagelist
   TOOLBAR SET IMAGELIST hDlg, %IDC_Toolbar, hLst, 0
   'create buttons
   TOOLBAR ADD BUTTON  hDlg, %IDC_Toolbar, 1, %IDT_X, %TBSTYLE_CHECK, "X"
   TOOLBAR ADD BUTTON  hDlg, %IDC_Toolbar, 2, %IDT_Y, %TBSTYLE_CHECK, "Y"
   TOOLBAR ADD BUTTON  hDlg, %IDC_Toolbar, 3, %IDT_Y, %TBSTYLE_CHECK, "Z"

   'create menu
   MENU NEW BAR TO hMenu
   MENU NEW POPUP TO hMenuOptions
   MENU ADD POPUP, hMenu, "&Options", hMenuOptions, %MF_ENABLED
   MENU ADD STRING, hMenuOptions, "&Alternate Layout", %IDM_Alternate, %MF_ENABLED
   MENU ADD STRING, hMenuOptions, "&Hide Bottom", %IDM_ShowBottom, %MF_ENABLED
   MENU ADD STRING, hMenuOptions, "&Fixed Position", %IDM_Fixed, %MF_ENABLED
   MENU ATTACH hMenu, hDlg
                                                                                     

Theo Gottwald

The XSed-Editor from XBLite (last Sign of Live in 2020) was made as a fork from Jose's SED-Editor.
So in Jose's code there should also be this feature.

Zlatko Vid

Yes Theo it is by Jose
and yes it have splitter but horizontal with some sort of tiny button or
rebar docker or something ..but i need simple splitter nothing fancy
by the way Garry example work well too.
spliter from XBlite as splitter from Powerbasic ..both uses static control if i get it right
in PB is called LABEL.

In o2 i use child Window..and finally get it that mouse pointer cursor
change when is over that splitter window

SELECT hWnd

CASE splitWin

    select wMsg

         CASE WM_LBUTTONDOWN


         CASE WM_MOUSEMOVE
              GetMouseX = LoWord(lParam)
              GetMouseY = HiWord(lParam)

             if (GetMouseX > spx+1) or (GetMouseX < spx+7)
                SetCursor(LoadCursor(0, IDC_SIZEWE)) ' change cursor back to standard arrow
             end if
             

    end select

Zlatko Vid

Well so far nothing
this DDT syntax is very awkward and is not easy to translate code from PowerBasic to OxygenBasic
even on PB Garry examples work really well and properly ...also he use Dialogs not Windows.
Garry made great job with all this snippets..
There is example without subclassing :

   'Features:
'1. Two different layouts
'2. Both a horizontal and vertical splitter bars (horizontal bar can be removed)
'3. Splitter bar positions can be fixed position or positioned on a percentage basis

'Primary Code;
'Due to the length of this example, on a description will be covered in this section.
'See the compilable example below for the source code.

'Splitter bar action is accomplished by detecting the presence of a mouse click and
'drag movement. This can be done by monitoring mouse action over a control, over simply
'over an area of the dialog. This approach uses label controls as the splitter bars - one
'for vertical splitting and one for horizontal splitting.

'The code sections/functions used in the compilable example below are:
'1. %WM_SetCursor            - detects mouse clicks and movement
'2. Sub MoveBarUpDown        - moves horizontal bar in response to mouse action
'3. Sub MoveBarLeftRight     - moves vertical bar in response to mouse action
'4. Sub ResizeWindow         - adjusts controls in response to user resizing of dialog
'5. Sub ResizeSplitterBars   - adjust splitter bars in response to user resizing of dialog
'6. Sub SetControlVisibility - used to show/hide controls according to layout option selection


'Compilable Example:
#COMPILER PBWIN 9, PBWIN 10
#COMPILE EXE
#DIM ALL
#DEBUG ERROR ON     'catch array/pointer errors - OFF in production
#DEBUG DISPLAY ON   'display untrapped errors   - OFF in production
#INCLUDE "Win32api.inc"
#RESOURCE "gbsnippets.pbr"

%IDC_Left = 500 : %IDC_Right = 501 : %IDC_Bottom = 502
%IDC_LabelH = 532 : %IDC_LabelV = 533 : %IDC_StatusBar = 536 : %IDM_Alternate = 534
%IDC_Toolbar = 537 : %IDM_ShowBottom = 600 : %IDM_Fixed = 601 : %IDT_New = 602
%ID_ImageList = 700 : %IDT_X = 701 : %IDT_Y = 702 : %IDT_Z = 703

' Global Variables: handles =============================================================
GLOBAL hDlg AS DWORD, hTree AS DWORD, hList AS DWORD, hMenu AS DWORD
GLOBAL SplitVInWork AS LONG, SplitHInWork AS LONG, ShowBottom&, hMenuOptions AS DWORD
GLOBAL XSplit AS SINGLE, YSplit AS SINGLE, AlternateLayout&, hLst AS DWORD
GLOBAL HBarLeft AS LONG, VBarTop AS LONG, FixedSplitterBar&

' Main Function =======================================================================

FUNCTION PBMAIN()
   DIALOG NEW PIXELS, 0, "Splitter Text",300,300,410,340, %WS_OVERLAPPEDWINDOW OR %WS_CLIPCHILDREN TO hDlg
   CONTROL ADD STATUSBAR, hDlg, %IDC_StatusBar, "",0,0,0,0     'xy, xxyy ignored, %ccs_bottom by default

   CONTROL ADD TOOLBAR, hDlg, %IDC_Toolbar, "Toolbar",0,0,0,0                    'xy, xxyy, txt$ ignored, %ccs_top by default
   'create imagelist for Toolbar
   IMAGELIST NEW ICON 16,16,32,3 TO hLst
   IMAGELIST ADD ICON hLst, "x"              '1
   IMAGELIST ADD ICON hLst, "y"              '2
   IMAGELIST ADD ICON hLst, "z"              '3
   'attach imagelist
   TOOLBAR SET IMAGELIST hDlg, %IDC_Toolbar, hLst, 0
   'create buttons
   TOOLBAR ADD BUTTON  hDlg, %IDC_Toolbar, 1, %IDT_X, %TBSTYLE_CHECK, "X"
   TOOLBAR ADD BUTTON  hDlg, %IDC_Toolbar, 2, %IDT_Y, %TBSTYLE_CHECK, "Y"
   TOOLBAR ADD BUTTON  hDlg, %IDC_Toolbar, 3, %IDT_Y, %TBSTYLE_CHECK, "Z"

   'create menu
   MENU NEW BAR TO hMenu
   MENU NEW POPUP TO hMenuOptions
   MENU ADD POPUP, hMenu, "&Options", hMenuOptions, %MF_ENABLED
   MENU ADD STRING, hMenuOptions, "&Alternate Layout", %IDM_Alternate, %MF_ENABLED
   MENU ADD STRING, hMenuOptions, "&Hide Bottom", %IDM_ShowBottom, %MF_ENABLED
   MENU ADD STRING, hMenuOptions, "&Fixed Position", %IDM_Fixed, %MF_ENABLED
   MENU ATTACH hMenu, hDlg

   'add the controls + splitter bars (labels)
   CONTROL ADD TEXTBOX, hDlg, %IDC_Left, "TopLeft",  20, 80, 160, 80
   CONTROL ADD TEXTBOX, hDlg, %IDC_Bottom, "Bottom",  20, 200, 370, 90
   CONTROL ADD TEXTBOX, hDlg, %IDC_Right, "TopRight", 220, 55, 170, 100
   CONTROL ADD LABEL, hDlg, %IDC_LabelH, "",  200, 45, 6, 125, %SS_NOTIFY , %WS_EX_CLIENTEDGE  ' up/down - does horizontal split
   CONTROL ADD LABEL, hDlg, %IDC_LabelV, "",  0,170, 410, 6, %SS_NOTIFY , %WS_EX_CLIENTEDGE   ' left/right - does vertical split

   XSplit = 0.5 : YSplit = 0.5 : ShowBottom& = 1 : HBarLeft = 100 : VBarTop = 100
   MENU SET STATE hMenuOptions, BYCMD %IDM_ShowBottom, ShowBottom& * 8

   DIALOG SHOW MODAL hDlg CALL DlgProc()
END FUNCTION

   'monitor mouse movement=================================

CALLBACK FUNCTION DlgProc() AS LONG
   LOCAL iReturn AS LONG, x AS LONG, y AS LONG, w AS LONG, h AS LONG
   SELECT CASE CB.MSG
      CASE %WM_COMMAND
         SELECT CASE CB.CTL
            CASE %IDM_Alternate
               AlternateLayout& = AlternateLayout&  XOR 1     'flip between 0 and 1
               MENU SET STATE hMenuOptions, BYCMD %IDM_Alternate, AlternateLayout& * 8
               ResizeWindow
            CASE %IDM_ShowBottom
               ShowBottom& = ShowBottom&  XOR 1     'flip between 0 and 1
               MENU SET STATE hMenuOptions, BYCMD %IDM_ShowBottom, ShowBottom& * 8
               ResizeWindow
            CASE %IDM_Fixed
               FixedSplitterBar& = FixedSplitterBar&  XOR 1     'flip between 0 and 1
               MENU SET STATE hMenuOptions, BYCMD %IDM_Fixed, FixedSplitterBar& * 8
               DIALOG GET CLIENT hDlg TO w,h
               'adjusts VBarTop/HBarLeft or xSplit/ySplit when option is changed
               'both are not kept current at all times - only the pair in use
               IF FixedSplitterBar& THEN
                  VBarTop = h - ySplit * h
                  HBarLeft = xSplit * w
               ELSE
                  ySplit = (h-VBarTop) / h
                  xSplit = HBarLeft / w
               END IF
               ResizeWindow
            CASE %IDT_X, %IDT_Y, %IDT_Z
               MSGBOX "No action. Toolbar included just to show how splitter bars work with toolbar in place.", %MB_OK + %MB_ICONINFORMATION, "Toolbar Button Pressed"
         END SELECT
      CASE %WM_SIZE
         ResizeWindow
      CASE %WM_SetCursor
         iReturn = GetDlgCtrlID  (CB.WPARAM)
         'identify over which label control the mouse action took place
         IF iReturn = %IDC_LabelH THEN MOUSEPTR 9 : FUNCTION = 1    '9 = horizontal cursor
         IF iReturn = %IDC_LabelV THEN MOUSEPTR 7 : FUNCTION = 1    '7 = vertical cursor

         'monitors the 3 basic splitter bar mouse actions, lbuttondown, mousemose, lbuttonup
         SELECT CASE HI(WORD, CB.LPARAM)
            CASE %WM_LBUTTONDOWN
               'sets flags to say splitter action has started (no actual movement yet)
               IF iReturn = %IDC_LabelV THEN SplitVInWork = 1
               IF iReturn = %IDC_LabelH THEN SplitHInWork = 1
            CASE %WM_MOUSEMOVE
               'Repositions splitter bars to match mouse position (if position has changed)
               IF SplitVInWork THEN IF MoveBarUpDown THEN ResizeWindow
               IF SplitHInWork THEN IF MoveBarLeftRight THEN ResizeWindow
            CASE %WM_LBUTTONUP
               'sets flags to say splitter action has ended
               SplitHInWork = 0 : SplitVInWork = 0
         END SELECT
   END SELECT
END FUNCTION

FUNCTION MoveBarUpDown AS LONG
   LOCAL pt AS POINT, h AS LONG, w AS LONG
   STATIC oldY AS LONG
   DIALOG GET CLIENT hDlg TO w,h
   GetCursorPos pt               'pt has xy screen coordinates
   ScreenToClient hDlg, pt       'pt now has client coordinates
   '    If h-pt.y < 50 Then Exit Function   'limit right motion   'optional
   '    If pt.y < 50 Then Exit Function                            'optional
   YSplit = (pt.y-3) / h         'actually, should only do one or the other
   VBarTop = h - (Pt.y-3)        'actually, should only do one or the other
   IF pt.y <> oldY THEN FUNCTION = %True : oldY = pt.y
END FUNCTION

FUNCTION MoveBarLeftRight AS LONG
   LOCAL pt AS POINT, h AS LONG, w AS LONG
   STATIC oldX AS LONG
   DIALOG GET CLIENT hDlg TO w,h
   GetCursorPos pt               'pt has xy screen coordinates
   ScreenToClient hDlg, pt       'pt now has client coordinates
   '    If w-pt.x < 50 Then Exit Function   'limit right motion       'optional
   '    If pt.x < 50 Then Exit Function                                 'optional
   XSplit = (pt.x-3) / w        'actually, should only do one or the other
   HBarLeft = pt.x-3            'actually, should only do one or the other
   IF pt.x <> oldX THEN FUNCTION = %True : oldX = pt.x
END FUNCTION

SUB ResizeWindow
   LOCAL vx AS LONG, vy AS LONG, hx AS LONG, hy AS LONG, h AS LONG, w AS LONG

   SetControlVisibility
   ResizeSplitterBars

   DIALOG GET SIZE hDlg TO w,h
   CONTROL GET LOC hDlg, %IDC_LabelH TO hx, hy
   CONTROL GET LOC hDlg, %IDC_LabelV TO vx, vy

   'Resize  controls
   IF ShowBottom& = 0 THEN
      'simple side by side of tree and richedit
      CONTROL SET LOC  hDlg, %IDC_Left, 5, 47
      CONTROL SET SIZE hDlg, %IDC_Left, hx - 10, h - 122
      CONTROL SET LOC  hDlg, %IDC_Right, hx + 9, 47
      CONTROL SET SIZE hDlg, %IDC_Right, w - hx - 24, h - 122

      STATUSBAR SET PARTS hDlg, %IDC_StatusBar, w/3, w/3, w/3

   ELSEIF AlternateLayout& = 0 THEN
      'left beside right - both over bottom
      CONTROL SET LOC  hDlg, %IDC_Left, 5, 47
      CONTROL SET SIZE hDlg, %IDC_Left, hx - 10, vy - 50

      CONTROL SET LOC  hDlg, %IDC_Right, hx + 9, 47
      CONTROL SET SIZE hDlg, %IDC_Right, w - hx - 24, vy - 50

      CONTROL SET LOC  hDlg, %IDC_Bottom, 5, vy + 8
      CONTROL SET SIZE hDlg, %IDC_Bottom, w - 20, h - vy - 85

      STATUSBAR SET PARTS hDlg, %IDC_StatusBar, w/3, w/3, w/3

   ELSEIF AlternateLayout& THEN
      'left over bottom, right top-to-bottom of page
      CONTROL SET LOC  hDlg, %IDC_Left, 5, 47
      CONTROL SET SIZE hDlg, %IDC_Left, hx - 10, vy - 50

      CONTROL SET LOC  hDlg, %IDC_Right, hx + 9, 47
      CONTROL SET SIZE hDlg, %IDC_Right, w - hx - 24, h - 122

      CONTROL SET LOC  hDlg, %IDC_Bottom, 5, vy + 8
      CONTROL SET SIZE hDlg, %IDC_Bottom, hx - 10, h - vy - 85

      STATUSBAR SET PARTS hDlg, %IDC_StatusBar, w/3, w/3, w/3

   END IF

   DIALOG REDRAW hDlg

END SUB

SUB ResizeSplitterBars
   LOCAL h AS LONG, w AS LONG, HLeft AS LONG, VTop AS LONG
   DIALOG GET CLIENT hDlg TO w,h

   'position does not depend on layout
   IF FixedSplitterBar& THEN
      VTop = h - VBarTop
      HLeft = HBarLeft
   ELSE
      VTop = ySplit*h
      HLeft = xSplit*w
   END IF

   CONTROL SET LOC hDlg,  %IDC_LabelV, 5, VTop
   CONTROL SET LOC hDlg,  %IDC_LabelH, HLeft, 45

   IF ShowBottom& = 0 THEN
      CONTROL SET SIZE hDlg, %IDC_LabelH, 6, h-66           'tree + richedit only
   ELSEIF AlternateLayout& = 0 THEN
      CONTROL SET SIZE hDlg, %IDC_LabelV, w-12, 6
      CONTROL SET SIZE hDlg, %IDc_LabelH, 6, VTop-48
   ELSEIF AlternateLayout& THEN
      'tree over listview. richedit top-to-bottom of page
      CONTROL SET SIZE hDlg, %IDC_LabelV, HLeft-10, 6
      CONTROL SET SIZE hDlg, %IDC_LabelH, 6, h - 66
   END IF
END SUB

SUB SetControlVisibility
   'Find controls are always visible
   'Left, Right Controls are always visible
   IF ShowBottom& = 0 THEN
      'simple side by side of left and right (no bottom)
      CONTROL SHOW STATE hDlg, %IDC_LabelV, %SW_HIDE
      CONTROL SHOW STATE hDlg, %IDC_Bottom, %SW_HIDE
      CONTROL SHOW STATE hDlg, %IDC_Statusbar, %SW_SHOW
   ELSE
      'either layout, with bottom showing
      'left beside right, both ver bottom OR
      'left over bottom, right top-to-bottom of page
      CONTROL SHOW STATE hDlg, %IDC_LabelV, %SW_SHOW
      CONTROL SHOW STATE hDlg, %IDC_Bottom, %SW_SHOW
      CONTROL SHOW STATE hDlg, %IDC_Statusbar, %SW_SHOW
   END IF
END SUB

Pierre Bellisle

Here is an example of a splitter using a modal dialog...


//KickResource "D:\Dev\Oxygen\o2\~code\~~~Resource.res" //Kick precompiler add a manifest for CommonControl-6 to co2.exe
//KickSwicht -run -64
//KickEnd

'*Add a resource manifest

'See interesting autosizing '\Oxygen\o2\demos\WinGUI\Autosizing\Demo7Dlg.o2bas

#autodim off

uses dialogs // \Oxygen\o2\inc\Dialogs.inc

%EditTop            101
%EditBot            102
%SplitHorz          902
%WM_NCACTIVATE      0x086
%WM_GETMINMAXINFO   0x0024
%WM_SETCURSOR       0x0020
%WM_NEXTDLGCTL      0x28
%IDC_SIZENS         32645
%IMAGE_CURSOR       2
%LR_LOADTRANSPARENT 0x20
%LR_SHARED          0x8000
%HWND_DESKTOP       0
%SIZE_MINIMIZED     1
%RDW_FRAME          0x0400
%RDW_ERASE          0x0004
%RDW_INVALIDATE     0x0001
%DWLP_MSGRESULT     0

type POINTFLOAT
single x
single y
end type

function MakeIntResource(byval word wInteger) as dword
return wInteger
end function

%ICC_STANDARD_CLASSES 0x4000

type INIT_COMMON_CONTROLSEX
DWORD dwSize
DWORD dwICC
end type

! function InitCommonControlsEx lib "COMCTL32.DLL" ALIAS "InitCommonControlsEx"
(BYREF lpInitCtrls AS INIT_COMMON_CONTROLSEX) as long 'nzok
'_____________________________________________________________________________

function DlgProc(sys hDlg, uint uMsg, sys wParam, lParam) as bool callback
static point      DlgArea
        point      CursorPos
static point      Delta
static point      SplitPos
static pointfloat Ratio
        rect       rcSplitHorz
static sys        hCursorUpDwn
static sys        hSplitHorz
static sys        hEditTop
static sys        hEditBot
static dword      Marge
static sys        hDragging

select case uMsg
   case WM_INITDIALOG
     static sys hBrush = CreateSolidBrush(Blue)
     static sys hIcon = ExtractIcon(GETMODULEHANDLE(""), "Shell32.dll", 294) 'o
     SendMessage(hDlg, WM_SETICON, ICON_SMALL, hIcon)

     hEditTop     = GetDlgItem(hDlg, EditTop)
     hEditBot     = GetDlgItem(hDlg, EditBot)
     hSplitHorz   = GetDlgItem(hDlg, SplitHorz)
     hCursorUpDwn = LoadCursor(NULL, MakeIntResource(IDC_SIZENS))

     GetWindowRect(hSplitHorz, rcSplitHorz)
     MapWindowPoints(HWND_DESKTOP, hDlg, @rcSplitHorz, 2)
     Marge = rcSplitHorz.Left * 2
     Ratio.Y = 0.40 'Top of splitter bar / height of client area

     PostMessage(hEditTop, %EM_SETSEL, -1, 0) 'Set caret at the end of text

   case WM_COMMAND
     sys id    = loword(wParam)
     sys event = hiword(wParam)
     select case id
       case IDCANCEL 'Escape key
         EndDialog(hDlg, 0)
     end select

   case WM_SETCURSOR
     if wParam = hSplitHorz then
       SetCursor(hCursorUpDwn)
       SetWindowLongPtr(hDlg, DWLP_MSGRESULT, true)
       if hiword(LPARAM) = WM_LBUTTONDOWN then
         GetCursorPos(CursorPos)
         ScreenToClient(hDlg, CursorPos)
         Delta.y = CursorPos.y - SplitPos.y 'Offset between top of splitter bar and vertical cursor position inside splitter bar
         hDragging = wParam
         SetCapture(hDlg) 'To get cursor pos and button-up feedback even when the cursor is not inside the dialog.
       end if
       return true
     end if
     return false

   case WM_MOUSEMOVE
     if hDragging = hSplitHorz then 'Cursor on horizontal splitterbar
       CursorPos.y = hiword(LPARAM)
       if CursorPos.y >= Delta.y + 5 then 'Prevent over top border dialog limit
         if CursorPos.y <= DlgArea.y - Delta.y - 5 then 'Prevent over bottom border dialog limit
           SplitPos.y = CursorPos.y - Delta.y
           Ratio.Y    = SplitPos.y / DlgArea.Y
           MoveWindow(hSplitHorz, Marge, SplitPos.y, DlgArea.x - Marge * 2, Marge \ 2, true)
           MoveWindow(hEditBot, Marge, SplitPos.y + Marge, DlgArea.x - Marge * 2, DlgArea.Y - SplitPos.y - Marge * 2, true)
           MoveWindow(hEditTop, Marge, Marge, DlgArea.X - Marge * 2, convert long(SplitPos.y - Marge * 1.7), true)
         end if
       end if
     end if

   case WM_LBUTTONUP 'Left mouse button down to up transition
     if hDragging then
       ReleaseCapture() 'See SetCapture()
       hDragging = false
     end if

   case WM_SIZE
     if wParam <> SIZE_MINIMIZED then
       DlgArea.X  = loword(LPARAM)
       DlgArea.Y  = hiword(LPARAM)
       SplitPos.y = DlgArea.Y * Ratio.Y
       if SplitPos.y > DlgArea.Y - Marge then SplitPos.y = DlgArea.Y - Marge 'Prevent over top dialog limit
       if SplitPos.y < 1 then SplitPos.y = 1 'Prevent under bottom dialog limit
       MoveWindow(hSplitHorz, Marge, SplitPos.y, DlgArea.x - Marge * 2, Marge \ 2, true)
       MoveWindow(hEditBot, Marge, SplitPos.y + Marge, DlgArea.x - Marge * 2, convert long(DlgArea.Y - SplitPos.y - Marge * 2), true)
       MoveWindow(hEditTop, Marge, Marge, convert long(DlgArea.X - Marge * 2), convert long(SplitPos.y - Marge * 1.7), true)
       RedrawWindow(hEditBot, BYVAL NULL, BYVAL NULL, RDW_FRAME | RDW_ERASE | RDW_INVALIDATE)
     end if

   case WM_GETMINMAXINFO
     MINMAXINFO *MinMaxInfoPtr
     @MinMaxInfoPtr = lParam
     MinMaxInfoPtr.ptMinTrackSize.X = 350
     MinMaxInfoPtr.ptMinTrackSize.Y = 100

   case WM_NCACTIVATE
     static sys hFocusBak
     if wParam = false then 'Application loose focus
       hFocusBak = GetFocus()
     elseif hFocusBak then
       SendMessage(hDlg, WM_NEXTDLGCTL, hFocusBak, 1)
       hFocusBak = false
     end if
     return false

   case WM_CTLCOLORSTATIC
     if lParam = hSplitHorz then
       return(hBrush)
     end if

    case WM_CLOSE
      EndDialog(hDlg, 0)

    case WM_DESTROY
      DestroyIcon(hIcon)
      DeleteObject(hBrush)

   case else
     return false

end select

return true

end function
'_____________________________________________________________________________

function WinMain()

INIT_COMMON_CONTROLSEX InitControlStruct
InitControlStruct.dwSize = SIZEOF(INIT_COMMON_CONTROLSEX)
InitControlStruct.dwICC  = %ICC_STANDARD_CLASSES
InitCommonControlsEX(InitControlStruct)

Dialog(0, 0, 250, 200, "SplitterBar" & sizeof(sys) * 8, WS_VISIBLE | WS_CAPTION | WS_MINIMIZEBOX |
WS_MAXIMIZEBOX | WS_SIZEBOX | WS_SYSMENU | WS_CLIPSIBLINGS | DS_CENTER | DS_SETFONT, 10, "Segoe UI", 0)

string sEdit = quote
-EditQuote-  You may resize this dialog in both directions.
The blue STATIC act as splitterbar.
Action should be appropriate even when the drag goes very fast or out of border
-EditQuote-

Control(sEdit, EditTop, "Edit", ES_MULTILINE | ES_LEFT | ES_MULTILINE | WS_TABSTOP | WS_VSCROLL,
2, 2, 246, 100, WS_EX_LEFT | WS_EX_CLIENTEDGE, 0)

Control("", SplitHorz, "Static", WS_CHILD | WS_VISIBLE | SS_NOTIFY, 2, 103, 246, 2, 0, 0)

sEdit = quote
-EditQuote-  The splitterbar will stop at the maximum top and maximum bottom.
If the dialog is resized vertically, the splitterbar will move in proportion.
The mouse cursor will change to IDC_SIZENS north-south double arrow when over the splitterbar.
Maximizing the window is no problem.
-EditQuote-

Control(sEdit, EditBot, "Edit", ES_MULTILINE | ES_LEFT | ES_MULTILINE | WS_TABSTOP | WS_VSCROLL,
2, 106, 246, 90, WS_EX_LEFT | WS_EX_CLIENTEDGE, 0)

CreateModalDialog(null, @DlgProc, 0)

end function
'_____________________________________________________________________________

WinMain()
end
'_____________________________________________________________________________
'

Pierre Bellisle

#7
An other example of a splitter using SDK...


//KickResource "D:\Dev\Oxygen\o2\~code\~~~Resource.res" //Kick add a manifest for CommonControl-6
//KickEnd

//*See also D:\Dev\Oxygen\o2\demos\WinGUI\Autosizing\Demo7Dlg.o2bas

//*Add a resource manifest

#autodim off

uses dialogs

%EditTop                 101
%EditBot                 102
%SplitHorz               902
%WM_NCACTIVATE           0x086
%WM_GETMINMAXINFO        0x0024
%WM_SETCURSOR            0x0020
%WM_NEXTDLGCTL           0x28
%IDC_SIZENS              32645
%HWND_DESKTOP            0
%SIZE_MINIMIZED          1
%RDW_FRAME               0x0400
%RDW_ERASE               0x0004
%RDW_INVALIDATE          0x0001
%SPI_GETICONTITLELOGFONT 0x001F
%COLOR_BTNFACE           15

type NONCLIENTMETRICS
long    cbSize
long    iBorderWidth
long    iScrollWidth
long    iScrollHeight
long    iCaptionWidth
LOGFONT iCaptionHeight
long    lfCaptionFont
long    iSMCaptionWidth
LOGFONT iSMCaptionHeight
long    lfSMCaptionFont
long    iMenuWidth
LOGFONT iMenuHeight
LOGFONT lfMenuFont
LOGFONT lfStatusFont
LOGFONT fMessageFont
end type

type POINTFLOAT
single x
single y
end type

function MakeIntResource(byval word wInteger) as dword
return wInteger
end function

%ICC_STANDARD_CLASSES 0x4000

type INIT_COMMON_CONTROLSEX
DWORD dwSize
DWORD dwICC
end type

! function InitCommonControlsEx lib "COMCTL32.DLL" ALIAS "InitCommonControlsEx"(BYREF lpInitCtrls AS INIT_COMMON_CONTROLSEX) as long
'_____________________________________________________________________________

function WndProc(sys hWnd, wMsg, wParam, lparam) as sys callback
static point      DlgArea
        point      CursorPos
static point      Delta
static point      SplitPos
static pointfloat Ratio
        rect       rcSplitHorz
static sys        hCursorUpDwn
static dword      Marge
static sys        hDragging
static sys        hEditTop
static sys        hSplitHorz
static sys        hEditBot

select case wMsg

   case WM_CREATE
     static sys hBrush = CreateSolidBrush(Blue)
     hCursorUpDwn = LoadCursor(NULL, MakeIntResource(IDC_SIZENS))
     PostMessage(hEditTop, %EM_SETSEL, -1, 0) 'Set caret at the end of text
     PostMessage(hEditBot, %EM_SETSEL, -1, 0) 'Set caret at the end of text
     return(1)

   case WM_COMMAND
     sys id    = loword(wParam)
     sys event = hiword(wParam)
     select case id
       case IDCANCEL 'Escape key
         SendMessage(hwnd, WM_CLOSE, 0, 0)
         return(0)
     end select

   case WM_SETCURSOR
     if wParam = hSplitHorz then
       SetCursor(hCursorUpDwn)
       if hiword(LPARAM) = WM_LBUTTONDOWN then 'Left mouse button up to down transition
         GetCursorPos(CursorPos)
         ScreenToClient(hWnd, CursorPos)
         Delta.y = CursorPos.y - SplitPos.y 'Offset between top of splitter bar and vertical cursor position inside splitter bar
         hDragging = wParam
         SetCapture(hWnd) 'To get cursor pos and button-up feedback even when the cursor is not inside the dialog.
       end if
       return(true)
     end if

   case WM_MOUSEMOVE
     if hDragging = hSplitHorz then 'Cursor on horizontal splitterbar
       CursorPos.y = hiword(LPARAM)
       if CursorPos.y >= Delta.y + 5 then 'Prevent over top border dialog limit
         if CursorPos.y <= DlgArea.y - Delta.y - 5 then 'Prevent over bottom border dialog limit
           SplitPos.y = CursorPos.y - Delta.y
           Ratio.Y    = SplitPos.y / DlgArea.Y
           MoveWindow(hSplitHorz, Marge, SplitPos.y, DlgArea.x - Marge * 2, Marge \ 1, true)
           MoveWindow(hEditBot, Marge, SplitPos.y + Marge * 2 - 1, DlgArea.x - Marge * 2, DlgArea.Y - SplitPos.y - Marge * 1, true)
           MoveWindow(hEditTop, Marge, Marge, DlgArea.X - Marge * 2, convert long(SplitPos.y - Marge * 1.7), true)
         end if
       end if
       return(0)
     end if

   case WM_LBUTTONUP 'Left mouse button down to up transition
     if hDragging then
       ReleaseCapture() 'See SetCapture()
       hDragging = false
       return(0)
     end if

   case WM_SIZE
     if wParam <> SIZE_MINIMIZED then
       DlgArea.X  = loword(LPARAM)
       DlgArea.Y  = hiword(LPARAM)
       if hEditBot = 0 then 'Om app start first init
         hEditTop   = GetDlgItem(hWnd, EditTop)
         hSplitHorz = GetDlgItem(hWnd, SplitHorz)
         hEditBot   = GetDlgItem(hWnd, EditBot)
         GetWindowRect(hSplitHorz, rcSplitHorz)
         MapWindowPoints(HWND_DESKTOP, hWnd, @rcSplitHorz, 2)
         Marge = rcSplitHorz.Left * 2
         Ratio.Y = 0.40 'Top of splitter bar / height of client area
       end if
       SplitPos.y = DlgArea.Y * Ratio.Y
       if SplitPos.y > DlgArea.Y - Marge then SplitPos.y = DlgArea.Y - Marge 'Prevent over top dialog limit
       if SplitPos.y < 1 then SplitPos.y = 1 'Prevent under dialog bottom limit
       MoveWindow(hSplitHorz, Marge, SplitPos.y, DlgArea.x - Marge * 2, Marge \ 1, true)
       MoveWindow(hEditBot, Marge, SplitPos.y + Marge * 2 - 1, DlgArea.x - Marge * 2, DlgArea.Y - SplitPos.y - Marge * 1, true)
       MoveWindow(hEditTop, Marge, Marge, DlgArea.X - Marge * 2, convert long(SplitPos.y - Marge * 1.7), true)
       RedrawWindow(hEditBot, BYVAL NULL, BYVAL NULL, RDW_FRAME | RDW_ERASE | RDW_INVALIDATE)
       return(0)
     end if

   case WM_GETMINMAXINFO 'Set minimim/maximum dialog size
     MINMAXINFO *MinMaxInfoPtr
     @MinMaxInfoPtr = lParam
     MinMaxInfoPtr.ptMinTrackSize.X = 350
     MinMaxInfoPtr.ptMinTrackSize.Y = 100
     return(0)

   case WM_NCACTIVATE
     static sys hFocusBak
     if wParam = false then 'Application loose focus
       hFocusBak = GetFocus()
       return(true)
     elseif hFocusBak then
       SendMessage(hWnd, WM_NEXTDLGCTL, hFocusBak, 1)
       hFocusBak = false
       return(0)
     end if
     return(DefWindowProc(hWnd, wMsg, wParam, lParam))

   case WM_CTLCOLORSTATIC
     if lParam = hSplitHorz then
       return(hBrush)
     end if

   case WM_KEYDOWN
     Select wParam
    Case 27
       SendMessage(hwnd, WM_CLOSE, 0, 0) 'Escape key to exit
       return(0)
     End Select

    case WM_DESTROY
      DeleteObject(hBrush)
      PostQuitMessage(0)
      return(0)

end select

return(DefWindowProc(hWnd, wMsg, wParam, lParam))

end function
'_____________________________________________________________________________

function WinMain()

NONCLIENTMETRICS NonClient
WndClass         wc
Msg              wm
sys              inst, hwnd, hControl, hIcon, inst
sys              WindowWidth, WindowHeight, WindowPosX, WindowPosY

WindowWidth  = 250
WindowHeight = 300
WindowPosX   = (GetSystemMetrics(SM_CXSCREEN) - WindowWidth)  \ 2
WindowPosY   = (GetSystemMetrics(SM_CYSCREEN) - WindowHeight) \ 2

NonClient.cbSize = SIZEOF(NONCLIENTMETRICS)
hIcon            = ExtractIcon GETMODULEHANDLE(""), "Shell32.dll", 294 'o
inst             = GetModuleHandle(0)
wc.style         = CS_HREDRAW | CS_VREDRAW
wc.lpfnWndProc   = @WndProc
wc.cbClsExtra    = 0
wc.cbWndExtra    = 0
wc.hInstance     = inst
wc.hIcon         = hIcon
wc.hCursor       = LoadCursor(0, IDC_ARROW)
wc.hbrBackground = COLOR_BTNFACE + 1
wc.lpszMenuName  = null
wc.lpszClassName = strptr("OXYGEN BASIC")

RegisterClass(@wc)

INIT_COMMON_CONTROLSEX InitControlStruct
InitControlStruct.dwSize = SIZEOF(INIT_COMMON_CONTROLSEX)
InitControlStruct.dwICC  = %ICC_STANDARD_CLASSES
InitCommonControlsEX(InitControlStruct) 'nzok

LOGFONT LogicalFont
SystemParametersInfo(SPI_GETICONTITLELOGFONT, SIZEOF(LOGFONT), @LogicalFont, 0)
sys hFont = CreateFontIndirect(@LogicalFont)

hwnd = CreateWindowEx(0, wc.lpszClassName, "SplitterBar" & sizeof(sys) * 8 & " - o2 v. " & o2version,
                       WS_OVERLAPPED | WS_BORDER | WS_DLGFRAME | WS_CAPTION | WS_SYSMENU |
                       WS_MINIMIZEBOX | WS_SIZEBOX | WS_CLIPSIBLINGS,
                       WindowPosX, WindowPosY,
                       WindowWidth, WindowHeight, HWND_DESKTOP, 0, inst, 0)

string sEdit = quote
-EditQuote1-  You may resize this dialog in both directions.
The blue STATIC act as splitterbar.
Action should be appropriate even when the drag goes very fast or out of border
-EditQuote1-
hControl = CreateWindowEx(WS_EX_LEFT | WS_EX_CLIENTEDGE,        'Extended styles
                           "Edit",                               'Class name
                           StrPtr(sEdit),                        'Caption
                           WS_CHILD | WS_VISIBLE | WS_TABSTOP |  'Window styles
                           WS_VSCROLL |ES_MULTILINE | ES_LEFT,   'Class styles
                           2, 2,                                 'Left, top
                           246, 100,                             'Width, height
                           hWnd, EditTop,                        'Handle of parent, control ID
                           inst, NULL)                           'Handle of instance, creation parameters
SendMessage(hControl, WM_SETFONT, hFont, true)

hControl = CreateWindowEx(0,                                    'Extended styles
                           "Static",                             'Class name
                           "",                                   'Caption
                           WS_CHILD | WS_VISIBLE |               'Window styles
                           SS_NOTIFY,                            'Class styles
                           2, 103,                               'Left, top
                           246, 2,                               'Width, height
                           hWnd, SplitHorz,                      'Handle of parent, control ID
                           inst, NULL)                           'Handle of instance, creation parameters

sEdit = quote
-EditQuote2-  The splitterbar will stop at the maximum top and maximum bottom.
If the dialog is resized vertically, the splitterbar will move in proportion.
The mouse cursor will change to IDC_SIZENS north-south double arrow when over the splitterbar.
Maximizing the window is no problem.
-EditQuote2-
hControl =  CreateWindowEx(WS_EX_LEFT | WS_EX_CLIENTEDGE,        'Extended styles
                            "Edit",                               'Class name
                            StrPtr(sEdit),                        'Caption
                            WS_CHILD | WS_VISIBLE | WS_TABSTOP |  'Window styles
                            WS_VSCROLL |ES_MULTILINE | ES_LEFT,   'Class styles
                            2, 106,                               'Left, top
                            246, 90,                              'Width, height
                            hWnd, EditBot,                        'Handle of parent, control ID
                            inst, NULL)                           'Handle of instance, creation parameters
SendMessage(hControl, WM_SETFONT, hFont, true)

ShowWindow(hwnd, SW_SHOW)
UpdateWindow(hwnd)

sys bRet
do while bRet := GetMessage(@wm, 0, 0, 0)
   if bRet <> -1 then
     TranslateMessage(@wm)
     DispatchMessage(@wm)
   end if
wend

DeleteObject(hFont)

end function
'_____________________________________________________________________________

WinMain()
end
'_____________________________________________________________________________
'

Zlatko Vid


Roland Stowasser

#9
Hello,

in the Oxygen distribution there is also \demos\WinGUI\Autosizing\SmallApp.o2bas which applies some kind of a horizontal splitting window. The splitter bar can be dragged horizontally.

Zlatko Vid

From what this example come ?

is that from PowerBasic ?

and what is

MoveWindow(hEditTop, Marge, Marge, convert long(DlgArea.X - Marge * 2), convert long(SplitPos.y - Marge * 1.7), true)

i mean ..is convert some strange new command i have never see before ??

Pierre Bellisle

#11
Yep,
I did code the original in PowerBASIC.
While learning Oxygen, I thought it was a good idea to translate it.

You will find "convert" in the o2 .chm help.
Convert a type to another type, or convert an expresstio no a specific type.

PowerBASIC will most of the time convert automatically a function parameter of the wrong type,
aka a SINGLE to a DWORD or an expression as parameter.

O2 does it also,
but in this particular case...
MoveWindow(hEditTop, Marge, Marge, DlgArea.X - Marge * 2, convert long(SplitPos.y - Marge * 1.7), true)
I had bad result, all went fine as soon as I converted the expression "SplitPos.y - Marge * 1.7" to a long, using convert long().
I guess the "1.7" was the bad guy.

Note that only convert long() that have "1.7" in them must be keeped.
Some others, I forgot to remove them, they are not needed. I updated the SDK example above.

Maybe Charles will tell us the exact rules for this...




Zlatko Vid

Hi Piere

I am in process to modify your example that work with my include awinh037.inc

but i never see this before :

string sEdit = quote
-EditQuote1-  You may resize this dialog in both directions.
The blue STATIC act as splitterbar.
Action should be appropriate even when the drag goes very fast or out of border
-EditQuote1-


ouch is that new way for string ???

anyway color static to blue is great ..i like it
and whole program work really well
:)

Pierre Bellisle

Hi  Zlatko,

Don't know when it was implemented. I saw the tag name for super-quotes "quote"
while trying some code demo from Charles, "\demos\Basics\SuperQuote.o2bas" then I looked in the help.

It is indeed a pretty sharp way to easily write big multi-lines string...
One more fantastic idea from Charles that make life easier. Thank to him!

Have a great coding day...