This include file detects when the mouse is over any type of control or window and I think has many uses.
The zip file includes an example program and a help file.
Andy.
I've added in some more commands to the mouse over controls include file which are proving to be very handy.
The commands are as follows (not documented yet in the help file):
ControlClick
ControlClickUp
ControlRClick
ControlRclickUp
int = ControlClick(MyWindow,MyControl)
Returns True (1) if the mouse is over the control and the left mouse button was clicked.
int = ControlClickUp(MyWindow,MyControl)
Returns True (1) if the mouse is over the control and the left mouse button was released.
The other two commands do exactly the same as above but when the right mouse button is clicked / released.
Copy the include file to your includes folder and over write any older version if you have one.
Compile and run the button test program - BUT read the following first please!
In my reg viewer program I added in a context menu for a control, but when the context menu was showing it partly covered another control. As you moved the mouse down the context menu at some point the mouse was also over the other control.
Because the mouse was over the other control, and I had told it to do something if it was - the control was doing this "action" even though you were moving the mouse up and down the first controls context menu.
So these new commands, together with a variable enabled me to stop this.
Have a look at this code from the button test program:-
if mousedown(1) then CMenu = 0 '<---- Check is mouse left button clicked FIRST
'Check for Right click on control with this command
IF ControlRClick(win,static_1)
CMenu = 1 '<---------- Context menu exists!
POINT cursor3
GetCursorPos(cursor3)
ScreenToClient(win.hwnd, cursor3)
CONTEXTMENU win,cursor3.x, cursor3.y
MENUITEM "Export key",0,2002
separator
MENUITEM "Copy key name",0,110
separator
MENUITEM "Copy key details",0,111
ENDMENU
endif
'===================================================================
'
' The control "radio_1" can have "static_1's" context menu over it
' so we need to check if the context menu exists or not.
'
' Variable CMenu = 0 - no context menu.
' CMenu = 1 - context menu exists.
'
' So, only do something with radio_1 IF context menu does not exists
'
'===================================================================
if MouseOver(win,radio_1) = 1 and CMenu = 0 '<--------- Check here......
SETFONT win,"Tahoma", 22, 400, 0, radio_1
else
if MouseMovedOff(win,radio_1) 'Do this one time only.
SETFONT win,"Arial", 10, 400, 0, radio_1
endif
endif
Static_1 has the text ""Move the mouse over here, ..........."
When you right click say on the word "mouse" a context menu appears.
This context menu appears over part of the radio_1 controls text.
Radio_1's text will only enlarge if static_1's context menu does not exists.
Try it.
Finally, comment out AND CMenu = 0 from this line (like this):
if MouseOver(win,radio_1) = 1 'and CMenu = 0 '<--- comment out the AND part.
You will see the the problem, and how to fix it.
Still confused as to what I'm trying to say??????? then give it a go.
Andy.
:)
I have been looking closely at your program/inc file and noticed that it takes a lot of storage. See:
'====================================================================
' Somewhere to store the window and control co-ordinates, sizes etc.'
' '
' 1,000 windows and 10,000 controls. '
' '
'====================================================================
int MOControlDown[10000],MOControlAcross[10000],MOControlWidth[10000],MOControlHeight[10000]
' storage bytes: 40,000*4 = 160,000'
int MOControlNumber[10000],MOControlTrack[10000],MOControlOverNumber[10000]
' storage bytes: 30,000*4 = 120,000'
int MOWindowDown[1000],MOWindowAcross[1000],MOWindowWidth[1000],MOWindowHeight[1000],MOWindowOverNumber[1000]
' storage bytes: 5,000*4 = 20,000'
int MOWindowLeft[1000],MOWindowRight[1000],MOWindowTop[1000],MOWindowBottom[1000]
' storage bytes: 4,000*4 = 16,000'
UINT MOControlsWindow[10000],MOWindowPointer[1000]
' storage bytes: 11,000*4 = 44,000'
string MOWindowName[1000],MOWindowDesc[1000],MOControlType[10000]
' storage bytes: 3,000*255 = 765,000'
' Total storage bytes: 1,125,000'
I am guessing that 1000 windows and 10,000 controls is the max that can be created in IWB. However, in reality, I would be surprised if any one would create more than maybe 50 windows with 1000 controls, which would free up alot of storage. Plus looking at the code many of the 3 string fields, probably store much less than 255 chars. So, I am wondering if they could be redefined as ISTRINGs. Say the max length of the variable that will be stored in a STRING variable is 14 characters then:
' Reference dimensioned ISTRINGs (1000 rows of 14 chars each, add 1 for /0 as last char (needed)
def sn[15,1000]:istring
sn[0,c] = Name
Just some thing to think about to save the program from needing more than 1 Meg of memory just for this utility.
Bill
Bill,
Yes, you do make a good point.
My ultimate plan is to make them istrings and use pointers, so we could set an initial number of windows and controls, and increase when needed.
Just a bit busy coding something else at the moment, but thanks for taking the interest!
Andy.
:)
Hi,
Well I thought I would post this now, I need to document the new functions.
However, here they are:
MoveControlUp
MoveControlDown
MoveControlLeft
MoveControlRight
These are the same as I posted the other day, but they have an optional parameter
which limits a control's position to within "X" of the top / bottom / left or right of the current window specified.
Example:
MoveControlLeft(w1,SelectedControl,Movement,20) 'limits the control from being moved to within 20 of the left of the window specified.
There is also a correction for ControlUp that Brian reported to me.
ControlDrag
This now has four optional paramters (top / bottom / left /right), with these you cannot drag a control beyond these values. The sub wants a gold old tidy up but it works.
Example:
ControlDrag(MyWindow,MyControl,0,610,130,1090)
(0 from the top, 610 from the bottom, 130 from the left & 1090 from the right).
These values refer to your specified window not the screen position, and can stop a user dragging a control out of the window and subsequently out of sight.
In effect, you are creating a border inside your specified window in which a user is allowed to drag a control.
MOGetSize
It's like our GETSIZE command but it gives you the actual position of a control in the specified window not the position on screen, and I can tell you that's really handy!
You use it like this
MOGetSize(MyWindow,MyControl)
and it returns these values:
MOControlSize.x (across)
MOControlSize.y (down)
MOControlSize.w (width)
MOControlSize.h (height)
You can then simply adjust your control's position using our SETSIZE command without doing any calculations.
I will post some examples here tomorrow.
See attached for version 6.0.
Andy.
P.S.
"I've just finished reading a book about a swimming pool, it started off really shallow but it had a deep ending" - sorry!
:)
Hi Andy,
Your ControlDrag procedure looks really complex. Consider capturing mouse when starting drag operation and releasing mouse capture on mouse button release.
Here is some old code:
$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",200,320,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
Hi Jalih,
Been to long since we have seen you!
Yes, I have to agree, in the case of dragging a control yours in much simpler.
Maybe there is a way to change my ControlDrag function to yours, I will have to see.
The idea behind this include file is to provide a "one stop shop" for us all where we can use / copy useful sections of code into our programs rather than having to spend hours searching for something.
Thanks so much for the code.
Andy.
:)