IonicWind Software

IWBasic => General Questions => Topic started by: Andy on November 23, 2017, 05:42:52 AM

Title: Dragging controls - testing
Post by: Andy on November 23, 2017, 05:42:52 AM
I've been wondering how you can get a user to move controls - say buttons around a window.  Anne does this most days when she is playing card games on her laptop.

So I've written a new routine in the Mouse over controls file to take care of dragging controls.

Attached is the program and new (beta version of the include file).

There are three buttons, you can drag them around the window as you please, just use a bit of common sense with how fast you do it.

I think this could be used for games, visual design etc, as it should work for any type of control.

You may have to play around with the timer speed.

Could any one test it for me and give feedback please...

Thanks,
Andy. 
:)
Title: Re: Dragging controls - testing
Post by: Brian on November 23, 2017, 06:22:29 AM
Don't know what you've done, Andy, but it hasn't gone wrong for me yet!

Brian
Title: Re: Dragging controls - testing
Post by: Andy on November 23, 2017, 06:32:02 AM
Thanks Brian!

It's all in the sequence, just a few simple lines in the right order and it works.

Imagine the buttons loaded with images, say the ace of hearts, five of diamonds, and the three of clubs - you could see a card game coming.

Or, you could design a screen for designing something.

Thanks again for testing!
Andy.
:)
Title: Re: Dragging controls - testing
Post by: Brian on November 23, 2017, 06:42:18 AM
Andy,

I don't do cards, but I'm OK at Snap or spotting Mr Bun the Baker!

Brian
Title: Re: Dragging controls - testing
Post by: Egil on November 23, 2017, 08:16:20 AM
Great idea Andy!

For a long time I have been thinking about trying to make a simple WYSIWG Editor for making web pages, using the built in browser control to view the work in progress.
Maybe your Drag Control routines  can be used to place text and/or pictures in the browser window, and move them around until the design is ok.
And then scan or parse that browser control in order to produce the proper html code. Have to think about this for a while, but example certainly is a leap forward for making such an Editor possible.

Thanks for sharing!


Egil

Title: Re: Dragging controls - testing
Post by: Andy on November 23, 2017, 09:02:40 AM
Thanks so much Egil,

I will have a think on that and see what I can come up with.

Thanks for the support!! - it has so many possibilities / uses.

Andy.
:)
Title: Re: Dragging controls - testing
Post by: LarryMc on November 23, 2017, 06:52:15 PM
Maybe someone will take the idea of moving controls around and come up with an idea for a Visual Designer that generates code of some kind ::) ;)
Title: Re: Dragging controls - testing
Post by: Andy on November 23, 2017, 10:10:15 PM
The possibility did cross my mind Larry, but didn't want to step on anybodies toes.  ;)

I am going to look at Egils suggestion and see what I can come up with (that is the text and picture side of things).
:)
Title: Re: Dragging controls - testing
Post by: jalih on November 24, 2017, 01:08:16 AM
You could cheat too:


$INCLUDE "windowssdk.inc"

window w1
openwindow w1,10,20,800,800,@sysmenu,0,"Drag the controls...",&w1_handler
CONTROL w1,@BUTTON,"Drag me1",50,40,200,50,0x50000000,1
CONTROL w1,@BUTTON,"Drag me2",50,150,100,50,0x50000000,2
CONTROL w1,@BUTTON,"Drag me3",50,250,100,50,0x50000000,3

SubClassButton(w1, 1)
SubClassButton(w1, 2)
SubClassButton(w1, 3)

waituntil iswindowclosed(w1)
end

sub w1_handler(),int
  SELECT @MESSAGE
    CASE @IDCREATE
      centerwindow w1     
    CASE @IDCLOSEWINDOW
      UnSubClassButton(w1, 1)
      UnSubClassButton(w1, 2)
      UnSubClassButton(w1, 3)
      CLOSEWINDOW w1
  endselect
  RETURN 0
ENDSUB


sub ButtonHandler(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam),LRESULT
  SELECT uMsg
    case WM_NCHITTEST
      LRESULT hit = DefWindowProc(hWnd, uMsg, wParam, lParam)
      if hit = HTCLIENT then hit = HTCAPTION
      return hit
  ENDSELECT
  RETURN CallWindowProcA(GetWindowLong(hWnd, GWL_USERDATA),hWnd,uMsg,wParam,lParam)
ENDSUB


