WindowsXP-SP1/enduser/stuff/hhctrl/sizebar.cpp

326 lines
8.5 KiB
C++

///////////////////////////////////////////////////////////
//
//
// SIZEBAR.cpp - CSizeBar control encapsulates the sizebar
//
//
//
// Copyright (C) 1996-1997 Microsoft Corporation. All rights reserved.
///////////////////////////////////////////////////////////
//
// Includes
//
#include "header.h"
#ifdef _DEBUG
#undef THIS_FILE
static const char THIS_FILE[] = __FILE__;
#endif
#include "system.h"
#include "secwin.h"
#include "contain.h"
// For ID_TAB_CONTROL
#include "resource.h"
#include "windowsx.h"
// For the ScreenRectToClientRect Function.
#include "navpane.h"
///////////////////////////////////////////////////////////
//
// external functions.
//
///////////////////////////////////////////////////////////
//
// Constructor
//
CSizeBar::CSizeBar()
: m_hWnd(NULL),
m_hWndParent(NULL),
m_pWinType(NULL),
m_bDragging(false)
{
}
///////////////////////////////////////////////////////////
//
// Destructor
//
CSizeBar::~CSizeBar()
{
if ( IsValidWindow(m_hWnd) )
{
DestroyWindow( m_hWnd);
}
}
///////////////////////////////////////////////////////////
//
// Operations
///////////////////////////////////////////////////////////
//
// Create
//
bool
CSizeBar::Create(CHHWinType* pWinType)
{
// Validate
ASSERT(pWinType) ;
ASSERT(IsValidWindow(pWinType->GetHwnd())) ;
// Save
m_hWndParent = pWinType->GetHwnd();
m_pWinType = pWinType ;
// Calc the size
RECT rcSizeBar ;
CalcSize(&rcSizeBar) ;
// Create the window.
m_hWnd = CreateWindow(txtSizeBarChildWindowClass, NULL,
WS_CHILD | WS_VISIBLE,
rcSizeBar.left, rcSizeBar.top,
RECT_WIDTH(rcSizeBar), RECT_HEIGHT(rcSizeBar),
m_hWndParent, NULL, _Module.GetModuleInstance(), NULL);
if (m_hWnd)
{
// Set the userdata to our this pointer.
SetWindowLongPtr(m_hWnd, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(this));
return true;
}
else
return false ;
}
///////////////////////////////////////////////////////////
//
// ResizeWindow
void
CSizeBar::ResizeWindow()
{
// Validate
ASSERT(IsValidWindow(hWnd())) ;
// Calculate our size.
RECT rc;
CalcSize(&rc); // This will be the navigation window.
// Size the window.
MoveWindow(hWnd(), rc.left, rc.top,
RECT_WIDTH(rc), RECT_HEIGHT(rc),
TRUE); // need to repaint the sizebar when their is a margin on the right
// end of the toolbar so the ghost of the sizebar is removed
// Redraw the sizebar.
Draw() ;
}
///////////////////////////////////////////////////////////
//
// RegisterWindowClass
//
void
CSizeBar::RegisterWindowClass()
{
WNDCLASS wc;
ZeroMemory(&wc, sizeof(WNDCLASS)); // clear all members
wc.hInstance = _Module.GetModuleInstance();
wc.hbrBackground = (HBRUSH) COLOR_WINDOW;
//wc.lpszMenuName = MAKEINTRESOURCE(HH_MENU);
wc.lpfnWndProc = s_SizeBarProc;
wc.lpszClassName = txtSizeBarChildWindowClass;
wc.hCursor = LoadCursor(NULL, IDC_SIZEWE);
VERIFY(RegisterClass(&wc));
}
///////////////////////////////////////////////////////////
//
// Access Functions
//
///////////////////////////////////////////////////////////
//
// Width
//
int
CSizeBar::Width()
{
// Current the width is fixed, but based on metrics.
return GetSystemMetrics(SM_CXSIZEFRAME);
}
///////////////////////////////////////////////////////////
//
// Internal Helper Functions
//
///////////////////////////////////////////////////////////
//
// CalcSize
//
void
CSizeBar::CalcSize(RECT* prect)
{
ASSERT(m_pWinType) ;
// Get the size of the HTML Help window.
RECT rectHtml ;
::GetWindowRect(m_pWinType->GetHTMLHwnd(), &rectHtml );
// Convert to the coordinates of help window itself.
ScreenRectToClientRect(m_hWndParent, &rectHtml) ;
// Now use this information to create our rectangle.
prect->left = rectHtml.left - Width() ;
prect->right = prect->left + Width() ;
prect->top = rectHtml.top ;
prect->bottom = rectHtml.bottom ;
}
///////////////////////////////////////////////////////////
//
// Draw
//
void
CSizeBar::Draw()
{
// Get a dc to draw in.
HDC hdc = GetDC(hWnd()) ;
// get the rectangle to draw on.
RECT rc ;
GetClientRect(hWnd(), &rc) ;
// Draw the edge.
DrawEdge(hdc, &rc, EDGE_ETCHED,
m_bDragging ? (BF_TOPLEFT | BF_BOTTOMRIGHT | BF_MIDDLE) :(BF_TOPLEFT | BF_BOTTOM | BF_MIDDLE)) ;
// Clean up.
ReleaseDC(hWnd(), hdc) ;
}
///////////////////////////////////////////////////////////
//
// Member function Window Proc
//
LRESULT
CSizeBar::SizeBarProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg)
{
case WM_LBUTTONDOWN:
if ( wParam == MK_LBUTTON && m_pWinType)
{
SetCapture(hwnd); // capture the mouse to this window.
m_offset = GET_X_LPARAM(lParam) ; // The initial x position happens to be the offset.
m_bDragging = true ;
}
break;
case WM_LBUTTONUP:
if (m_bDragging && (GetCapture() == hwnd))
{
ReleaseCapture(); // release the mouse capture from this window.
//TODO - This nasty code uses to many internal members of CHHWinType...
// Get the rectangle for the sizebar.
RECT rcSizeBar ;
GetWindowRect(m_hWnd, &rcSizeBar) ;
ScreenRectToClientRect(m_pWinType->GetHwnd(), &rcSizeBar) ;
// Change the left size of the Topic pane.
m_pWinType->rcHTML.left = rcSizeBar.right;
// move the Nav Pane
ASSERT(m_pWinType->GetNavigationHwnd());
if (m_pWinType->IsExpandedNavPane() &&
IsValidWindow(m_pWinType->hwndNavigation))
{
m_pWinType->rcNav.right = rcSizeBar.left;
}
// resize the tab control and its' dialogs. This will also resize the sizebar and draw it.
::ResizeWindow(m_pWinType, false); // This is the one defined in wndproc.cpp. Don't recalc the sizes. Use the ones we've set.
m_bDragging = false ;
}
break;
case WM_MOUSEMOVE:
if (m_bDragging)
{
ASSERT(m_pWinType) ;
// Get the rectangle for the htmlhelp window.
RECT rcHelpWin;
GetClientRect(m_pWinType->GetHwnd(), &rcHelpWin);
// Get the rectangle for the sizebar.
RECT rcSizeBar ;
GetWindowRect(m_hWnd, &rcSizeBar) ;
// Calculate the new position.
ScreenRectToClientRect(m_pWinType->GetHwnd(), &rcSizeBar) ;
rcSizeBar.left += GET_X_LPARAM(lParam) - m_offset ;
// The width of rcSizeBar is now not correct.
// Validate the new position.
if ( (rcSizeBar.left > MinimumPaneWidth()) && // Check left side.
(rcSizeBar.left + Width() < rcHelpWin.right - MinimumTopicWidth()) ) // Check right boundary.
{
// Move it.
SetWindowPos(m_hWnd, NULL,
rcSizeBar.left,
rcSizeBar.top,
0,0,
SWP_NOOWNERZORDER | SWP_NOSIZE | SWP_NOZORDER) ;
}
}
break;
case WM_PAINT:
{
// Draw an edige on the left side of the size bar.
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hwnd, &ps) ;
Draw() ;
EndPaint(hwnd, &ps) ;
}
break ;
case WM_ERASEBKGND:
return 1; // We don't want the background erased.
default:
return DefWindowProc(hwnd, msg, wParam, lParam);
}
return 0;
}
///////////////////////////////////////////////////////////
//
// Callbacks
//
///////////////////////////////////////////////////////////
//
// Static Window Proc
//
LRESULT WINAPI
CSizeBar::s_SizeBarProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
CSizeBar* pThis = reinterpret_cast<CSizeBar*>(GetWindowLongPtr(hwnd, GWLP_USERDATA));
if (pThis)
return pThis->SizeBarProc(hwnd, msg, wParam, lParam) ;
else
return DefWindowProc(hwnd, msg, wParam, lParam);
}