tbar95.cpp
来自「A*算法 A*算法 A*算法 A*算法A*算法A*算法」· C++ 代码 · 共 1,707 行 · 第 1/4 页
CPP
1,707 行
const long styleOld = GetWindowStyle();
wxToolBarBase::SetWindowStyleFlag(style);
// don't recreate an empty toolbar: not only this is unnecessary, but it is
// also fatal as we'd then try to recreate the toolbar when it's just being
// created
if ( GetToolsCount() &&
(style & MASK_NEEDS_RECREATE) != (styleOld & MASK_NEEDS_RECREATE) )
{
// to remove the text labels, simply re-realizing the toolbar is enough
// but I don't know of any way to add the text to an existing toolbar
// other than by recreating it entirely
Recreate();
}
}
// ----------------------------------------------------------------------------
// tool state
// ----------------------------------------------------------------------------
void wxToolBar::DoEnableTool(wxToolBarToolBase *tool, bool enable)
{
::SendMessage(GetHwnd(), TB_ENABLEBUTTON,
(WPARAM)tool->GetId(), (LPARAM)MAKELONG(enable, 0));
}
void wxToolBar::DoToggleTool(wxToolBarToolBase *tool, bool toggle)
{
::SendMessage(GetHwnd(), TB_CHECKBUTTON,
(WPARAM)tool->GetId(), (LPARAM)MAKELONG(toggle, 0));
}
void wxToolBar::DoSetToggle(wxToolBarToolBase *WXUNUSED(tool), bool WXUNUSED(toggle))
{
// VZ: AFAIK, the button has to be created either with TBSTYLE_CHECK or
// without, so we really need to delete the button and recreate it here
wxFAIL_MSG( _T("not implemented") );
}
// ----------------------------------------------------------------------------
// event handlers
// ----------------------------------------------------------------------------
// Responds to colour changes, and passes event on to children.
void wxToolBar::OnSysColourChanged(wxSysColourChangedEvent& event)
{
wxRGBToColour(m_backgroundColour, ::GetSysColor(COLOR_BTNFACE));
// Remap the buttons
Realize();
// Relayout the toolbar
int nrows = m_maxRows;
m_maxRows = 0; // otherwise SetRows() wouldn't do anything
SetRows(nrows);
Refresh();
// let the event propagate further
event.Skip();
}
void wxToolBar::OnMouseEvent(wxMouseEvent& event)
{
if (event.Leaving() && m_pInTool)
{
OnMouseEnter( -1 );
event.Skip();
return;
}
if ( event.RightDown() )
{
// find the tool under the mouse
wxCoord x,y;
event.GetPosition(&x, &y);
wxToolBarToolBase *tool = FindToolForPosition(x, y);
OnRightClick(tool ? tool->GetId() : -1, x, y);
}
else
{
event.Skip();
}
}
// This handler is required to allow the toolbar to be set to a non-default
// colour: for example, when it must blend in with a notebook page.
void wxToolBar::OnEraseBackground(wxEraseEvent& event)
{
wxColour bgCol = GetBackgroundColour();
if (!bgCol.Ok())
{
event.Skip();
return;
}
// notice that this 'dumb' implementation may cause flicker for some of the
// controls in which case they should intercept wxEraseEvent and process it
// themselves somehow
RECT rect;
::GetClientRect(GetHwnd(), &rect);
HBRUSH hBrush = ::CreateSolidBrush(wxColourToRGB(bgCol));
HDC hdc = GetHdcOf((*event.GetDC()));
#ifndef __WXWINCE__
int mode = ::SetMapMode(hdc, MM_TEXT);
#endif
::FillRect(hdc, &rect, hBrush);
::DeleteObject(hBrush);
#ifndef __WXWINCE__
::SetMapMode(hdc, mode);
#endif
}
bool wxToolBar::HandleSize(WXWPARAM WXUNUSED(wParam), WXLPARAM lParam)
{
// calculate our minor dimension ourselves - we're confusing the standard
// logic (TB_AUTOSIZE) with our horizontal toolbars and other hacks
RECT r;
if ( ::SendMessage(GetHwnd(), TB_GETITEMRECT, 0, (LPARAM)&r) )
{
int w, h;
if ( GetWindowStyle() & wxTB_VERTICAL )
{
w = r.right - r.left;
if ( m_maxRows )
{
w *= (m_nButtons + m_maxRows - 1)/m_maxRows;
}
h = HIWORD(lParam);
}
else
{
w = LOWORD(lParam);
if (HasFlag( wxTB_FLAT ))
h = r.bottom - r.top - 3;
else
h = r.bottom - r.top;
if ( m_maxRows )
{
// FIXME: hardcoded separator line height...
h += HasFlag(wxTB_NODIVIDER) ? 4 : 6;
h *= m_maxRows;
}
}
if ( MAKELPARAM(w, h) != lParam )
{
// size really changed
SetSize(w, h);
}
// message processed
return true;
}
return false;
}
bool wxToolBar::HandlePaint(WXWPARAM wParam, WXLPARAM lParam)
{
// erase any dummy separators which we used for aligning the controls if
// any here
// first of all, do we have any controls at all?
wxToolBarToolsList::compatibility_iterator node;
for ( node = m_tools.GetFirst(); node; node = node->GetNext() )
{
if ( node->GetData()->IsControl() )
break;
}
if ( !node )
{
// no controls, nothing to erase
return false;
}
// prepare the DC on which we'll be drawing
wxClientDC dc(this);
dc.SetBrush(wxBrush(GetBackgroundColour(), wxSOLID));
dc.SetPen(*wxTRANSPARENT_PEN);
RECT r;
if ( !::GetUpdateRect(GetHwnd(), &r, FALSE) )
{
// nothing to redraw anyhow
return false;
}
wxRect rectUpdate;
wxCopyRECTToRect(r, rectUpdate);
dc.SetClippingRegion(rectUpdate);
// draw the toolbar tools, separators &c normally
wxControl::MSWWindowProc(WM_PAINT, wParam, lParam);
// for each control in the toolbar find all the separators intersecting it
// and erase them
//
// NB: this is really the only way to do it as we don't know if a separator
// corresponds to a control (i.e. is a dummy one) or a real one
// otherwise
for ( node = m_tools.GetFirst(); node; node = node->GetNext() )
{
wxToolBarToolBase *tool = node->GetData();
if ( tool->IsControl() )
{
// get the control rect in our client coords
wxControl *control = tool->GetControl();
wxRect rectCtrl = control->GetRect();
// iterate over all buttons
TBBUTTON tbb;
int count = ::SendMessage(GetHwnd(), TB_BUTTONCOUNT, 0, 0);
for ( int n = 0; n < count; n++ )
{
// is it a separator?
if ( !::SendMessage(GetHwnd(), TB_GETBUTTON,
n, (LPARAM)&tbb) )
{
wxLogDebug(_T("TB_GETBUTTON failed?"));
continue;
}
if ( tbb.fsStyle != TBSTYLE_SEP )
continue;
// get the bounding rect of the separator
RECT r;
if ( !::SendMessage(GetHwnd(), TB_GETITEMRECT,
n, (LPARAM)&r) )
{
wxLogDebug(_T("TB_GETITEMRECT failed?"));
continue;
}
// does it intersect the control?
wxRect rectItem;
wxCopyRECTToRect(r, rectItem);
if ( rectCtrl.Intersects(rectItem) )
{
// yes, do erase it!
dc.DrawRectangle(rectItem);
// Necessary in case we use a no-paint-on-size
// style in the parent: the controls can disappear
control->Refresh(false);
}
}
}
}
return true;
}
void wxToolBar::HandleMouseMove(WXWPARAM WXUNUSED(wParam), WXLPARAM lParam)
{
wxCoord x = GET_X_LPARAM(lParam),
y = GET_Y_LPARAM(lParam);
wxToolBarToolBase* tool = FindToolForPosition( x, y );
// cursor left current tool
if( tool != m_pInTool && !tool )
{
m_pInTool = 0;
OnMouseEnter( -1 );
}
// cursor entered a tool
if( tool != m_pInTool && tool )
{
m_pInTool = tool;
OnMouseEnter( tool->GetId() );
}
}
WXLRESULT wxToolBar::MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam)
{
switch ( nMsg )
{
case WM_MOUSEMOVE:
// we don't handle mouse moves, so always pass the message to
// wxControl::MSWWindowProc (HandleMouseMove just calls OnMouseEnter)
HandleMouseMove(wParam, lParam);
break;
case WM_SIZE:
if ( HandleSize(wParam, lParam) )
return 0;
break;
#ifndef __WXWINCE__
case WM_PAINT:
if ( HandlePaint(wParam, lParam) )
return 0;
#endif
}
return wxControl::MSWWindowProc(nMsg, wParam, lParam);
}
// ----------------------------------------------------------------------------
// private functions
// ----------------------------------------------------------------------------
WXHBITMAP wxToolBar::MapBitmap(WXHBITMAP bitmap, int width, int height)
{
MemoryHDC hdcMem;
if ( !hdcMem )
{
wxLogLastError(_T("CreateCompatibleDC"));
return bitmap;
}
SelectInHDC bmpInHDC(hdcMem, (HBITMAP)bitmap);
if ( !bmpInHDC )
{
wxLogLastError(_T("SelectObject"));
return bitmap;
}
wxCOLORMAP *cmap = wxGetStdColourMap();
for ( int i = 0; i < width; i++ )
{
for ( int j = 0; j < height; j++ )
{
COLORREF pixel = ::GetPixel(hdcMem, i, j);
for ( size_t k = 0; k < wxSTD_COL_MAX; k++ )
{
COLORREF col = cmap[k].from;
if ( abs(GetRValue(pixel) - GetRValue(col)) < 10 &&
abs(GetGValue(pixel) - GetGValue(col)) < 10 &&
abs(GetBValue(pixel) - GetBValue(col)) < 10 )
{
::SetPixel(hdcMem, i, j, cmap[k].to);
break;
}
}
}
}
return bitmap;
// VZ: I leave here my attempts to map the bitmap to the system colours
// faster by using BitBlt() even though it's broken currently - but
// maybe someone else can finish it? It should be faster than iterating
// over all pixels...
#if 0
MemoryHDC hdcMask, hdcDst;
if ( !hdcMask || !hdcDst )
{
wxLogLastError(_T("CreateCompatibleDC"));
return bitmap;
}
// create the target bitmap
HBITMAP hbmpDst = ::CreateCompatibleBitmap(hdcDst, width, height);
if ( !hbmpDst )
{
wxLogLastError(_T("CreateCompatibleBitmap"));
return bitmap;
}
// create the monochrome mask bitmap
HBITMAP hbmpMask = ::CreateBitmap(width, height, 1, 1, 0);
if ( !hbmpMask )
{
wxLogLastError(_T("CreateBitmap(mono)"));
::DeleteObject(hbmpDst);
return bitmap;
}
SelectInHDC bmpInDst(hdcDst, hbmpDst),
bmpInMask(hdcMask, hbmpMask);
// for each colour:
for ( n = 0; n < NUM_OF_MAPPED_COLOURS; n++ )
{
// create the mask for this colour
::SetBkColor(hdcMem, ColorMap[n].from);
::BitBlt(hdcMask, 0, 0, width, height, hdcMem, 0, 0, SRCCOPY);
// replace this colour with the target one in the dst bitmap
HBRUSH hbr = ::CreateSolidBrush(ColorMap[n].to);
HGDIOBJ hbrOld = ::SelectObject(hdcDst, hbr);
::MaskBlt(hdcDst, 0, 0, width, height,
hdcMem, 0, 0,
hbmpMask, 0, 0,
MAKEROP4(PATCOPY, SRCCOPY));
(void)::SelectObject(hdcDst, hbrOld);
::DeleteObject(hbr);
}
::DeleteObject((HBITMAP)bitmap);
return (WXHBITMAP)hbmpDst;
#endif // 0
}
#endif // wxUSE_TOOLBAR && Win95
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?