SUB SubClassButton(WINDOW parent, INT id)
  HWND hButton = GETCONTROLHANDLE(parent,id)
  WNDPROC lpFn = GetWindowLong(hButton, GWL_WNDPROC)

  if lpFn <> &ButtonHandler
    WNDPROC OldWndProc = SetWindowLongA(hButton,GWL_WNDPROC,&ButtonHandler)
    SetWindowLong(hButton, GWL_USERDATA, OldWndProc)
  endif
endsub


SUB UnSubClassButton(WINDOW parent, INT id)
  HWND hButton = GETCONTROLHANDLE(parent,id)

  WNDPROC OldWndProc = GetWindowLong(hButton, GWL_USERDATA)
  SetWindowLongA(hButton, GWL_WNDPROC, OldWndProc)
endsub


Best way to handle dragging of controls would probably be using SetCapture(), ReleaseCapture() , handle mouse messages and WM_CAPTURECHANGED. Using timer is not necessary.
Title: Re: Dragging controls - testing
Post by: Andy on November 24, 2017, 02:42:40 AM
Jalih,

Nice bit of code, don't see how that's cheating!

One thing, with your code I can only drag buttons, I added a static and a checkbox - but they would not drag.

Andy.
Title: Re: Dragging controls - testing
Post by: Brian on November 24, 2017, 03:32:48 AM
Jalih,

Nice way of moving stuff about, but it does get mixed up sometimes - I ended up with the same wording on two buttons! Seems to be losing track of which button you are working on

Brian
Title: Re: Dragging controls - testing
Post by: Egil on November 24, 2017, 04:26:32 AM
Quote from: LarryMc on November 23, 2017, 06:52:15 PM
Maybe someone will take the idea of moving controls around and come up with an idea for a Visual Designer that generates code of some kind ::) ;)

Would it be a good idea to have a kind of framework to move tings around and place them on screen, and then add "modules" that generates the code needed for IWB, PHP, HTML etc... ?

I can see many uses for such a framework. And as a "bonus" many of our coders can be involved in writing the extra modules.
Title: Re: Dragging controls - testing
Post by: jalih on November 24, 2017, 06:07:37 AM
Quote from: Brian Pugh on November 24, 2017, 03:32:48 AM
Nice way of moving stuff about, but it does get mixed up sometimes - I ended up with the same wording on two buttons! Seems to be losing track of which button you are working on

It's not losing track of buttons. You should handle refreshing and z-order of buttons, so they get redrawn correctly. All it does, it lets window think you are moving window from it's caption bar.
Title: Re: Dragging controls - testing
Post by: aurelCB on November 24, 2017, 11:44:59 AM
First of all you don't need
"windowssdk.inc"
you must know how windows API functions work
when you learn that then you know everything!
Title: Re: Dragging controls - testing
Post by: jalih on November 24, 2017, 02:07:34 PM
Quote from: aurelCB on November 24, 2017, 11:44:59 AM
First of all you don't need
"windowssdk.inc"
you must know how windows API functions work
when you learn that then you know everything!
Any real reason not to use it? I prefer to spend my time doing productive work instead of reading and searching through header files for type definitions.

Why reinvent the wheel?

Windows API is huge, try doing gdi+, direct2d, directwrite or some other COM-stuff without header files.
Title: Re: Dragging controls - testing
Post by: Brian on November 25, 2017, 02:28:42 AM
Aurel,

Don't know where you are coming from, unless you are the 1 in 1 billion people
who know the API off by heart, and can write the headers, types and declares
off the bat, and convert them to IWB format as you type

Brian
Title: Re: Dragging controls - testing
Post by: Andy on November 25, 2017, 04:58:04 AM
Aurel,

Not sure what you are saying, without header files I'd be posting 20 questions a day.

Now, continuing with the dragging code, I've now got a button (region button) loaded with Brian's on / off images.  I converted them to bitmaps.

When you place the mouse over the "off" button, it hot tracks and changes to"on" - the important thing is that this is now a picture and you can still drag it.

"Drag me 1" now has a right click context menu - the options don't do anything but you can see options for things like "properties" or "edit" etc.

Just wished I could get a flat button without a border.  I did it once by making a static act like a button, but unsure if you can add a picture to a static?

Attached are the files.

Andy.
Title: Re: Dragging controls - testing
Post by: jalih on November 25, 2017, 10:49:21 AM
Here is my final demo...

Should also work with static controls, just remember to set SS_NOTIFY style. No timer is necessary.


$INCLUDE "windowssdk.inc"

