notebook.cpp
来自「A*算法 A*算法 A*算法 A*算法A*算法A*算法」· C++ 代码 · 共 1,389 行 · 第 1/3 页
CPP
1,389 行
TC_ITEM tcItem;
tcItem.mask = TCIF_TEXT;
tcItem.pszText = (wxChar *)strText.c_str();
if ( !HasFlag(wxNB_MULTILINE) )
return TabCtrl_SetItem(GetHwnd(), nPage, &tcItem) != 0;
// multiline - we need to set new page size if a line is added or removed
int rows = GetRowCount();
bool ret = TabCtrl_SetItem(GetHwnd(), nPage, &tcItem) != 0;
if ( ret && rows != GetRowCount() )
{
const wxRect r = GetPageSize();
const size_t count = m_pages.Count();
for ( size_t page = 0; page < count; page++ )
m_pages[page]->SetSize(r);
}
return ret;
}
wxString wxNotebook::GetPageText(size_t nPage) const
{
wxCHECK_MSG( IS_VALID_PAGE(nPage), wxEmptyString, wxT("notebook page out of range") );
wxChar buf[256];
TC_ITEM tcItem;
tcItem.mask = TCIF_TEXT;
tcItem.pszText = buf;
tcItem.cchTextMax = WXSIZEOF(buf);
wxString str;
if ( TabCtrl_GetItem(GetHwnd(), nPage, &tcItem) )
str = tcItem.pszText;
return str;
}
int wxNotebook::GetPageImage(size_t nPage) const
{
wxCHECK_MSG( IS_VALID_PAGE(nPage), -1, wxT("notebook page out of range") );
TC_ITEM tcItem;
tcItem.mask = TCIF_IMAGE;
return TabCtrl_GetItem(GetHwnd(), nPage, &tcItem) ? tcItem.iImage : -1;
}
bool wxNotebook::SetPageImage(size_t nPage, int nImage)
{
wxCHECK_MSG( IS_VALID_PAGE(nPage), false, wxT("notebook page out of range") );
TC_ITEM tcItem;
tcItem.mask = TCIF_IMAGE;
tcItem.iImage = nImage;
return TabCtrl_SetItem(GetHwnd(), nPage, &tcItem) != 0;
}
void wxNotebook::SetImageList(wxImageList* imageList)
{
wxNotebookBase::SetImageList(imageList);
if ( imageList )
{
(void) TabCtrl_SetImageList(GetHwnd(), (HIMAGELIST)imageList->GetHIMAGELIST());
}
}
// ----------------------------------------------------------------------------
// wxNotebook size settings
// ----------------------------------------------------------------------------
wxRect wxNotebook::GetPageSize() const
{
wxRect r;
RECT rc;
::GetClientRect(GetHwnd(), &rc);
// This check is to work around a bug in TabCtrl_AdjustRect which will
// cause a crash on win2k or on XP with themes disabled if either
// wxNB_MULTILINE is used or tabs are placed on a side, if the rectangle
// is too small.
//
// The value of 20 is chosen arbitrarily but seems to work
if ( rc.right > 20 && rc.bottom > 20 )
{
TabCtrl_AdjustRect(GetHwnd(), false, &rc);
wxCopyRECTToRect(rc, r);
}
return r;
}
void wxNotebook::SetPageSize(const wxSize& size)
{
// transform the page size into the notebook size
RECT rc;
rc.left =
rc.top = 0;
rc.right = size.x;
rc.bottom = size.y;
TabCtrl_AdjustRect(GetHwnd(), true, &rc);
// and now set it
SetSize(rc.right - rc.left, rc.bottom - rc.top);
}
void wxNotebook::SetPadding(const wxSize& padding)
{
TabCtrl_SetPadding(GetHwnd(), padding.x, padding.y);
}
// Windows-only at present. Also, you must use the wxNB_FIXEDWIDTH
// style.
void wxNotebook::SetTabSize(const wxSize& sz)
{
::SendMessage(GetHwnd(), TCM_SETITEMSIZE, 0, MAKELPARAM(sz.x, sz.y));
}
wxSize wxNotebook::CalcSizeFromPage(const wxSize& sizePage) const
{
wxSize sizeTotal = sizePage;
// We need to make getting tab size part of the wxWidgets API.
wxSize tabSize;
if (GetPageCount() > 0)
{
RECT rect;
TabCtrl_GetItemRect((HWND) GetHWND(), 0, & rect);
tabSize.x = rect.right - rect.left;
tabSize.y = rect.bottom - rect.top;
}
if ( HasFlag(wxNB_LEFT) || HasFlag(wxNB_RIGHT) )
{
sizeTotal.x += tabSize.x + 7;
sizeTotal.y += 7;
}
else
{
sizeTotal.x += 7;
sizeTotal.y += tabSize.y + 7;
}
return sizeTotal;
}
void wxNotebook::AdjustPageSize(wxNotebookPage *page)
{
wxCHECK_RET( page, _T("NULL page in wxNotebook::AdjustPageSize") );
const wxRect r = GetPageSize();
if ( !r.IsEmpty() )
{
page->SetSize(r);
}
}
// ----------------------------------------------------------------------------
// wxNotebook operations
// ----------------------------------------------------------------------------
// remove one page from the notebook, without deleting
wxNotebookPage *wxNotebook::DoRemovePage(size_t nPage)
{
wxNotebookPage *pageRemoved = wxNotebookBase::DoRemovePage(nPage);
if ( !pageRemoved )
return NULL;
TabCtrl_DeleteItem(GetHwnd(), nPage);
if ( m_pages.IsEmpty() )
{
// no selection any more, the notebook becamse empty
m_nSelection = -1;
}
else // notebook still not empty
{
int selNew = TabCtrl_GetCurSel(GetHwnd());
if (selNew != -1)
{
// No selection change, just refresh the current selection.
// Because it could be that the slection index changed
// we need to update it.
// Note: this does not mean the selection it self changed.
m_nSelection = selNew;
m_pages[m_nSelection]->Refresh();
}
else if (int(nPage) == m_nSelection)
{
// The selection was deleted.
// Determine new selection.
if (m_nSelection == int(GetPageCount()))
selNew = m_nSelection - 1;
else
selNew = m_nSelection;
// m_nSelection must be always valid so reset it before calling
// SetSelection()
m_nSelection = -1;
SetSelection(selNew);
}
else
{
wxFAIL; // Windows did not behave ok.
}
}
return pageRemoved;
}
// remove all pages
bool wxNotebook::DeleteAllPages()
{
size_t nPageCount = GetPageCount();
size_t nPage;
for ( nPage = 0; nPage < nPageCount; nPage++ )
delete m_pages[nPage];
m_pages.Clear();
TabCtrl_DeleteAllItems(GetHwnd());
m_nSelection = -1;
InvalidateBestSize();
return true;
}
// same as AddPage() but does it at given position
bool wxNotebook::InsertPage(size_t nPage,
wxNotebookPage *pPage,
const wxString& strText,
bool bSelect,
int imageId)
{
wxCHECK_MSG( pPage != NULL, false, _T("NULL page in wxNotebook::InsertPage") );
wxCHECK_MSG( IS_VALID_PAGE(nPage) || nPage == GetPageCount(), false,
_T("invalid index in wxNotebook::InsertPage") );
wxASSERT_MSG( pPage->GetParent() == this,
_T("notebook pages must have notebook as parent") );
// add a new tab to the control
// ----------------------------
// init all fields to 0
TC_ITEM tcItem;
wxZeroMemory(tcItem);
// set the image, if any
if ( imageId != -1 )
{
tcItem.mask |= TCIF_IMAGE;
tcItem.iImage = imageId;
}
// and the text
if ( !strText.empty() )
{
tcItem.mask |= TCIF_TEXT;
tcItem.pszText = (wxChar *)strText.c_str(); // const_cast
}
// hide the page: unless it is selected, it shouldn't be shown (and if it
// is selected it will be shown later)
HWND hwnd = GetWinHwnd(pPage);
SetWindowLong(hwnd, GWL_STYLE, GetWindowLong(hwnd, GWL_STYLE) & ~WS_VISIBLE);
// this updates internal flag too -- otherwise it would get out of sync
// with the real state
pPage->Show(false);
// fit the notebook page to the tab control's display area: this should be
// done before adding it to the notebook or TabCtrl_InsertItem() will
// change the notebooks size itself!
AdjustPageSize(pPage);
// finally do insert it
if ( TabCtrl_InsertItem(GetHwnd(), nPage, &tcItem) == -1 )
{
wxLogError(wxT("Can't create the notebook page '%s'."), strText.c_str());
return false;
}
// succeeded: save the pointer to the page
m_pages.Insert(pPage, nPage);
// we may need to adjust the size again if the notebook size changed:
// normally this only happens for the first page we add (the tabs which
// hadn't been there before are now shown) but for a multiline notebook it
// can happen for any page at all as a new row could have been started
if ( m_pages.GetCount() == 1 || HasFlag(wxNB_MULTILINE) )
{
AdjustPageSize(pPage);
}
// now deal with the selection
// ---------------------------
// if the inserted page is before the selected one, we must update the
// index of the selected page
if ( int(nPage) <= m_nSelection )
{
// one extra page added
m_nSelection++;
}
// some page should be selected: either this one or the first one if there
// is still no selection
int selNew = -1;
if ( bSelect )
selNew = nPage;
else if ( m_nSelection == -1 )
selNew = 0;
if ( selNew != -1 )
SetSelection(selNew);
InvalidateBestSize();
return true;
}
int wxNotebook::HitTest(const wxPoint& pt, long *flags) const
{
TC_HITTESTINFO hitTestInfo;
hitTestInfo.pt.x = pt.x;
hitTestInfo.pt.y = pt.y;
int item = TabCtrl_HitTest(GetHwnd(), &hitTestInfo);
if ( flags )
{
*flags = 0;
if ((hitTestInfo.flags & TCHT_NOWHERE) == TCHT_NOWHERE)
*flags |= wxNB_HITTEST_NOWHERE;
if ((hitTestInfo.flags & TCHT_ONITEM) == TCHT_ONITEM)
*flags |= wxNB_HITTEST_ONITEM;
if ((hitTestInfo.flags & TCHT_ONITEMICON) == TCHT_ONITEMICON)
*flags |= wxNB_HITTEST_ONICON;
if ((hitTestInfo.flags & TCHT_ONITEMLABEL) == TCHT_ONITEMLABEL)
*flags |= wxNB_HITTEST_ONLABEL;
}
return item;
}
// ----------------------------------------------------------------------------
// flicker-less notebook redraw
// ----------------------------------------------------------------------------
#if USE_NOTEBOOK_ANTIFLICKER
// wnd proc for the spin button
LRESULT APIENTRY _EXPORT wxNotebookSpinBtnWndProc(HWND hwnd,
UINT message,
WPARAM wParam,
LPARAM lParam)
{
if ( message == WM_ERASEBKGND )
return 0;
return ::CallWindowProc(CASTWNDPROC gs_wndprocNotebookSpinBtn,
hwnd, message, wParam, lParam);
}
LRESULT APIENTRY _EXPORT wxNotebookWndProc(HWND hwnd,
UINT message,
WPARAM wParam,
LPARAM lParam)
{
return ::CallWindowProc(CASTWNDPROC gs_wndprocNotebook,
hwnd, message, wParam, lParam);
}
void wxNotebook::OnEraseBackground(wxEraseEvent& WXUNUSED(event))
{
// do nothing here
}
void wxNotebook::OnPaint(wxPaintEvent& WXUNUSED(event))
{
wxPaintDC dc(this);
wxMemoryDC memdc;
RECT rc;
::GetClientRect(GetHwnd(), &rc);
wxBitmap bmp(rc.right, rc.bottom);
memdc.SelectObject(bmp);
// if there is no special brush just use the solid background colour
#if wxUSE_UXTHEME
HBRUSH hbr = (HBRUSH)m_hbrBackground;
#else
HBRUSH hbr = 0;
#endif
wxBrush brush;
if ( !hbr )
{
brush = wxBrush(GetBackgroundColour());
hbr = GetHbrushOf(brush);
}
::FillRect(GetHdcOf(memdc), &rc, hbr);
MSWDefWindowProc(WM_PAINT, (WPARAM)memdc.GetHDC(), 0);
dc.Blit(0, 0, rc.right, rc.bottom, &memdc, 0, 0);
}
#endif // USE_NOTEBOOK_ANTIFLICKER
// ----------------------------------------------------------------------------
// wxNotebook callbacks
// ----------------------------------------------------------------------------
void wxNotebook::OnSize(wxSizeEvent& event)
{
if ( GetPageCount() == 0 )
{
// Prevents droppings on resize, but does cause some flicker
// when there are no pages.
Refresh();
event.Skip();
return;
}
#ifndef __WXWINCE__
else
{
// Without this, we can sometimes get droppings at the edges
// of a notebook, for example a notebook in a splitter window.
// This needs to be reconciled with the RefreshRect calls
// at the end of this function, which weren't enough to prevent
// the droppings.
wxSize sz = GetClientSize();
// Refresh right side
wxRect rect(sz.x-4, 0, 4, sz.y);
RefreshRect(rect);
// Refresh bottom side
rect = wxRect(0, sz.y-4, sz.x, 4);
RefreshRect(rect);
// Refresh left side
rect = wxRect(0, 0, 4, sz.y);
RefreshRect(rect);
}
#endif // !__WXWINCE__
// fit all the notebook pages to the tab control's display area
RECT rc;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?