Link to home
Start Free TrialLog in
Avatar of Karrtik Iyer
Karrtik IyerFlag for India

asked on

C++ | MFC | Windows programming | WM_MOVING not being called

I have a custom control being derived from CWND and implemented as a grid. To enable drag and drop of rows of the grid I have a draggable transparent dialog (CDraggableDialog) displaying the current row and used NCHITTEST to drag the row. To restrict the movement of dragged row in within some area, I have trapped WM_MOVING message in CDraggableDialog class. However this event is not being fired.
If I use a simple test dialog based application, in which I use the same CDraggableDialog on top the parent dialog/main dialog, it works and WM_MOVING event is fired for CDraggableDialog class.
I am unable to figure the reason behind this behavior.
Please help.
Thanks,
Karrtik
Avatar of sarabande
sarabande
Flag of Luxembourg image

you may use spy to find out what happens. i would assume that the draggable dialog is not a child window of the active window which runs the current message loop.

note, a modal dialog in mfc has it own message loop and would not be notified if you have an sdi or mdi mfc project where the m_pMainWnd was set in the InitInstance function of the application class. also messaging for non-modal dialogs has limited message traffic if you didn't create it as a child window of the current active dialog or view and do correct 'subclassing'. subclassing means that the windows proc function of the window was properly added to a stack. if not the problem is then that the dragged window doesn't send notifications to its parent dialog (or sends it to a wrong window outside of the current message loop) and therefore additional messages like WM_MOVING were not created or sent to a window which doesn't handle them.

Sara
Avatar of Karrtik Iyer

ASKER

Thanks sara, I shall try using spy. Couple of more questions.
1) I'm getting winodwpositionchanged event properly in the draggable dialog both in actual app as well as test app. So if what you are saying is correct would we get this event properly while we don't get WM_Moving event?
2) Does any window creation style (dwstyle) of parent grid CWND matter to get wm_moving event in Draggable dialog class? May be in the test program since the parent is a main dialog instead of CWND grid, the parent dialog is created with some styles which I'm not using for parent CWND in my actual application?
all messages directed to the window itself were fired as an event.

WM_MOVING is different since it wasn't sent to the window moved directly but was created from other messages like WM_LBUTTONDOWN and WM_MOUSEMOVE and was sent to the parent of the window moved as a notification message. because of that there are a few hurdles to take to get the event passed via message map to the dragging class itself which in your case is working if you have a simple dialog and not if you add the class into a more complex framework.

if you post the class headers and (the context of) creation of the CDraggableClass i probably could give you advice what you could do. but it is probably simpler to catch WM_LBUTTONDOWN, then capture the mouse such that WM_MOUSEMOVE was sent to the window, and then handle WM_MOUSE_MOVE until the WM_LBUTTONUP was fired.

1) I'm getting winodwpositionchanged event properly
this message was sent after the window already was moved while WM_MOVING is sent before moving (what allows to correct or adjust the move or even prevent from moving).

Does any window creation style (dwstyle) of parent grid CWND matter to get wm_moving event in Draggable dialog class?

no, as far as i know. the problem is that the parent grid doesn't handle the message at all. you would need to derive from grid class in order to handle more messages.

May be in the test program since the parent is a main dialog instead of CWND grid, the parent dialog is created with some styles

a dialog handles messages of (all) child controls and in your case the CDraggableDialog is treated as a control.

as you have the sources of mfc you may search when the WM_MOVING message was sent. in your test dialog you then could set a breakpoint and perhaps find out which messages and conditions are necessary to fire the event. you probably will see that the grid doesn't handle all the messages same way as a dialog.

Sara

Sara
Thanks Sara, I am handling Mouse Move and LBUttonDown and LButtonUp events in my grid class which I am not handling my dialog in test program, could that be cause? What should I do in these event to ensure my CDraggableDialog receives the WM_MOVING event? I tried deferring the call to CWND::ONmouseMove and CWND::OnLButtonUp/Down at end of my logic in the grid class but that did not help me getting WM_Moving in CDraggableDialog.
basically I need WM_Moving for the CDraggableDialog class because that is the only event in which I could restrict the area in which the user can drag the draggable dialog, do you think there is any other way I can restrict the movement of DraggableDialog within some specified area without having to depend on WM_Moving event?
Sorry in the above post I mentioned PositionChanged event, I wanted to mention that I am getting OnWindowPosChanging event successfully in both actual app as well as test program. But I am unable to do the restriction of movement of draggable dialog using OnWindowPosChanging as I am able to do it successfully on WM_MOVING.
BTW, do you need header files of my CDraggable class, anything else? I have shared both cpp and header file, there isnt anything confidential in it, so its ok. Also I have shared my test code which works. (TransparentDIalog.zip)

Thanks for all your help,
Regards,
Karrtik
DraggableDialog.zip
TransparentDialog.zip
On more thing, may be something strikes after reading this comment of mine, in my actual app, cdraggabledialog is in a MFC DLL which also contains the Grid CWND which is hosted on a dialog in the actual app exe, however in test app everything is within an EXE, there's is no MFC DLL involved in the test application.
ASKER CERTIFIED SOLUTION
Avatar of sarabande
sarabande
Flag of Luxembourg image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
cdraggabledialog is in a MFC DLL
you should try to add the class and header directly to the application project.

moving it to a dll should be the second step if all works. there are simply too many issues that could happen if you do all at once.

Sara
Hi Sara,
On further investigation both in test program and in the actual app, the issue happening is that once the drag of the CDraggableDialog is started using OnNCHITTest trapped in CDraggableDialog, the WM_Moving does not get fible window once again after the initial drag start. Although on mouse of move  and LButton down pf the parent Window (Grid) the draggable window is shown moving, till the user again left clicks on the dragged window shown, the WM_MOVING event is not fired. This works the same in both the test app as well as actual app. Please let me know if you can help me in resolving this issue. Any help would be appreciated.
Psuedo code written on Mouse Move of parent window or grid window:
1> Get Key state and check if the mouse move have has happened with LButton down, then display the Draggable Window using ShowWindowMethod with SW_SHOW argument. This is done after doing a setwindowPos on the draggable window as top most window.
2> In NCHITTest event of DraggableWindow, since it is a window without caption, to enable drag, check if hit area is client then return it as HTCAPTION so that drag is automatically handled as on title bar of any dialog.
3> On ExitSizeMove event of DragabbleWindow, hide  the draggablewindow once LBUtton is released and send message to parent window (grid) that drag is complete.
Basically I would like to select the draggable window automatically on NCHITTEST instead of user having to select it once again for getting the WM Moving event to restrict the drag area. I have tried doing setactivewindow, setfocus on the draggable dialog as soon as it is shown but that doesn't help. So any help to resolve this issue would be appreciated.
i would assume that the mfc framework uses a handler for left button down, and mouse move, and finally will call CWnd::OnNcHitTest virtually and then send the WM_MOVING message. if that is true, an overload of any of the handlers or the OnNcHitTest by your own handlers, may prevent the WM_MOVING being created since the framework code was no longer executed.

you may test the hypothesis by commenting  all message handlers for WM_LBUTTONDOWN and WM_MOUSEMOVE and by calling CWnd::OnNcHitTest in your overloaded function (and return immediately).

Sara