window w1
openwindow w1,10,20,800,800,@sysmenu,0,"Drag the controls...",&w1_handler
CONTROL w1,@BUTTON,"Drag me1",50,40,200,50,0x50000000,1
CONTROL w1,@BUTTON,"Drag me2",50,150,100,50,0x50000000,2
CONTROL w1,@BUTTON,"Drag me3",50,250,100,50,0x50000000,3
CONTROL w1,@STATIC,"Hey",13,300,102,340,SS_NOTIFY, 4

SubClassControl(w1, 1)
SubClassControl(w1, 2)
SubClassControl(w1, 3)
SubClassControl(w1, 4)

waituntil iswindowclosed(w1)
end

sub w1_handler(),int
  SELECT @MESSAGE
    CASE @IDCREATE
      centerwindow w1
    CASE @IDCLOSEWINDOW
      UnSubClassControl(w1, 1)
      UnSubClassControl(w1, 2)
      UnSubClassControl(w1, 3)
      UnSubClassControl(w1, 4)
      CLOSEWINDOW w1
  endselect
  RETURN 0
ENDSUB


sub DragHandler(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam),LRESULT
static int drag = FALSE
static POINT anchor
int rcWin[4]
SELECT uMsg
case WM_LBUTTONDOWN
drag = TRUE
GetWindowRect(hWnd,&rcWin)
w = rcWin[2] - rcWin[0]
h = rcWin[3] - rcWin[1]
GetCursorPos(&anchor)
anchor.x = anchor.x - rcWin[0]
anchor.y = anchor.y - rcWin[1]
BringWIndowToTop(hWnd)
SetCapture(hWnd)
return 0
case WM_LBUTTONUP
ReleaseCapture()
drag = FALSE
anchor.x = 0
anchor.y = 0
case WM_MOUSEMOVE
if drag
GetWindowRect(hWnd,&rcWin)
w = rcWin[2] - rcWin[0]
h = rcWin[3] - rcWin[1]
POINT pt
GetCursorPos(&pt)
pt.x = pt.x - anchor.x
pt.y = pt.y - anchor.y
MapWindowPoints(NULL, w1.hwnd, &pt, 1)
MoveWindow(hWnd, pt.x, pt.y, w, h, TRUE)
InvalidateRect(hWnd, NULL, TRUE)
endif
case WM_CAPTURECHANGED
drag = FALSE
InvalidateRect(hWnd, NULL, TRUE)
ENDSELECT
RETURN CallWindowProcA(GetWindowLong(hWnd, GWL_USERDATA),hWnd,uMsg,wParam,lParam)
ENDSUB


SUB SubClassControl(WINDOW parent, INT id)
  HWND hButton = GETCONTROLHANDLE(parent,id)
  WNDPROC lpFn = GetWindowLong(hButton, GWL_WNDPROC)

  if lpFn <> &DragHandler
    WNDPROC OldWndProc = SetWindowLongA(hButton,GWL_WNDPROC,&DragHandler)
    SetWindowLong(hButton, GWL_USERDATA, OldWndProc)
  endif
endsub


SUB UnSubClassControl(WINDOW parent, INT id)
  HWND hButton = GETCONTROLHANDLE(parent,id)

  WNDPROC OldWndProc = GetWindowLong(hButton, GWL_USERDATA)
  SetWindowLongA(hButton, GWL_WNDPROC, OldWndProc)
endsub
Title: Re: Dragging controls - testing
Post by: Egil on November 25, 2017, 12:35:41 PM
Quote from: jalih on November 25, 2017, 10:49:21 AM
Here is my final demo...

Great code!
And after setting a background color for the window, the beauty of it suddenly become clearer...

Thanks!


Egil
Title: Re: Dragging controls - testing
Post by: LarryMc on November 25, 2017, 05:26:54 PM
jalih's code looks like one of the very most basic parts of IWB+ without all the layers and layers of stuff stacked on (including the linked list trees, Andy) to accomplish everything else that is required.  A few controls you have to draw to look like the real controls  also, in order to get them to do in IWB+. Some you just allocate space.

Title: Re: Dragging controls - testing
Post by: aurelCB on November 26, 2017, 01:45:11 AM
Hi to all
Just to answer to Brian
You probably don't know that I am author of almost complete API headers for
Oxygen basic ( called awinh.inc )which use CDCL shape of windows api functions.
IWB(EB) can use same form
Also i have tested dll produced with IWB( in my case EB) and work with o2 compiler.
and dll produced with o2 work with IWB(EB).
also i have modifyed version of DLIB(pl) api headers too.
I hope that i explain from where i know about API functions  :D
Title: Re: Dragging controls - testing
Post by: Andy on November 26, 2017, 03:23:37 AM
Aurel,

You certainly know a lot more than me, and I can see where you are coming from with all that development.

