New code is bolded. It's meant to move window without border and TitleBar. And it works very, very smoothly :cheekygreen: But it can not handle rapid mouse movement. Here's the code with a few questions at the end...
Quote@@:;__________________no return value!!!!!
cmp uMsg,WM_MOUSEMOVE
jne @f
test wParam,MK_CONTROL ;is CTRL pressed
jz NotCtr ;if not goto NotCtr
test wParam,MK_LBUTTON ;is Left mouse pressed
jz EndMouseMove ;if not goto EndMouseMove
;move window through lParam x.y
mov eax,lParam ;new mouse position
and eax,65535 ;FFFFh ;LOW word for x
sub eax,WInputFlagMousePoint.x ;new-old=move difference
add WInputFlagX,eax ;add window pos + move differemce
mov eax,lParam ;new mouse position
shr eax,16 ;HI word for Y
sub eax,WInputFlagMousePoint.y ;new-old=move difference
add WInputFlagY,eax ;add win pos + move diference
invoke MoveWindow,hWnd,WInputFlagX,WInputFlagY,WInputFlagWidth,WInputFlagHeight,TRUE
;invoke SetWindowPos,hWnd,HWND_TOP,WInputFlagX,WInputFlagY,WInputFlagWidth,WInputFlagHeight,SWP_NOSIZE
jmp EndMouseMove
NotCtr:
invoke SetClassLong, hWnd,GCL_HCURSOR,hcurArrow
invoke SetCursor, hcurArrow
EndMouseMove:
;-----end wm_mousemove-----
@@:;____________________return 0
cmp uMsg,WM_LBUTTONDOWN
jne @F
mov eax,lParam
and eax,0FFFFh ;LO byte for X
mov WInputFlagMousePoint.x,eax
mov eax,lParam
shr eax,16 ;HI byte for y
mov WInputFlagMousePoint.y,eax
test wParam,MK_CONTROL
jz NotCtrlP
invoke SetClassLong, hWnd,GCL_HCURSOR,hcurGrabbed
invoke SetCursor, hcurGrabbed
xor eax,eax
ret
NotCtrlP:
xor eax,eax
ret
;--------end wm_lbutondown-------------------
Questions:
Is there better way to move window without border?
This code does the job if you move mouse by slow/normal paste. If mouse movement is too rapid or fast, cursor simply leaves client area. It looks like window is too slow to stay below cursor. This does not happen if you grab and move window by the TitleBar. No matter how fast you move it. Any idea how to replicate it with window without border and TitleBar?
oh man... :dazzled: :lol
.elseif eax==WM_LBUTTONDOWN
invoke SendMessage, hWnd, WM_NCLBUTTONDOWN, HTCAPTION, 0
Quote
.elseif eax==WM_LBUTTONDOWN
invoke SendMessage, hWnd, WM_NCLBUTTONDOWN, HTCAPTION, 0
The problem with the above code is that you cannot drag the window's imaginary title above the desktop top side.
Try it, it will bounce down upon mouse button release, due to windows trying to keep the title available (even though it's non-existant).
The following code, although a bit long, will drag the window without any unexpected hops or twitches.
; #################################################################################################
; DragWindow by LimoDriver [30/03/2007]
; #################################################################################################
.data?
gx_Pnt POINT <?>
.code
; #################################################################################################
DragWindow proc gh_Wnd : DWORD, d_Msg : DWORD
;{
LOCAL x_Rct : RECT
; -------------------------------------------------------------------------------------------------
mov eax, d_Msg
@@: cmp eax, WM_RBUTTONDOWN
jnz @F
;{
invoke LoadCursor, 0, IDC_SIZEALL
invoke SetCursor, eax
invoke GetCursorPos, addr gx_Pnt
invoke SetCapture, gh_Wnd
jmp @DW_E
;}
; -------------------------------------------------------------------------------------------------
@@: cmp eax, WM_RBUTTONUP
jnz @F
;{
invoke ReleaseCapture
jmp @DW_E
;}
; -------------------------------------------------------------------------------------------------
@@: cmp eax, WM_MOUSEMOVE
jnz @F
;{
invoke GetCapture
cmp eax, gh_Wnd
jnz @F
;{
push gx_Pnt.y
push gx_Pnt.x
invoke GetCursorPos, addr gx_Pnt
invoke GetWindowRect, gh_Wnd, addr x_Rct
mov ecx, gx_Pnt.x
pop eax
sub ecx, eax
add ecx, x_Rct.left
mov edx, gx_Pnt.y
pop eax
sub edx, eax
add edx, x_Rct.top
invoke SetWindowPos, gh_Wnd, 0, ecx, edx, 0, 0, SWP_NOZORDER or SWP_NOSIZE
jmp @DW_E
;}
;}
; -------------------------------------------------------------------------------------------------
@@: return d_Msg
@DW_E: return 0
;}
DragWindow endp
; #################################################################################################
Quote from: LimoDriver on March 30, 2007, 09:49:12 PM
The problem with the above code is that you cannot drag the window's imaginary title above the desktop top side.
Try it, it will bounce down upon mouse button release, due to windows trying to keep the title available (even though it's non-existant).
I wouldn't call it a problem, rather a good feature. Why would I want to drag a window somewhere outside desktop, say: x,y(100,-10). This ensures that there will be always a small part of window accessible on the desktop...
QuoteWhy would I want to drag a window somewhere outside desktop, say: x,y(100,-10). This ensures that there will be always a small part of window accessible on the desktop...
The code I pasted also ensures that a small part of the window is always accessible, since you cannot drag the window to a point on screen beyond the desktop.
The only difference is that it's truly up to the application developers call to decide on the minimum and maximum bounding boxes, instead of windows enforcing its "show title" will - on a usually skinned window without the actual title.
Check out any proper application that supports drag anywhere on its body frame (any self respecting media player, for example) - they all have it coded properly, and not via WM_NCLBUTTONDOWN.
Don't take me wrong, I'm not afraid of coding, nor I'm envy of few extra code lines, but when it's not worth it I'd rather keep things simple...
Quotebut when it's not worth it I'd rather keep things simple...
This is most definitely true. For instance, if we're just dragging child controls from within the main application frame, WM_NCLBUTTONDOWN is a savior.
Hello guys :)
Thank you a lot for your prompt response. I had (still have) some odd problems with cable internet so I could not reply sooner.
Anyway, I am amazed by your knowledge. Thanks again!
Now, lets return to asm :wink
ramguru,
Your solution works. It's fast, simple, almost flawless. I even do not mind if it tries to show non existing TitleBar. Bad thing is that WM_NCLBUTTONDOWN somehow blocks cursor changing. Another bad thing is that I have no clue WHY it works. And how to implement it if I ever decide to "drag child controls"
LimoDriver,
You've posted some mean code dude :wink First to ask about DragWindow proc:
IF I do invoke DragWindow param1, param2 in WinProc and IF there are no ret's in it... I'll be able to do one more check for WM_'s I already checked in DragWindow. Is it good way to summarize code for WinProc I might use in future?
F. you posted works because of SetCapture, GetCapture... Nice solution btw :8) I tried to implement it in my previously posted code for learning purposes. And it works 50% :green Any rapid moving window to the right or down is fast as it should be. Not a grip lost.
BUT (bigger than J.Lo's) if you move window up or left - it disappears completely!!! I thought about it for a while and finally I realize that window receives a NEGATIVE value for X and/or Y through WM_MOUSEMOVE lParam!!! Because mouse is moved from client area and X.Y are relative to window's top left corner! Isn't that lovely?
Do anyone know how are represented those negative values in lParam hi and lo word. How should I properly convert it in dword values. And last but maybe most important question:
How do we add, sub, signed numbers?!?
OK imagine you're using SetCapture and your cursor suddenly appears outside client area
so this is how I checked in one of my program
mov ecx, lParam
shr ecx, 16 ; ecx --> y
.if ecx > 0F000h ; if cx < 0
invoke do_action
.endif
FFFF0000 (0,-1)
FFFE0001 (1,-2)
How to convert word negative to dword negative:
mov ecx, lParam
shr ecx, 16 ; high-order negative
or ecx, 0FFFF0000h ; whole reg negative
How to add,sub:
simply, if whole reg negative
you simply
mov ecx, -1 ; ecx == FFFFFFFF
add ecx, 1 ; ecx == 0 because of overflow [1]00000000
mov ecx, -1 ; ecx == FFFFFFFF
sub ecx, 1 ; ecx == FFFFFFFE
Mmmmmm... So you are saying that I am abusing sub/add :wink And I see why!
I did this :
mov eax,lParam ;new mouse position
shr eax,16 ;HI word for Y
sub eax,WInputFlagMousePoint.y ;new-old=move difference
add WInputFlagY,eax ;add win pos + move diference
In C/basic it would work: mouse.y=oldmouse.y+mousediference
if mousediference is negative it would be correctly subtracted from oldmouse.y. In my code it threats it like positive value and sets window far away from desktop.
Basically I always have to check if result is negative and write appropriate code! I guess I wanted some mathematical shortcut :wink
Thank you ramguru :U
p.s. I am not totally a lost cause :wink I manage to convert negative word to negative dword correctly! Other two examples are going to be great help to me. Thanks man!
Quote from: CoR on April 01, 2007, 06:42:13 PM
IF I do invoke DragWindow param1, param2 in WinProc and IF there are no ret's in it... I'll be able to do one more check for WM_'s I already checked in DragWindow. Is it good way to summarize code for WinProc I might use in future?
Well everyone wants to write his own version of WinProc.
When I have large applications, I usually separate everything regarding certian actions into separate mini-WndProc's
This way, when you're done with something, you just dub it done, and never reopen the file again (in this case DragWindow).
It's possible that more than one function will check for the same WM_ but this is utterly irrelevant unless you're writing... writing... no, trust me, it's utterly irrelevant :)
The current code is written in a way that it will return 0 if the DragWindow function has actually done something with the WM_. This way, upon return, you can just ret from the main WndProc if you're sure that you don't need any of the WM_'s included in DragWindow anymore.
All right :bg I manage negative numbers and here's the code:
@@:;_______________________no return value!!!!!
cmp uMsg,WM_MOUSEMOVE
jne @f
test wParam,MK_CONTROL ;is CTRL pressed
jz NotCtr ;if not goto NotCtr
test wParam,MK_LBUTTON ;is Left mouse pressed
;jz EndMouseMove ;if not goto EndMouseMove
jz EndMM
invoke GetCapture
cmp eax,hWnd
;jne EndMouseMove
jne EndMM
; y x x, y = lParam
;FFFF0000 (0,-1)
;FFFE0001 (1,-2)
mov eax,lParam ;new mouse position
and eax,00000000000000001111111111111111b ;65535 ;FFFFh ;LOW word for X
test ax,1000000000000000b ; 08000h to see if no, is positive
jz poz jmp if it is
or eax, 0FFFF0000h ;if negative, make it dword negative
sub eax,ClientAreaMouseHP.x ;new-old=move difference
add WInputX,eax ;add window pos + move differemce
jmp y
poz:
sub eax,ClientAreaMouseHP.x ;new-old=move difference
add WInputX,eax ;add window pos + move differemce
y:
mov eax,lParam ;new mouse position
shr eax,16 ;HI word for Y
test ax,1000000000000000b
jz poz1
or eax, 0FFFF0000h
sub eax,ClientAreaMouseHP.y ;new-old=move difference
add WInputY,eax ;add win pos + move diference
jmp wpiMove
poz1:
sub eax,ClientAreaMouseHP.y ;new-old=move difference
add WInputY,eax ;add win pos + move diference
wpiMove:
;invoke MoveWindow,hWnd,WInputX,WInputY,WInputWidth,WInputHeight,TRUE
invoke SetWindowPos,hWnd,HWND_TOP,WInputX,WInputY,WInputWidth,WInputHeight,SWP_NOSIZE
jmp EndMM
NotCtr:
invoke SetClassLong, hWnd,GCL_HCURSOR,hcurArrow
invoke SetCursor, hcurArrow
EndMM:
;------------------------------end wm_mousemove------------------------------
Quote from: LimoDriver on March 30, 2007, 11:01:37 PM
This is most definitely true. For instance, if we're just dragging child controls from within the main application frame, WM_NCLBUTTONDOWN is a savior.
How do you move child controls? Or to be more precise I want to move edit control with mouse. With end goal to stretch edit control little more over all client area and to be able to move whole window clicking on that edit area?
How do you want to move child controls? - implement splitter window (http://www.catch22.net/tuts/splitter.asp) or something like resource editor does: resize, move ?
Exactly like advanced resource editor! First to move only edit control, and after to add CTRL+LBUTTONDOWN to move edit resource and whole window (because only edit control will be visible)
Don't expect simple answer for advanced question :wink
In my dialog editor I use EnumChildWindows, then I use:
[in enum proc (lParam = DWORD(pt.y,pt.x))]
GetParent ; to get parent window handle
GetWindowRect ; to get child window rect
ClientToScreen ; to translate coor
PtInRect ; to check if mouse was pressed in child window
That involves also z-order, if controls overlaps, also some controls are composite and complicate things...
That's just to get window handle
Ok, thanks. That will be a good guideline. I'll post code as soon as make something half usable :wink
I should mention one thing, that might be not what you want and not work in your app, besides in dialog editor everything is different: all windows are disabled...
Now that's reassuring :bg
Quote from: ramguru on April 10, 2007, 05:42:44 PM
Don't expect simple answer for advanced question :wink
Hehehe :bg
I have putted this problem on a side because I thought it was out of my grasp. For I while I coded some EditBoxes for window resizing. Well I do not know (yet) how to pass values from EditBox to variable
but here's the solution for EditBoxDragging:
invokel CreateWindowEx,.......
mov hEDIT,eax
invoke SetWindowLong,hEDIT,GWL_WNDPROC,myDraggingEDITboxProc
mov hEDITold,eax ;places addr of an OLD (default) window editbox proc
EDITboxProc proc hWnd:DWORD, uMsg:DWORD, wParam :DWORD, lParam :DWORD
@@:;_______________________no return value!!!!!
cmp uMsg,WM_MOUSEMOVE
jne @f
some code
jmp TheEnd
@@:;_________________________no return value!!!!!
cmp uMsg,WM_LBUTTONDOWN
jne @F
some code
jmp TheEnd
@@:
bla,bla,bla code for REGULAR window movement. Basically it's exactly the same parts of proc that Limo or I have posted earlier.
jmp TheEnd
@@:
TheEnd:
invoke CallWindowProc,hEDITold,hWnd,uMsg,wParam,lParam
ret
EDITboxProc endp
You just have to be sure that NewEditBox has no
ret's in any WM_check! To be able to pass msg parameters to Default EditBox proc. It's works like a charm.
So simple, clean, nice... I am starting to think good about Window creators. As a concept is seems that they did good job!
keywords: child control edit box move drag