is there any simple way to drag my buttons and change position after i draw them ? ???
Subclass the button and send a message to button's caption$include "windows.inc"
DIALOG d1
INT g_buttonproc
CREATEDIALOG d1,0,0,300,202,0x80CA0880,0,"Caption",&d1_handler
CONTROL d1,@SYSBUTTON,"drag me",96,63,70,20,0x50010000,1000
domodal d1
SUB d1_handler
SELECT @MESSAGE
CASE @IDINITDIALOG
g_buttonproc = _SetWindowLong(GetControlHandle(d1, 1000), GWL_WNDPROC, &DragDropCtlProc)
CASE @IDCLOSEWINDOW
CLOSEDIALOG d1,@IDOK
ENDSELECT
RETURN
ENDSUB
sub DragDropCtlProc(hwnd:int,msg:int,wparam:int,lparam:int),int
if (msg=WM_LBUTTONDOWN) /* and dragging alloved */
SendMessage(hwnd, WM_NCLBUTTONDOWN, HTCAPTION, 0)
return 0
endif
return _CallWindowProc(g_buttonproc, hwnd, msg,wParam,lParam)
endsub
:o :o never thought, thank you
just put a second button
CONTROL d1,@SYSBUTTON,"drag me",96,63,70,20,0x50010000,1000
CONTROL d1,@SYSBUTTON,"drag me2",196,163,70,20,0x50010000,1001
and subclassed also button 2
SUB d1_handler
SELECT @MESSAGE
CASE @IDINITDIALOG
g_buttonproc = _SetWindowLong(GetControlHandle(d1, 1000), GWL_WNDPROC, &DragDropCtlProc)
g_buttonproc = _SetWindowLong(GetControlHandle(d1, 1001), GWL_WNDPROC, &DragDropCtlProc)
CASE @IDCLOSEWINDOW
CLOSEDIALOG d1,@IDOK
ENDSELECT
RETURN
ENDSUB
works super.
Sapero how easy is it to resize one of them ?
I would create the button as child of a another child window (like static control), 1-2 pixels wider and higher than the button, then draw a sizing rectangle on this static control if the button has keyboard focus, detect mouse moving to change the cursor in same way as in dialog editor, and simply resize the static and button if the mouse is moving while the left mouse button is down.
To do so, just create a static control 82x22, and button as child of this static at 1,1 80x20. Subclass this static control to be able to respond to mouse moving. Also subclass your button to detect the focus and notify the static control about.
Pseudo code for static control:
WM_NCHITTEST: retrun HTCLIENT, only for static/group controls you need to handle this message
WM_MOUSEMOVE: if (button has focus) and (left mouse button is up) then SetCursor(CursorPosToCursorType(x,y))
// where CursorPosToCursorType returns up+down arrow if 'mouse' is over upper or lever border...
if (button has focus) and (left mouse button is down) - resize/move the static and resize the button
WM_SETFOCUS - draw or remove black border from static control, it enables or diables cursor changes inside WM_MOUSEMOVE. You'll need to save previous static position and size (rectangle) to propertly move and resize it.
Pseudo code for button control:
WM_SETFOCUS - notify the static control that you got or lost the focus (draw/remove the sizing rectangle)
If your familiar with MASM, you can study the ResEd (http://www.radasm.com) source for this (resource editor)
Of course you can create this static control only if the button got focus, so you can change the parent of button to this static control, then move the button back and destroy this static control, if the button lost focus.
Another possiblity: change button style - add or remove WS_SIZEBOX or WS_THICKFRAME:
CONTROL d1,@SYSBUTTON,"drag me",96,63,70,20,0x50010000 | 0x40000,1000
second solution is easy thanks
Quote from: sapero on April 10, 2007, 06:44:34 PM
I would create the button as child of a another child window (like static control), 1-2 pixels wider and higher than the button, then draw a sizing rectangle on this static control if the button has keyboard focus, detect mouse moving to change the cursor in same way as in dialog editor, and simply resize the static and button if the mouse is moving while the left mouse button is down.
To do so, just create a static control 82x22, and button as child of this static at 1,1 80x20. Subclass this static control to be able to respond to mouse moving. Also subclass your button to detect the focus and notify the static control about.
Will this technique work for any control?
Quote from: sapero on April 10, 2007, 06:44:34 PM
Pseudo code for static control:
WM_NCHITTEST: retrun HTCLIENT, only for static/group controls you need to handle this message
WM_MOUSEMOVE: if (button has focus) and (left mouse button is up) then SetCursor(CursorPosToCursorType(x,y))
// where CursorPosToCursorType returns up+down arrow if 'mouse' is over upper or lever border...
if (button has focus) and (left mouse button is down) - resize/move the static and resize the button
WM_SETFOCUS - draw or remove black border from static control, it enables or diables cursor changes inside WM_MOUSEMOVE. You'll need to save previous static position and size (rectangle) to propertly move and resize it.
Pseudo code for button control:
WM_SETFOCUS - notify the static control that you got or lost the focus (draw/remove the sizing rectangle)
Of course you can create this static control only if the button got focus, so you can change the parent of button to this static control, then move the button back and destroy this static control, if the button lost focus.
Another possiblity: change button style - add or remove WS_SIZEBOX or WS_THICKFRAME:
CONTROL d1,@SYSBUTTON,"drag me",96,63,70,20,0x50010000 | 0x40000,1000
do you have any "actual" code samplke for all of that, that you would be willing to share?
Larry
Try the arrached source. It creates some different controls, let you resize and move them, and aligns control position and size to 2-pixels.
It is not perfect, can be better.
KILLFOCUS handler is very primitive: hides and shows the control. I've not found better way to 100% redraw the control.
AWSUME!!!!!!!!!!!!! ;D ;D ;D
Of course initially it wouldn't compile and had a TON of errors. ???
After I downloaded your NEW windows.inc stuff it worked great. :-[
The example was EXACTLY what I was looking for. ;D
You the man, Sapero!!!!hanks again,
Larry
the new windows.inc stuff is a lot more complicated looking than the shipped "windows.inc"
My question is that if I create a lib file that has the $include "windows.inc" statement in the lib source file will the user of the distributed lib also have to have the new windows.inc setup inoder to be able to use the lib?
Larry
Larry,
Once you make a .lib it is compiled, just machine code, no references to the include files are part of it. The same as making a DLL or .exe
Paul.
thanks,
Life is great then!
Larry
sapero,
playing with the sample code from above.
ran into a problem.
Here's what I CAN do:
left-click to select any of the controls and watch focus changed from control to control
right click while a control has focus and have a content menu popup.
Here's what I can not do:
Have a control selected (like above) and left click on the dialog (not on a control) and have the selected control automatically lose focus and have focus switch to the dialog itself.
I tried variations on this in the main dialog handler:
case WM_LBUTTONDOWN
if GetFocus()<> d1.hwnd
SENDMESSAGE(GetFocus(), WM_KILLFOCUS, 0,0)
endif
_setfocus(d1.hwnd)
Am am I missing something entirely?
Larry
I've gotten closer to making it work:
case WM_LBUTTONDOWN
if GetFocus()<> d1.hwnd
setfocus(d1,1012)
endif
where id 1012 is a blank @static located in the bottom left corner of the dialog and is 1x1 pixels
and it is not sub-classed like all the other controls
so, when I left-click outside a sub-classed control that currently has the focus the drag box will go away and I get the proper context menu to appear.
BUT
The sub-classed contextmenu routine(which looks like this:)
case WM_CONTEXTMENU
' create custom menu (for any control)
wParam = CreateMenu(1)
APPENDMENU(wParam,"Properties",MF_STRING,10000)
APPENDMENU(wParam,"Delete",MF_STRING,10001)
select TrackPopupMenu(wParam, TPM_RETURNCMD, LOWORD(lParam), HIWORD(lParam), 0, hwnd, 0)
case 10001
destroywindow(hwnd)
case 10000
showdialog d2
endselect
DestroyMenu(wParam)
return 0
responds immediately (one-click) if I pick delete
but I have to click twice to get it to show the dialog.
Any ideas?
Larry
1. In the WM_LBUTTONDOWN handler of the dialog, call _SetFocus(0), or set the focus to the invisible control
2. Because every CASE calls SELECT.
Save TrackPopupMenu return value in free variable then pass it to SELECT.
As usual, right on target.
Thanks Sapero
Larry
sapero
In the "drag" source file you posted above there is a line$define LPFNPROP "A8VD76"
Is there something specific about "A8VD76" or is that purely arbitrary and can be replaced with anything I want?
Larry
This is a random string, typed by my fist ;D
My understanding is that it just has to be unique; right?
Larry
Sapero,
Ran into a problem I can't resolve.
I'm using the dragging routines you posted for me in the project I'm working on..
All the sudden the resizing of my edit control and my listbox control is acting weird.
Regardless of what size I create those 2 controls once I resize to larger than 110 x 25 they will not allow themselves to be resized to a size smaller than that even if they were created at a smaller size.
All the other controls resize as you would expect them to.
All the controls use the same subclassing and resizing routine.
You're example works fine by itself.
I'm not absolutely sure but I'm almost sure the 2 problem controls worked okay before I upgraded to 1.6/1.6.1
but I might be mistaken.
Got any ideas.
Almost forgot, the form that the controls are children of is also subclassed and has the dragging but the routines are copied and renamed just for the form. Don't know if that makes any difference or not.
Larry
It makes no difference, the compiled code does not know about function names.
In the MyControlProc() function try to block unprocessed messages (but selected only) - I did so to find why the static control did not allow me to resize it.
sub MyControlProc
select
case ...
case ...
' add this
default
print hex$(uMsg)
Lookup the message in winuser.inc and if you think a printed 'hex' message can be the cause (like WM_NCLBUTTONDOWN), add new case and let it eat the message by returning zero, or better DefWindowProc (while CallWindowProc will forward this message to the control):
sub MyControlProc
select
case ...
case ...
' messages to hide from subclassed control - call the default handler
case WM_NCLBUTTONDOWN
case& 0xSOMETHING
return DefWindowProc(hwnd, uMsg, wParam, lParam)
' messages to eat - cancel this message
case WM_**
case& 0xSOMETHING2
return 0
The string assigned to LPFNPROP can be any, but remember to not change already used by EBasic library strings like "LPFN", BBRUSH, BGRND, FGRND... (use EnumProps api to enumerate all them)
I ate all the messages that were coming through and no improvement.
Any other suggestions?
Larry