For the rest of us "mere mortals" we rely on those header files - but obviously you don't need to!

Jalih,

Nice code,  I see you are sub classing the buttons to use a different handler, good stuff.

I think if you look through my mouse over include file at the functions available you will see a lot of coding and for "mere mortals" like myself who prefer a simple command to do all the work you want it to, then my include file is the way to go.

The whole point of me writing this file was so that any of us could add in say just 5 or 6 lines to their iwb program in a simple way to give some powerful functions.

Example:

To check if the mouse is over a control you only need 3 commands, all written for you (and yes that timer)....

1. MouseOverControl(w1,1) <--- Tell the include file the control you want to keep track of.
2. Trackwindow(w1) <--- Track the window in case it is moved / re-sized.
3. IF MouseOver(w1,1) <--- Mouse is over the control ----- do something.....

Where w1 is the window, and 1 is the control.

But as said before, nice code.

Andy.
:)
Title: Re: Dragging controls - testing
Post by: jalih on November 26, 2017, 03:24:57 AM
Quote from: aurelCB on November 26, 2017, 01:45:11 AM
Hi to all
Just to answer to Brian
You probably don't know that I am author of almost complete API headers for
Oxygen basic ( called awinh.inc )which use CDCL shape of windows api functions.
I thought Oxygen basic can read most C headers directly? Why not just use headers bundled with C compiler?
Title: Re: Dragging controls - testing
Post by: Andy on November 26, 2017, 03:41:45 AM
Aurel and Jalih,

It's a nice little debate, I appreciate all that you both do, but can we leave the header question off this post please, I think it's off track with my original question / point.

No offence meant!  :)

Andy.
Title: Re: Dragging controls - testing
Post by: aurelCB on November 26, 2017, 04:20:44 AM
jalih
QuoteI thought Oxygen basic can read most C headers directly? Why not just use headers bundled with C compiler?
no...o2 is assembler with basic-like syntax and can read some C shape of includes but not
directly....so that is about headers.

andy
your questions is hmm strange to me ..
you probably understand that any GUI object is Window
but with different parameters...so if you can move window you can move any control
in similar way.
Another thing is if you wish to build Form builder or something like that .
In most GUI designer when you activate any control creation you can see this control
only when your mouse pointer is on new window area.
Title: Re: Dragging controls - testing
Post by: aurelCB on November 26, 2017, 04:26:06 AM
oh i see now
you want to move created controls around window?
that is relatively easy
under windows message WM_MOUSEMOVE
you must add code to detect position of your control
for example if your button is
x=100,y=100
under submesagge WM_LMOUSEBUTTONDOWN
which mean when your left mouse button is down
then you use
api call - MoveWindow where you add x,y variable to track you mouse pointer
is that clear for you?
Title: Re: Dragging controls - testing
Post by: jalih on November 26, 2017, 04:29:46 AM
Quote from: Andy on November 26, 2017, 03:23:37 AM
The whole point of me writing this file was so that any of us could add in say just 5 or 6 lines to their iwb program in a simple way to give some powerful functions.

Example:

To check if the mouse is over a control you only need 3 commands, all written for you (and yes that timer)....

1. MouseOverControl(w1,1) <--- Tell the include file the control you want to keep track of.
2. Trackwindow(w1) <--- Track the window in case it is moved / re-sized.
3. IF MouseOver(w1,1) <--- Mouse is over the control ----- do something.....

Where w1 is the window, and 1 is the control.
You could subclass control and store controls parent HWND. Define your own custom window message. Inside your subclassed control handler, you handle WM_NCHITTEST message and test if result is HTCLIENT. If it is, then get mouse cursor position and send your custom window message to parent window along with controls HWND and mouse cursor position information. You can store that information inside wparam and lparam of window message.

Now parent window gets window message along with control handle and mouse cursor position, when mouse cursor moves inside controls client area.

This functionality could be encapsulated inside  two functions (add and remove tracking). Program using these functions would only need to handle your custom window message.
Title: Re: Dragging controls - testing
Post by: Andy on November 26, 2017, 04:59:15 AM
Both good ideas / suggestions, thanks - I will look into them.

So to round up the original question if my drag control command worked on other machines - yes it did.

Thanks every one for the posts / testing / suggestions, always useful and constructive.

Andy.
:)




Title: Re: Dragging controls - testing
Post by: Brian on November 26, 2017, 06:07:57 AM
Aurel,

This topic is in danger of becoming a Big Willy contest! I wish I knew more about the API without having to look them up frequently, and you must be clever to do what you have done, with your DLLS

