home *** CD-ROM | disk | FTP | other *** search
/ Tools / WinSN5.0Ver.iso / NETSCAP.50 / WIN1998.ZIP / ns / cmd / winfe / dragbar.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1998-04-08  |  10.1 KB  |  411 lines

  1. /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
  2.  *
  3.  * The contents of this file are subject to the Netscape Public License
  4.  * Version 1.0 (the "NPL"); you may not use this file except in
  5.  * compliance with the NPL.  You may obtain a copy of the NPL at
  6.  * http://www.mozilla.org/NPL/
  7.  *
  8.  * Software distributed under the NPL is distributed on an "AS IS" basis,
  9.  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
  10.  * for the specific language governing rights and limitations under the
  11.  * NPL.
  12.  *
  13.  * The Initial Developer of this code under the NPL is Netscape
  14.  * Communications Corporation.  Portions created by Netscape are
  15.  * Copyright (C) 1998 Netscape Communications Corporation.  All Rights
  16.  * Reserved.
  17.  */
  18.  
  19. #include "stdafx.h"
  20. #include "dragbar.h"
  21. #include "navfram.h"
  22. #ifdef _DEBUG
  23. #undef THIS_FILE
  24. static char BASED_CODE THIS_FILE[] = __FILE__;
  25. #endif
  26. #define CX_BORDER 2
  27. #define CY_BORDER 2
  28.  
  29.  
  30. CDragBar::CDragBar(CRect& crRect, CNSNavFrame* pDockFrame)
  31. {
  32.     //    Set our members.
  33.     m_bDragging = FALSE;
  34.     m_crTracker = crRect;
  35.     m_dockedFrame = pDockFrame;
  36.     m_bInDeskCoord = FALSE;
  37. }
  38.  
  39. CDragBar::~CDragBar()
  40. {
  41.     //    If we were tracking, then let our clipped region go, etc.
  42.     if(m_bDragging == TRUE)    {
  43.         //    Release the bounds established on the mouse.
  44.         ::ClipCursor(NULL);
  45.     }
  46. }
  47.  
  48. void CDragBar::PostNcDestroy( )
  49. {
  50.     delete this;
  51. }
  52.  
  53.  
  54. void CDragBar::OnDestroy()
  55. {
  56.     CWnd::OnDestroy();
  57. }
  58.  
  59. BEGIN_MESSAGE_MAP(CDragBar, CWnd)
  60.     ON_WM_LBUTTONDOWN()
  61.     ON_WM_RBUTTONDOWN()
  62.     ON_WM_SETCURSOR()
  63.     ON_WM_PAINT()
  64.     ON_WM_MOUSEMOVE()
  65.     ON_WM_DESTROY()
  66.     ON_WM_LBUTTONDBLCLK()
  67. END_MESSAGE_MAP()
  68.  
  69. void CDragBar::SetRect(CRect& rect, BOOL inDeskCoord) 
  70. {  
  71.     m_crTracker = rect;
  72.     m_bInDeskCoord = FALSE;
  73.  
  74.     MoveWindow(rect);
  75. }
  76.  
  77. void CDragBar::GetRect(CRect& rect)
  78. {
  79.     rect = m_crTracker;
  80.     if (m_bInDeskCoord) {
  81.         GetDesktopWindow()->MapWindowPoints( m_parentView, &rect);
  82.     }
  83. }
  84.  
  85. void CDragBar::InitLoop()
  86. {
  87.     // handle pending WM_PAINT messages
  88.     MSG msg;
  89.     while (::PeekMessage(&msg, NULL, WM_PAINT, WM_PAINT, PM_NOREMOVE))
  90.     {
  91.         if (!GetMessage(&msg, NULL, WM_PAINT, WM_PAINT))
  92.             return;
  93.         DispatchMessage(&msg);
  94.     }
  95.     m_bDitherLast = FALSE;
  96.     m_rectLast.SetRectEmpty();
  97.  
  98.     CWnd* pWnd = CWnd::GetDesktopWindow();
  99.     if (pWnd->LockWindowUpdate())
  100.         m_pDC = pWnd->GetDCEx(NULL, DCX_WINDOW|DCX_CACHE|DCX_LOCKWINDOWUPDATE);
  101.     else
  102.         m_pDC = pWnd->GetDCEx(NULL, DCX_WINDOW|DCX_CACHE);
  103.     ASSERT(m_pDC != NULL);
  104. }
  105.  
  106. void CDragBar::CancelLoop()
  107. {
  108.     DrawFocusRect(TRUE);    // gets rid of focus rect
  109.     ReleaseCapture();
  110.  
  111.     CWnd* pWnd = CWnd::GetDesktopWindow();
  112. #ifdef XP_WIN32
  113.     pWnd->UnlockWindowUpdate();
  114. #else
  115.     ASSERT(::IsWindow(m_hWnd));
  116.     ::LockWindowUpdate(NULL); 
  117. #endif
  118.     if (m_pDC != NULL)
  119.     {
  120.         pWnd->ReleaseDC(m_pDC);
  121.         m_pDC = NULL;
  122.     }
  123. }
  124.  
  125. void CDragBar::DrawFocusRect(BOOL bRemoveRect)
  126. {
  127.     ASSERT(m_pDC != NULL);
  128.  
  129.     // default to thin frame
  130.     CSize size(CX_BORDER, CY_BORDER);
  131.  
  132.     // determine new rect and size
  133.     CRect rect;
  134.     CBrush* pWhiteBrush = CBrush::FromHandle((HBRUSH)::GetStockObject(WHITE_BRUSH));
  135.     if (bRemoveRect)
  136.         size.cx = size.cy = 0;
  137.  
  138. #ifdef XP_WIN32
  139.     CBrush *pBrush = CDC::GetHalftoneBrush();
  140.     HBRUSH hOldBrush = NULL;
  141.     if(pBrush != NULL)    {
  142.         hOldBrush = (HBRUSH)SelectObject(m_pDC->m_hDC, pBrush->m_hObject);
  143.     }
  144.     m_pDC->PatBlt(m_crTracker.left, m_crTracker.top,
  145.         m_crTracker.Width(), m_crTracker.Height(), PATINVERT);
  146.  
  147.     if(hOldBrush != NULL)    {
  148.         SelectObject(m_pDC->m_hDC, hOldBrush);
  149.     }
  150. #else
  151.     m_pDC->PatBlt(m_crTracker.left, m_crTracker.top, m_crTracker.Width(),
  152.             m_crTracker.Height(), DSTINVERT);
  153. #endif
  154.     m_rectLast = rect;
  155.     m_sizeLast = size;
  156. }
  157.  
  158. void CDragBar::OnLButtonDown(UINT nFlags, CPoint point) 
  159. {
  160.     if (!m_dockedFrame->IsTreeVisible())
  161.         return;
  162.  
  163.     //    Capture mouse events.
  164.     InitLoop();
  165.  
  166.     //    Mark the point at which the mouse went down.
  167.     //    This can be used to calculate the relative distance of the movement of the tracker.
  168.     m_cpLBDown = point;
  169.  
  170.     //    Set tracking state.
  171.     m_bDragging = TRUE;
  172.  
  173.  
  174.     CPoint cursorPt(point);
  175.     MapWindowPoints( m_parentView, &cursorPt, 1 );
  176.     m_parentView->MapWindowPoints( GetDesktopWindow(), &cursorPt, 1 );
  177.     m_ptLast = cursorPt;
  178.  
  179.     CRect parentRect;
  180.     CalcClientArea(&parentRect);
  181.     ::ClientToScreen(m_parentView->GetSafeHwnd(), &parentRect.TopLeft());
  182.     ::ClientToScreen(m_parentView->GetSafeHwnd(), &parentRect.BottomRight());
  183.     ::ClipCursor(parentRect);
  184.  
  185.     if (!m_bInDeskCoord) {
  186.         m_parentView->MapWindowPoints( GetDesktopWindow(), &m_crTracker);
  187.         m_bInDeskCoord = TRUE;
  188.     }
  189.     //    Invert the tracker.
  190.     Move(cursorPt);   // call it here to handle special keys
  191.     Track();
  192. }
  193.  
  194. void CDragBar::OnRButtonDown(UINT nFlags, CPoint point)
  195. {
  196.     m_dockedFrame->CollapseWindow();
  197. }
  198.  
  199. void CDragBar::EndDrag()
  200. {
  201.     CancelLoop();
  202.     ::ClipCursor(NULL);
  203.  
  204.     //    Set that we are no longer tracking.
  205.     m_bDragging = FALSE;
  206.     CRect tempRect(m_crTracker);
  207.     GetDesktopWindow()->MapWindowPoints( m_parentView, &tempRect);
  208.     MoveWindow(tempRect);
  209.     Invalidate();
  210.     m_dockedFrame->m_pSelector->Invalidate();
  211.     m_parentView->RecalcLayout();
  212. }
  213.  
  214. void CDragBar::Move( CPoint point )
  215. {
  216.     CPoint ptOffset = point - m_ptLast;
  217.     //    If we're currently tracking, simply update the coords.
  218.     if(m_bDragging == TRUE)    {
  219.         //    Turn off the tracker.
  220.         DrawFocusRect();
  221.  
  222.         if (m_orientation == DOCKSTYLE_VERTLEFT ||
  223.             (m_orientation == DOCKSTYLE_VERTRIGHT)) {
  224.             ptOffset.y = 0;
  225.         }
  226.         else {
  227.             ptOffset.x = 0;
  228.         }
  229.         m_crTracker.OffsetRect(ptOffset);
  230.         //    Turn on the tracker.
  231.         DrawFocusRect();
  232.         m_ptLast = point;
  233.         return;
  234.     }
  235. }
  236. void CDragBar::OnMouseMove( UINT nFlags, CPoint point )
  237. {
  238.     if(m_bDragging == TRUE)    return;
  239.     if (!m_dockedFrame->IsTreeVisible())  // Cannot drag when tree is closed.
  240.         return;
  241.  
  242.     static HCURSOR hcurLast = NULL;
  243.     static HCURSOR hcurDestroy = NULL;
  244.     static UINT uLastCursorID = 0;
  245.     UINT uCursorID;
  246.  
  247.     //    Decide which cursor we want to load.
  248.     if (m_orientation == DOCKSTYLE_HORZTOP || 
  249.         m_orientation == DOCKSTYLE_HORZBOTTOM) {
  250.         //    Horizontal.
  251.         uCursorID = AFX_IDC_VSPLITBAR;
  252.     }
  253.     else    {
  254.         //    Vertical.
  255.         uCursorID = AFX_IDC_HSPLITBAR;
  256.     }
  257.  
  258.     //    Only if not already loaded.
  259.     HCURSOR hcurToDestroy = NULL;
  260.     if(uCursorID != uLastCursorID)    {
  261.         HINSTANCE hInst =
  262. #ifdef _AFXDLL
  263.         AfxFindResourceHandle(MAKEINTRESOURCE(uCursorID), RT_GROUP_CURSOR);
  264. #else
  265.         AfxGetResourceHandle();
  266. #endif
  267.  
  268.         //    Load in another cursor.
  269.         hcurToDestroy = hcurDestroy;
  270.  
  271.         hcurDestroy = hcurLast = ::LoadCursor(hInst, MAKEINTRESOURCE(uCursorID));
  272.         uLastCursorID = uCursorID;
  273.     }
  274.  
  275.     //    Set the cursor.
  276.     ::SetCursor(hcurLast);
  277.  
  278.     //    Destroy the previous cursor if need be.
  279.     if(hcurToDestroy != NULL)    {
  280.         ::DestroyCursor(hcurToDestroy);
  281.     }
  282. }
  283.  
  284. BOOL CDragBar::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message) 
  285. {
  286.     if (nHitTest == HTCLIENT && pWnd == this && !m_bDragging)    {
  287.         return TRUE;    // we will handle it in the mouse move
  288.     }
  289.     
  290.     return CWnd::OnSetCursor(pWnd, nHitTest, message);
  291. }
  292.  
  293. void CDragBar::OnPaint() 
  294. {
  295.     CPaintDC dc(this); // device context for painting
  296.     
  297.     //    The area we're drawing.
  298.     CRect crRect;
  299.     GetClientRect(crRect);
  300.     //    Draw it as the button face if no other color available.
  301.     WFE_FillSolidRect((CDC *)&dc, crRect, sysInfo.m_clrBtnFace);
  302. #ifndef XP_WIN32
  303.     short dockStyle = m_dockedFrame->GetDockStyle();
  304.  
  305.     WFE_FillSolidRect((CDC *)&dc, crRect, RGB(255, 255, 255));
  306.     HDC hdc = dc.GetSafeHdc();
  307.     ::SelectObject(hdc, ::GetStockObject(BLACK_PEN));
  308.     if ((dockStyle == DOCKSTYLE_VERTLEFT) || (dockStyle == DOCKSTYLE_VERTRIGHT)) {
  309.         ::MoveTo(hdc,crRect.left, crRect.top);
  310.         ::LineTo(hdc,crRect.left, crRect.bottom);
  311.         ::MoveTo(hdc,crRect.right-1, crRect.top);
  312.         ::LineTo(hdc,crRect.right-1, crRect.bottom);
  313.     }
  314.     else {
  315.         ::MoveTo(hdc,crRect.left, crRect.bottom);
  316.         ::LineTo(hdc,crRect.right, crRect.bottom);
  317.         ::MoveTo(hdc,crRect.left, crRect.top);
  318.         ::LineTo(hdc,crRect.right, crRect.top);
  319.     }
  320. #endif
  321. }
  322.  
  323. void CDragBar::OnLButtonDblClk(UINT nFlags, CPoint point) 
  324. {
  325.     //    Treat same as button down.
  326.     OnLButtonDown(nFlags, point);
  327. }
  328.  
  329. void CDragBar::CalcClientArea(RECT* lpRectClient)
  330. {
  331.  
  332.     AFX_SIZEPARENTPARAMS layout;
  333. #ifdef XP_WIN32
  334.     layout.bStretch = FALSE;
  335.     layout.sizeTotal.cx = layout.sizeTotal.cy = 0;
  336. #endif
  337.     m_parentView->GetClientRect(&layout.rect);    // starting rect comes from client rect
  338.     CWnd *pView = m_parentView->GetDescendantWindow(AFX_IDW_PANE_FIRST, TRUE);
  339.     HWND hWnd = pView->GetSafeHwnd();
  340.  
  341.     layout.hDWP = NULL; // not actually doing layout
  342.  
  343.     for (HWND hWndChild = ::GetTopWindow(m_parentView->GetSafeHwnd()); hWndChild != NULL;
  344.         hWndChild = ::GetNextWindow(hWndChild, GW_HWNDNEXT))
  345.     {
  346.         if (hWndChild != hWnd && hWndChild != GetSafeHwnd() && hWndChild != m_dockedFrame->GetSafeHwnd())
  347.             ::SendMessage(hWndChild, WM_SIZEPARENT, 0, (LPARAM)&layout);
  348.     }
  349.     short dockStyle = m_dockedFrame->GetDockStyle();
  350.  
  351.     lpRectClient->left = layout.rect.left;
  352.     lpRectClient->right = layout.rect.right;
  353.     lpRectClient->top = layout.rect.top;
  354.     lpRectClient->bottom = layout.rect.bottom;
  355.     if (dockStyle == DOCKSTYLE_VERTLEFT) 
  356.        lpRectClient->left += MIN_CATEGORY_WIDTH;
  357.     else if (dockStyle == DOCKSTYLE_VERTRIGHT) 
  358.        lpRectClient->right -= MIN_CATEGORY_WIDTH;
  359.     else if (dockStyle == DOCKSTYLE_HORZTOP) 
  360.        lpRectClient->top += MIN_CATEGORY_HEIGHT;
  361.     else if (dockStyle == DOCKSTYLE_HORZBOTTOM) 
  362.        lpRectClient->bottom -= MIN_CATEGORY_HEIGHT;
  363.  
  364. }
  365.  
  366. BOOL CDragBar::Track()
  367. {
  368.     // don't handle if capture already set
  369.     if (::GetCapture() != NULL)
  370.         return FALSE;
  371.  
  372.     // set capture to the window which received this message
  373.     SetCapture();
  374.  
  375.     // get messages until capture lost or cancelled/accepted
  376.     while (CWnd::GetCapture() == this) {
  377.         MSG msg;
  378.         if (!::GetMessage(&msg, NULL, 0, 0))
  379.         {
  380. #ifdef XP_WIN32
  381.             AfxPostQuitMessage(msg.wParam);
  382. #endif
  383.             break;
  384.         }
  385.  
  386.         switch (msg.message)
  387.         {
  388.         case WM_LBUTTONUP:
  389.             if (m_bDragging)
  390.                 m_bDragging = FALSE;
  391.             EndDrag();
  392.             return TRUE;
  393.         case WM_MOUSEMOVE:
  394.             if (m_bDragging)
  395.                 Move(msg.pt);
  396.             break;
  397.         case WM_RBUTTONDOWN:
  398.             CancelLoop();
  399.             return FALSE;
  400.  
  401.         // just dispatch rest of the messages
  402.         default:
  403.             DispatchMessage(&msg);
  404.             break;
  405.         }
  406.     }
  407.     CancelLoop();
  408.  
  409.     return FALSE;
  410. }
  411.