namespace phoenix { static LRESULT CALLBACK TabFrame_windowProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) { Object* object = (Object*)GetWindowLongPtr(hwnd, GWLP_USERDATA); if(object == nullptr) return DefWindowProc(hwnd, msg, wparam, lparam); TabFrame& tabFrame = (TabFrame&)*object; return Shared_windowProc(tabFrame.p.windowProc, hwnd, msg, wparam, lparam); } void pTabFrame::append(string text, const image& image) { unsigned selection = TabCtrl_GetItemCount(hwnd); wchar_t wtext[] = L""; TCITEM item; item.mask = TCIF_TEXT; item.pszText = wtext; TabCtrl_InsertItem(hwnd, selection, &item); setText(selection, text); if(!image.empty()) setImage(selection, image); } void pTabFrame::remove(unsigned selection) { TabCtrl_DeleteItem(hwnd, selection); buildImageList(); } void pTabFrame::setEnabled(bool enabled) { pWidget::setEnabled(enabled); for(auto& layout : tabFrame.state.layout) { if(layout) layout->setEnabled(layout->enabled()); } } void pTabFrame::setGeometry(Geometry geometry) { pWidget::setGeometry(geometry); geometry.x += 1, geometry.width -= 4; geometry.y += 21, geometry.height -= 23; for(auto& layout : tabFrame.state.layout) { if(layout) layout->setGeometry(geometry); } } void pTabFrame::setImage(unsigned selection, const image& image) { buildImageList(); } void pTabFrame::setSelection(unsigned selection) { TabCtrl_SetCurSel(hwnd, selection); synchronizeLayout(); } void pTabFrame::setText(unsigned selection, string text) { utf16_t wtext(text); TCITEM item; item.mask = TCIF_TEXT; item.pszText = (wchar_t*)wtext; TabCtrl_SetItem(hwnd, selection, &item); } void pTabFrame::setVisible(bool visible) { pWidget::setVisible(visible); for(auto& layout : tabFrame.state.layout) { if(layout) layout->setVisible(layout->visible()); } } void pTabFrame::constructor() { hwnd = CreateWindow(WC_TABCONTROL, L"", WS_CHILD | WS_TABSTOP, 0, 0, 0, 0, parentHwnd, (HMENU)id, GetModuleHandle(0), 0); SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)&tabFrame); windowProc = (WindowProc)GetWindowLongPtr(hwnd, GWLP_WNDPROC); SetWindowLongPtr(hwnd, GWLP_WNDPROC, (LONG_PTR)TabFrame_windowProc); setDefaultFont(); for(auto& text : tabFrame.state.text) append(text, {}); buildImageList(); setSelection(tabFrame.state.selection); synchronize(); } void pTabFrame::destructor() { if(imageList) { ImageList_Destroy(imageList); imageList = nullptr; } DestroyWindow(hwnd); } void pTabFrame::orphan() { destructor(); constructor(); } void pTabFrame::buildImageList() { if(imageList) ImageList_Destroy(imageList); unsigned size = pFont::size(hfont, " ").height; imageList = ImageList_Create(size, size, ILC_COLOR32, 1, 0); for(auto& image : tabFrame.state.image) { ImageList_Append(imageList, image, size); } TabCtrl_SetImageList(hwnd, imageList); for(unsigned n = 0; n < tabFrame.state.image.size(); n++) { TCITEM item; item.mask = TCIF_IMAGE; item.iImage = (tabFrame.state.image(n).empty() ? -1 : n); TabCtrl_SetItem(hwnd, n, &item); } } void pTabFrame::synchronizeLayout() { unsigned selection = 0; for(auto& layout : tabFrame.state.layout) { if(layout) layout->setVisible(selection == tabFrame.state.selection); selection++; } } void pTabFrame::onChange() { tabFrame.state.selection = TabCtrl_GetCurSel(hwnd); synchronizeLayout(); if(tabFrame.onChange) tabFrame.onChange(); } //called only if TCS_OWNERDRAWFIXED style is used //this style disables XP/Vista theming of the TabFrame void pTabFrame::onDrawItem(LPARAM lparam) { LPDRAWITEMSTRUCT item = (LPDRAWITEMSTRUCT)lparam; FillRect(item->hDC, &item->rcItem, GetSysColorBrush(COLOR_3DFACE)); SetBkMode(item->hDC, TRANSPARENT); SetTextColor(item->hDC, GetSysColor(COLOR_BTNTEXT)); unsigned selection = item->itemID; if(selection < tabFrame.state.text.size()) { string text = tabFrame.state.text[selection]; Size size = pFont::size(hfont, text); unsigned width = item->rcItem.right - item->rcItem.left + 1; if(!tabFrame.state.image[selection].empty()) { width += size.height + 2; ImageList_Draw(imageList, selection, item->hDC, item->rcItem.left + (width - size.width) / 2 - (size.height + 3), item->rcItem.top + 2, ILD_NORMAL); } TextOut(item->hDC, item->rcItem.left + (width - size.width) / 2, item->rcItem.top + 2, utf16_t(text), text.size()); } } }