But you started somewhere, and had some source code to get where you are now. What we are doing with the windowssdk.inc is a shortcut, admittedly. But the clever part is knowing which constant, type or declare, etc, to use given your current needs

Enough already!

Brian
Title: Re: Dragging controls - testing
Post by: jalih on November 26, 2017, 10:45:43 AM
Andy,

Here are my mouse tracking support routines for controls. You simply get window messages for mouse enter, mouse move and mouse leave.

Have fun!


$INCLUDE "windowssdk.inc"

' User defined window messages
$define MSG_TRACK_ENTER   0x4001
$define MSG_TRACK_MOVE    0x4002
$define MSG_TRACK_LEAVE   0x4003


window w1
openwindow w1,10,20,800,800,@sysmenu,0,"Mouse tracking for controls...",&w1_handler
CONTROL w1,@BUTTON,"1",50,40,200,50,0x50000000,1
CONTROL w1,@BUTTON,"2",50,150,100,50,0x50000000,2
CONTROL w1,@BUTTON,"3",50,250,100,50,0x50000000,3
CONTROL w1,@STATIC,"4",50,400,102,340,SS_NOTIFY, 4

TrackControl(w1, 1)
TrackControl(w1, 2)
TrackControl(w1, 3)
TrackControl(w1, 4)

openconsole

waituntil iswindowclosed(w1)
end

sub w1_handler(),int
SELECT @MESSAGE
CASE @IDCREATE
centerwindow w1
CASE @IDCLOSEWINDOW
UnTrackControl(w1, 1)
UnTrackControl(w1, 2)
UnTrackControl(w1, 3)
UnTrackControl(w1, 4)
CLOSEWINDOW w1
CASE MSG_TRACK_ENTER
print "Mouse Enter: ", "window handle:", @WPARAM, "x:", @LPARAM & 0xFF, "y:", @LPARAM >> 16
CASE MSG_TRACK_MOVE
print "Mouse Move : ", "window handle:", @WPARAM, "x:", @LPARAM & 0xFF, "y:", @LPARAM >> 16
CASE MSG_TRACK_LEAVE
print "Mouse Leave: ", "window handle:", @WPARAM
print ""
endselect
RETURN 0
ENDSUB


/****************************************************************************/

sub TrackHandler(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam),LRESULT
static int enter = FALSE

TRACKMOUSEEVENT tme
tme.cbSize = sizeof(tme)
tme.dwFlags = TME_LEAVE
tme.hwndTrack = hWnd
tme.dwHoverTime = HOVER_DEFAULT

pointer dat = GetWindowLong(hWnd, GWL_USERDATA)

SELECT uMsg
CASE WM_MOUSEMOVE
if !enter
enter = TRUE
TrackMouseEvent(&tme)
sendmessage(#<int>dat[0], MSG_TRACK_ENTER, hWnd, lParam)
ELSE
sendmessage(#<int>dat[0], MSG_TRACK_MOVE, hWnd, lParam)
EndIF
return 0
CASE WM_MOUSELEAVE
enter = FALSE
sendmessage(#<int>dat[0], MSG_TRACK_LEAVE, hWnd, 0)
return 0
ENDSELECT
RETURN CallWindowProcA(#<int>dat[1],hWnd,uMsg,wParam,lParam)
ENDSUB


SUB TrackControl(WINDOW parent, INT id)
  HWND hControl = GETCONTROLHANDLE(parent,id)
  WNDPROC lpFn = GetWindowLong(hControl, GWL_WNDPROC)
  pointer dat

  IF lpFn <> &TrackHandler
    WNDPROC OldWndProc = SetWindowLongA(hControl,GWL_WNDPROC,&TrackHandler)
    dat = new(int, 2)
    #<int>dat[0] = parent.hwnd
    #<int>dat[1] = OldWndProc
    SetWindowLong(hControl, GWL_USERDATA, dat)
  endif
endsub


SUB UnTrackControl(WINDOW parent, INT id)
  HWND hControl = GETCONTROLHANDLE(parent,id)

  WNDPROC lpFn = GetWindowLong(hControl, GWL_WNDPROC)
  if lpFn = &TrackHandler
    pointer dat = GetWindowLong(hControl, GWL_USERDATA)
    SetWindowLongA(hControl, GWL_WNDPROC, #<int>dat[1])
    delete dat
  endif
endsub
Title: Re: Dragging controls - testing
Post by: Andy on November 27, 2017, 07:24:45 AM
Thanks Jalih,

I will.

Think / consider this post closed now as far as I am concerned - thanks everyone.

Andy.