Creating draggable windows - SDI and dialogs
|
|||||||||||
IntroductionThe standard practice for moving a window is to drag it's title bar. This is handled for us by the operating system itself. But there are some applications that allow us to move the entire window by dragging anywhere within it's body. Sometimes it is pretty annoying when that happens, but there might be occasions where this is required. For dialog based applications there is a despicable trick which we can use to achieve this. The secret is to handle Of course there is always more than one way to skin a cat, and it's not much different when it comes to programming. The same goes for this article too. Roman Nurik, has explained a much easier way to accomplish the same as I have. I have included this much easier method in terms of number of lines and effort at the end of the article. I could have put them on the top of the article too, but I wanted the flow of the article to be from good to better. In fact after Roman's method, I have also provided a solution offered by Albert Ling, which in my opinion is? the most innovative of all the methods discussed here. Draggable dialogsThe UINT CDragDialogDlg::OnNcHitTest(CPoint point) { CRect r; GetClientRect(&r); ClientToScreen(&r); //Chk to see if the mouse is within //the dialog client areaif(r.PtInRect(point)) { if(m_mousedown) { return HTCAPTION; } } return CDialog::OnNcHitTest(point); }
void CDragDialogDlg::OnLButtonDown(UINT nFlags, CPoint point) { m_mousedown = true; CDialog::OnLButtonDown(nFlags, point); } void CDragDialogDlg::OnLButtonUp(UINT nFlags, CPoint point) { m_mousedown = false; CDialog::OnLButtonUp(nFlags, point); } Draggable SDI windowsAs I have mentioned earlier we cannot use the technique we used for dialog based applications here. The whole issue here is that the void CDragSDIView::OnLButtonDown(UINT nFlags, CPoint point) { m_mousedown = true; ClientToScreen(&point); m_lastpoint = point; CView::OnLButtonDown(nFlags, point); } Just as in the previous case, we override void CDragSDIView::OnLButtonUp(UINT nFlags, CPoint point) { m_mousedown = false; CView::OnLButtonUp(nFlags, point); }
void CDragSDIView::OnMouseMove(UINT nFlags, CPoint point) { CRect r; GetClientRect(&r); ClientToScreen(&r); ClientToScreen(&point); if(r.PtInRect(point)) { if(m_mousedown) { AfxGetMainWnd()->GetWindowRect(&r); AfxGetMainWnd()->MoveWindow( r.left - (m_lastpoint.x - point.x), r.top - (m_lastpoint.y - point.y), r.Width(),r.Height()); m_lastpoint = point; } } CView::OnMouseMove(nFlags, point); } Well, we first check to see if the point is within the client area of the view window.? If it is, then we check the A much easier way - Roman NurikAs I have mentioned in the introduction, there are multiple ways to skin cats, though why anyone would ever want to skin cats beat me. Cat skins are not exactly useful in my opinion. Alright, let's get to Roman's method for making draggable windows. First override ReleaseCapture(); //This is not compulsory
POINT pt;
GetCursorPos(&pt);
POINTS pts = {pt.x, pt.y};
::SendMessage(m_hWnd,WM_NCLBUTTONDOWN,HTCAPTION,(LPARAM)&pts);
ReleaseCapture(); //This is not compulsory ::SendMessage(m_hWnd,WM_NCLBUTTONDOWN,HTCAPTION,0);
pWnd->SendMesage(WM_NCLBUTTONDOWN,HTCAPTION,0);
Well, that was sure easier than the previously discussed techniques, wasn't it and thanks goes to Roman Nurik for this really cool tip. But then I guess each method would have it's pros and cons which may make themselves visible at random. Another way - Albert LingWell, we come to that matter of cats and skins again. Here is yet another solution suggested by Albert Ling, that seems to me to be the best of all the methods we have investigated. He overrides UINT CYourDlg::OnNcHitTest(CPoint point) { UINT hit = CDialog::OnNcHitTest(point); if ( hit == HTCLIENT ) { return HTCAPTION; } elsereturn hit; } If you thought Albert Ling's solution for dialog based apps was cool, you are yet to see his solution for SDI apps. It was simply amazing! This is what he did. He overrides UINT CYourView::OnNcHitTest(CPoint point) { UINT hit = CView::OnNcHitTest(point); if (hit == HTCLIENT ) return HTTRANSPARENT; else { return hit; } } UINT CMainFrame::OnNcHitTest(CPoint point) { UINT hit = CFrameWnd::OnNcHitTest(point); if ( hit == HTCLIENT ) { return HTCAPTION; } elsereturn hit; } ConclusionWell, when I wrote this article I was under the thoroughly mistaken impression that my method was the only way to go about doing it. That's when Roman came and proved me wrong by offering his solution which was quite simpler to implement. Just when I was trying to be complacent about all this by talking about the cat-skins in the old adage, out comes Albert Ling with yet another amazing solution. Now I live in constant fear of being bombarded with other solutions and feel like a haunted man. Heheh. No, actually I don't. Was just kidding. If any of you have other solutions, feel free to suggest it here via the forum, or email me directly so that we can make this a single point source for all methods used for creating draggable windows. About Nishant Sivakumar |
posted on 2006-11-15 16:42 weidagang2046 閱讀(812) 評論(0) 編輯 收藏 所屬分類: Windows