📄 toolwnd.cpp
字号:
/////////////////////////////////////////////////////////////////////////////
// Name: toolwnd.cpp
// Purpose: wxToolWindow implementation.
// Author: Aleksandras Gluchovas
// Modified by:
// Created: 06/09/98
// RCS-ID: $Id: toolwnd.cpp,v 1.19 2005/09/23 12:47:44 MR Exp $
// Copyright: (c) Aleksandras Gluchovas
// Licence: wxWindows licence
/////////////////////////////////////////////////////////////////////////////
// For compilers that support precompilation, includes "wx.h".
#include "wx/wxprec.h"
#ifdef __BORLANDC__
#pragma hdrstop
#endif
#ifndef WX_PRECOMP
#include "wx/wx.h"
#endif
#include "wx/fl/toolwnd.h"
#define _IMG_A 0xAA // Note: modified from _A to _IMG_A, _A was already defined (cygwin)
#define _IMG_B 0x00 // Note: modified from _B to _IMG_A, _B was already defined (cygwin)
#define _IMG_C 0x55 // Note: modified from _C to _IMG_C, for consistency reasons.
#define _IMG_D 0x00 // Note: modified from _D to _IMG_D, for consistency reasons.
// FOR NOW:: static
static const unsigned char _gCheckerImg[16] = { _IMG_A,_IMG_B,_IMG_C,_IMG_D,
_IMG_A,_IMG_B,_IMG_C,_IMG_D,
_IMG_A,_IMG_B,_IMG_C,_IMG_D,
_IMG_A,_IMG_B,_IMG_C,_IMG_D
};
/***** Implementation for class wxToolWindow *****/
IMPLEMENT_DYNAMIC_CLASS( wxToolWindow, wxFrame)
BEGIN_EVENT_TABLE( wxToolWindow, wxFrame )
EVT_PAINT ( wxToolWindow::OnPaint )
EVT_MOTION ( wxToolWindow::OnMotion )
EVT_LEFT_DOWN( wxToolWindow::OnLeftDown )
EVT_LEFT_UP ( wxToolWindow::OnLeftUp )
EVT_SIZE ( wxToolWindow::OnSize )
EVT_ERASE_BACKGROUND( wxToolWindow::OnEraseBackground )
END_EVENT_TABLE()
enum INTERNAL_HIT_CODES
{
HITS_WND_NOTHING,
HITS_WND_CLIENT,
HITS_WND_TITLE,
HITS_WND_LEFT_EDGE,
HITS_WND_RIGHT_EDGE,
HITS_WND_TOP_EDGE,
HITS_WND_BOTTOM_EDGE,
HITS_WND_TOP_LEFT_CORNER,
HITS_WND_BOTTOM_RIGHT_CORNER,
HITS_WND_TOP_RIGHT_CORNER,
HITS_WND_BOTTOM_LEFT_CORNER
};
wxToolWindow::wxToolWindow()
: mpClientWnd ( NULL ),
#ifndef __WXMSW__
mTitleFont( 8, wxSWISS, wxNORMAL, wxNORMAL ),
#else
// just to simulate MS-Dev style
mTitleFont( 8, wxSWISS, wxNORMAL, wxNORMAL, false, wxT("MS Sans Serif") ),
#endif
mTitleHeight ( 16 ),
mClntHorizGap ( 2 ),
mClntVertGap ( 2 ),
mWndVertGap ( 4 ),
mWndHorizGap ( 4 ),
mButtonGap ( 2 ),
mInTitleMargin( 4 ),
mHintBorder ( 4 ),
mResizeStarted( false ),
mRealTimeUpdatesOn( true ),
mMTolerance ( 5 ), // mouse-resizing tollerance
mCursorType( HITS_WND_NOTHING ),
mMouseCaptured( false ),
mpScrDc( NULL )
{
}
wxToolWindow::~wxToolWindow()
{
if ( mpScrDc ) delete mpScrDc;
for( size_t i = 0; i != mButtons.Count(); ++i )
delete mButtons[i];
}
void wxToolWindow::LayoutMiniButtons()
{
int w,h;
GetSize( &w, &h );
int x = w - mWndHorizGap - mInTitleMargin - BTN_BOX_WIDTH;
int y = mWndVertGap + 2;
for( size_t i = 0; i != mButtons.Count(); ++i )
{
mButtons[i]->SetPos( wxPoint( x,y ) );
x-= BTN_BOX_WIDTH + mButtonGap;
}
}
void wxToolWindow::SetClient( wxWindow* pWnd )
{
mpClientWnd = pWnd;
}
wxWindow* wxToolWindow::GetClient()
{
return mpClientWnd;
}
void wxToolWindow::SetTitleFont( wxFont& font )
{
mTitleFont = font;
}
void wxToolWindow::AddMiniButton( cbMiniButton* pBtn )
{
pBtn->mpWnd = this;
mButtons.Add( pBtn );
// not necesserely now..
//LayoutMiniButtons();
}
void wxToolWindow::OnPaint( wxPaintEvent& WXUNUSED(event) )
{
wxPaintDC pdc( this );
wxWindowDC dc( this );
int w,h;
GetSize( &w, &h );
wxBrush backGround( wxSystemSettings::GetColour(wxSYS_COLOUR_BTNFACE), wxSOLID );
//dc.SetBrush( *wxLIGHT_GREY_BRUSH );
dc.SetBrush( backGround );
dc.SetPen( *wxTRANSPARENT_PEN );
int y = mWndVertGap + mTitleHeight + mClntVertGap;
dc.DrawRectangle( 0,0, w, y ); // Top grey part.
dc.DrawRectangle( 0,y-1, mWndHorizGap + mClntHorizGap, h - y ); // Left grey part.
dc.DrawRectangle( w - ( mWndHorizGap + mClntHorizGap ), y-1,
mWndHorizGap + mClntHorizGap, h - y ); // Right grey part.
dc.DrawRectangle( 0, h - mWndVertGap - mClntVertGap, w, mWndVertGap + mClntVertGap ); // Bottom grey part.
// draw shades
dc.SetPen( *wxLIGHT_GREY_PEN );
dc.DrawLine( 0,0, w, 0 );
dc.DrawLine( 0,0, 0, h );
dc.SetPen( *wxWHITE_PEN );
dc.DrawLine( 1,1, w, 1 );
dc.DrawLine( 1,2, 1, h );
dc.SetPen( *wxGREY_PEN );
dc.DrawLine( w - 2, 1, w - 2, h - 1 );
dc.DrawLine( 1, h - 2, w - 2, h - 2 );
dc.SetPen( *wxBLACK_PEN );
dc.DrawLine( 0, h - 1, w, h - 1 );
dc.DrawLine( w-1, 0, w-1, h );
// fill inner area
dc.SetBrush( *wxTheBrushList->FindOrCreateBrush( wxColour( 0,0,128 ), wxSOLID ) );
dc.DrawRectangle( mWndHorizGap, mWndVertGap, w - mWndHorizGap*2, mTitleHeight );
dc.SetFont( mTitleFont );
for( size_t i = 0; i != mButtons.Count(); ++i )
mButtons[i]->Draw( dc );
int x1 = mWndHorizGap + mClntHorizGap;
int x2 = mButtons[ mButtons.GetCount() - 1 ]->mPos.x - mClntHorizGap*2;
dc.SetClippingRegion( x1, mWndVertGap + mClntVertGap, x2 - x1, mTitleHeight );
dc.SetTextForeground( *wxWHITE );
dc.SetBackgroundMode( wxTRANSPARENT );
dc.DrawText( GetTitle(), mWndHorizGap + 2, mWndVertGap + 1 );
}
void wxToolWindow::GetScrWindowRect( wxRect& r )
{
int x,y;
GetPosition(&x,&y);
int w,h;
GetSize( &w, &h );
r.x = x; r.y = y;
r.width = w; r.height = h;
}
void wxToolWindow::GetScrMousePos( wxMouseEvent& event, wxPoint& pos )
{
int x = event.m_x, y = event.m_y;
ClientToScreen( &x, &y );
pos.x = x; pos.y = y;
}
int wxToolWindow::HitTestWindow( wxMouseEvent& event )
{
wxPoint pos;
wxRect r;
GetScrMousePos( event, pos );
GetScrWindowRect( r );
int k = mMTolerance;
if ( !( pos.x >= r.x && pos.y >= r.y &&
pos.x < r.x + r.width &&
pos.y < r.y + r.height )
)
return HITS_WND_NOTHING;
if ( pos.y <= r.y + k )
{
if ( pos.x < r.x + k*2 )
return HITS_WND_TOP_LEFT_CORNER;
else
{
if ( pos.x >= r.x + r.width - k*2 )
return HITS_WND_TOP_RIGHT_CORNER;
else
return HITS_WND_TOP_EDGE;
}
}
else
{
if ( pos.y >= r.y + r.height - k )
{
if ( pos.x < r.x + k*2 )
return HITS_WND_BOTTOM_LEFT_CORNER;
else
{
if ( pos.x > r.x + r.width - k*2 )
return HITS_WND_BOTTOM_RIGHT_CORNER;
else
return HITS_WND_BOTTOM_EDGE;
}
}
else
{
if ( pos.x <= r.x + k )
return HITS_WND_LEFT_EDGE;
else
{
if ( pos.x >= r.x + r.width - k )
return HITS_WND_RIGHT_EDGE;
else
{
if ( pos.y <= r.y + mWndVertGap + mTitleHeight + mClntVertGap )
return HITS_WND_TITLE;
else
return HITS_WND_CLIENT;
}
}
}
}
}
void wxToolWindow::DrawHintRect( const wxRect& r )
{
// BUG BUG BUG (wx):: somehow stippled brush works only
// when the bitmap created on stack, not
// as a member of the class
int prevLF = mpScrDc->GetLogicalFunction();
mpScrDc->SetLogicalFunction( wxXOR );
wxBitmap checker( (const char*)_gCheckerImg, 8,8 );
wxBrush checkerBrush( checker );
mpScrDc->SetPen( *wxTRANSPARENT_PEN );
mpScrDc->SetBrush( checkerBrush );
int half = mHintBorder / 2;
mpScrDc->DrawRectangle( r.x - half, r.y - half,
r.width + 2*half, mHintBorder );
mpScrDc->DrawRectangle( r.x - half, r.y + r.height - half,
r.width + 2*half, mHintBorder );
mpScrDc->DrawRectangle( r.x - half, r.y + half - 1,
mHintBorder, r.height - 2*half + 2);
mpScrDc->DrawRectangle( r.x + r.width - half,
r.y + half - 1,
mHintBorder, r.height - 2*half + 2);
mpScrDc->SetBrush( wxNullBrush );
mpScrDc->SetLogicalFunction( prevLF );
}
void wxToolWindow::SetHintCursor( int type )
{
if ( mResizeStarted )
return;
if ( type == HITS_WND_NOTHING || type == HITS_WND_CLIENT )
{
// the cursor is out of window - reset to arrow
if ( mMouseCaptured )
{
ReleaseMouse();
mMouseCaptured = false;
}
SetCursor( wxCURSOR_ARROW );
mCursorType = type;
return;
}
// did the cursor actually changed?
if ( type != mCursorType )
{
mCursorType = type;
switch ( type )
{
case HITS_WND_LEFT_EDGE : SetCursor( wxCURSOR_SIZEWE ); break;
case HITS_WND_RIGHT_EDGE : SetCursor( wxCURSOR_SIZEWE ); break;
case HITS_WND_TOP_EDGE : SetCursor( wxCURSOR_SIZENS ); break;
case HITS_WND_BOTTOM_EDGE : SetCursor( wxCURSOR_SIZENS ); break;
case HITS_WND_TOP_LEFT_CORNER : SetCursor( wxCURSOR_SIZENWSE ); break;
case HITS_WND_BOTTOM_RIGHT_CORNER : SetCursor( wxCURSOR_SIZENWSE ); break;
case HITS_WND_TOP_RIGHT_CORNER : SetCursor( wxCURSOR_SIZENESW ); break;
case HITS_WND_BOTTOM_LEFT_CORNER : SetCursor( wxCURSOR_SIZENESW ); break;
case HITS_WND_TITLE : SetCursor( wxCURSOR_ARROW ); break;
case HITS_WND_CLIENT : SetCursor( wxCURSOR_ARROW ); break;
default: break;
}
if (mMouseCaptured)
{
mMouseCaptured = false;
ReleaseMouse();
}
}
if ( !mMouseCaptured )
{
mMouseCaptured = true;
CaptureMouse();
}
}
#define FL_INFINITY 32768
static inline void clip_to( int& value, long from, long till )
{
if ( value < from )
value = from;
if ( value > till )
value = till;
}
void wxToolWindow::AdjustRectPos( const wxRect& original, const wxSize& newDim, wxRect& newRect )
{
if ( mCursorType == HITS_WND_TOP_EDGE ||
mCursorType == HITS_WND_TOP_LEFT_CORNER )
{
newRect.x = original.x + original.width - newDim.x;
newRect.y = original.y + original.height - newDim.y;
}
else
if ( mCursorType == HITS_WND_LEFT_EDGE ||
mCursorType == HITS_WND_BOTTOM_LEFT_CORNER )
{
newRect.x = original.x + original.width - newDim.x;
newRect.y = original.y;
}
else
if ( mCursorType == HITS_WND_RIGHT_EDGE ||
mCursorType == HITS_WND_TOP_RIGHT_CORNER )
{
newRect.x = original.x;
newRect.y = original.y + original.height - newDim.y;
}
else
if ( mCursorType == HITS_WND_BOTTOM_EDGE ||
mCursorType == HITS_WND_BOTTOM_RIGHT_CORNER )
{
newRect.x = original.x;
newRect.y = original.y;
}
newRect.width = newDim.x;
newRect.height = newDim.y;
}
void wxToolWindow::CalcResizedRect( wxRect& rect, wxPoint& delta, const wxSize& minDim )
{
// Microsoft's rect-coordinates are best suited
// for the case of corner-clipping
int left = mInitialRect.x;
int top = mInitialRect.y;
int right = mInitialRect.x + mInitialRect.width;
int bottom = mInitialRect.y + mInitialRect.height;
// constraint delta edge is dragged
switch ( mCursorType )
{
case HITS_WND_LEFT_EDGE : delta.y = 0; break;
case HITS_WND_RIGHT_EDGE : delta.y = 0; break;
case HITS_WND_TOP_EDGE : delta.x = 0; break;
case HITS_WND_BOTTOM_EDGE : delta.x = 0; break;
default: break;
}
if ( mCursorType == HITS_WND_TOP_EDGE ||
mCursorType == HITS_WND_TOP_LEFT_CORNER )
{
left += delta.x;
top += delta.y;
clip_to( left, -FL_INFINITY, mInitialRect.x + mInitialRect.width - minDim.x );
clip_to( top, -FL_INFINITY, mInitialRect.y + mInitialRect.height - minDim.y );
}
else
if ( mCursorType == HITS_WND_LEFT_EDGE ||
mCursorType == HITS_WND_BOTTOM_LEFT_CORNER )
{
left += delta.x;
bottom += delta.y;
clip_to( left, -FL_INFINITY, mInitialRect.x + mInitialRect.width - minDim.x );
clip_to( bottom, mInitialRect.y + minDim.y, FL_INFINITY );
}
else
if ( mCursorType == HITS_WND_RIGHT_EDGE ||
mCursorType == HITS_WND_TOP_RIGHT_CORNER )
{
right += delta.x;
top += delta.y;
clip_to( right, mInitialRect.x + minDim.x, FL_INFINITY );
clip_to( top, -FL_INFINITY, mInitialRect.y + mInitialRect.height - minDim.y );
}
else
if ( mCursorType == HITS_WND_BOTTOM_EDGE ||
mCursorType == HITS_WND_BOTTOM_RIGHT_CORNER )
{
right += delta.x;
bottom += delta.y;
clip_to( right, mInitialRect.x + minDim.x, FL_INFINITY );
clip_to( bottom, mInitialRect.y + minDim.y, FL_INFINITY );
}
else
{
wxFAIL_MSG( _T("what did the cursor hit?") );
}
rect.x = left;
rect.y = top;
rect.width = right - left;
rect.height = bottom - top;
}
wxSize wxToolWindow::GetMinimalWndDim()
{
return wxSize( (mWndHorizGap + mClntHorizGap)*2 + BTN_BOX_WIDTH*4,
(mWndVertGap + mClntVertGap )*2 + mTitleHeight );
}
void wxToolWindow::OnMotion( wxMouseEvent& event )
{
if ( !mResizeStarted )
{
for( size_t i = 0; i != mButtons.Count(); ++i )
mButtons[i]->OnMotion( wxPoint( event.m_x, event.m_y ) );
SetHintCursor( HitTestWindow( event ) );
return;
}
wxPoint pos;
GetScrMousePos( event, pos );
if ( mCursorType == HITS_WND_TITLE )
{
int w,h;
GetSize( &w, &h );
SetSize( mInitialRect.x + pos.x - mDragOrigin.x,
mInitialRect.y + pos.y - mDragOrigin.y,
w,h, 0 );
}
else
{
wxPoint delta( pos.x - mDragOrigin.x, pos.y - mDragOrigin.y );
wxRect newRect;
wxSize minDim = GetMinimalWndDim();
CalcResizedRect( newRect, delta, minDim );
wxSize borderDim( ( mWndHorizGap + mClntHorizGap )*2,
( mWndVertGap + mClntVertGap )*2 + mTitleHeight );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -