📄 dockingcont.cpp.svn-base
字号:
return TRUE;
}
case WM_MOUSEMOVE:
{
if ((_beginDrag == TRUE) && (wParam == MK_LBUTTON))
{
int iItem = 0;
TCHITTESTINFO info = {0};
/* get selected sub item */
info.pt.x = LOWORD(lParam);
info.pt.y = HIWORD(lParam);
iItem = ::SendMessage(hwnd, TCM_HITTEST, 0, (LPARAM)&info);
SelectTab(iItem);
/* send moving message to parent window */
_dragFromTab = TRUE;
NotifyParent(DMM_MOVE);
_beginDrag = FALSE;
}
else
{
_beginDrag = FALSE;
}
return TRUE;
}
case WM_NOTIFY:
{
LPNMHDR lpnmhdr = (LPNMHDR)lParam;
if ((lpnmhdr->hwndFrom == _hContTab) && (lpnmhdr->code == TCN_GETOBJECT))
{
int iItem = 0;
TCHITTESTINFO info = {0};
/* get selected sub item */
info.pt.x = LOWORD(lParam);
info.pt.y = HIWORD(lParam);
iItem = ::SendMessage(hwnd, TCM_HITTEST, 0, (LPARAM)&info);
SelectTab(iItem);
}
break;
}
default:
break;
}
return ::CallWindowProc(_hDefaultTabProc, hwnd, Message, wParam, lParam);
}
void DockingCont::drawTabItem(DRAWITEMSTRUCT *pDrawItemStruct)
{
TCITEM tcItem = {0};
RECT rc = pDrawItemStruct->rcItem;
int nTab = pDrawItemStruct->itemID;
bool isSelected = (nTab == getActiveTb());
/* get current selected item */
tcItem.mask = TCIF_PARAM;
::SendMessage(_hContTab, TCM_GETITEM, nTab, (LPARAM)&tcItem);
char* text = ((tTbData*)tcItem.lParam)->pszName;
int length = strlen(((tTbData*)tcItem.lParam)->pszName);
/* get drawing context */
HDC hDc = pDrawItemStruct->hDC;
int nSavedDC = ::SaveDC(hDc);
// For some bizarre reason the rcItem you get extends above the actual
// drawing area. We have to workaround this "feature".
rc.top += ::GetSystemMetrics(SM_CYEDGE);
::SetBkMode(hDc, TRANSPARENT);
HBRUSH hBrush = ::CreateSolidBrush(::GetSysColor(COLOR_BTNFACE));
::FillRect(hDc, &rc, hBrush);
::DeleteObject((HGDIOBJ)hBrush);
/* draw orange bar */
if (isSelected == true)
{
RECT barRect = rc;
barRect.top += rc.bottom - 4;
hBrush = ::CreateSolidBrush(RGB(250, 170, 60));
::FillRect(hDc, &barRect, hBrush);
::DeleteObject((HGDIOBJ)hBrush);
}
/* draw icon if enabled */
if (((tTbData*)tcItem.lParam)->uMask & DWS_ICONTAB)
{
HIMAGELIST hImageList = (HIMAGELIST)::SendMessage(_hParent, DMM_GETIMAGELIST, 0, 0);
int iPosImage = ::SendMessage(_hParent, DMM_GETICONPOS, 0, (LPARAM)((tTbData*)tcItem.lParam)->hClient);
if ((hImageList != NULL) && (iPosImage >= 0))
{
/* Get height of image so we */
SIZE size = {0};
IMAGEINFO info = {0};
RECT & imageRect = info.rcImage;
ImageList_GetImageInfo(hImageList, iPosImage, &info);
/* calculate position of rect */
::GetTextExtentPoint(hDc, text, length, &size);
rc.left += ((rc.right - rc.left) - (imageRect.right - imageRect.left) - size.cx - 2) / 2;
ImageList_Draw(hImageList, iPosImage, hDc, rc.left, ((isSelected == true)?2:3), ILD_NORMAL);
rc.left += imageRect.right - imageRect.left - ((isSelected == true)?3:0);
}
}
COLORREF _unselectedColor = RGB(0, 0, 0);
::SetTextColor(hDc, _unselectedColor);
/* draw text */
rc.top -= ::GetSystemMetrics(SM_CYEDGE);
::SelectObject(hDc, _hFont);
::DrawText(hDc, text, length, &rc, DT_SINGLELINE|DT_VCENTER|DT_CENTER);
::RestoreDC(hDc, nSavedDC);
}
/*********************************************************************************
* Process function of dialog
*/
BOOL CALLBACK DockingCont::run_dlgProc(UINT Message, WPARAM wParam, LPARAM lParam)
{
switch (Message)
{
case WM_NCACTIVATE:
{
/* Note: lParam to identify the trigger window */
if ((int)lParam != -1)
{
::SendMessage(_hParent, WM_NCACTIVATE, wParam, 0);
}
break;
}
case WM_INITDIALOG:
{
_hContTab = ::GetDlgItem(_hSelf, IDC_TAB_CONT);
_hCaption = ::GetDlgItem(_hSelf, IDC_BTN_CAPTION);
/* intial subclassing of caption */
::SetWindowLong(_hCaption, GWL_USERDATA, reinterpret_cast<LONG>(this));
_hDefaultCaptionProc = reinterpret_cast<WNDPROC>(::SetWindowLong(_hCaption, GWL_WNDPROC, reinterpret_cast<LONG>(wndCaptionProc)));
/* intial subclassing of tab */
::SetWindowLong(_hContTab, GWL_USERDATA, reinterpret_cast<LONG>(this));
_hDefaultTabProc = reinterpret_cast<WNDPROC>(::SetWindowLong(_hContTab, GWL_WNDPROC, reinterpret_cast<LONG>(wndTabProc)));
break;
}
case WM_NCCALCSIZE:
case WM_SIZE:
{
onSize();
break;
}
case WM_DRAWITEM :
{
/* draw tab or caption */
if (((DRAWITEMSTRUCT *)lParam)->CtlID == IDC_TAB_CONT)
{
drawTabItem((DRAWITEMSTRUCT *)lParam);
return TRUE;
}
else
{
drawCaptionItem((DRAWITEMSTRUCT *)lParam);
return TRUE;
}
break;
}
case WM_NCLBUTTONDBLCLK :
{
RECT rcWnd = {0};
RECT rcClient = {0};
POINT pt = {HIWORD(lParam), LOWORD(lParam)};
getWindowRect(rcWnd);
getClientRect(rcClient);
ClientToScreen(_hSelf, &rcClient);
rcWnd.bottom = rcClient.top;
/* if in caption */
if ((rcWnd.top < pt.x) && (rcWnd.bottom > pt.x) &&
(rcWnd.left < pt.y) && (rcWnd.right > pt.y))
{
NotifyParent(DMM_DOCKALL);
return TRUE;
}
break;
}
case WM_SYSCOMMAND :
{
switch (wParam & 0xfff0)
{
case SC_MOVE:
NotifyParent(DMM_MOVE);
return TRUE;
default:
break;
}
return FALSE;
}
case WM_COMMAND :
{
switch (LOWORD(wParam))
{
case IDCANCEL:
doClose();
return TRUE;
default :
break;
}
break;
}
default:
break;
}
return FALSE;
}
void DockingCont::onSize(void)
{
TCITEM tcItem = {0};
RECT rc = {0};
RECT rcTemp = {0};
UINT iItemCnt = ::SendMessage(_hContTab, TCM_GETITEMCOUNT, 0, 0);
getClientRect(rc);
if (iItemCnt >= 1)
{
/* resize to docked window */
if (_isFloating == false)
{
/* draw caption */
if (_isTopCaption == TRUE)
{
::SetWindowPos(_hCaption, NULL, rc.left, rc.top, rc.right, 16, SWP_NOZORDER | SWP_NOACTIVATE);
rc.top += 16;
rc.bottom -= 16;
}
else
{
::SetWindowPos(_hCaption, NULL, rc.left, rc.top, 16, rc.bottom, SWP_NOZORDER | SWP_NOACTIVATE);
rc.left += 16;
rc.right -= 16;
}
if (iItemCnt >= 2)
{
/* resize tab and plugin control if tabs exceeds one */
/* resize tab */
rcTemp = rc;
rcTemp.top = (rcTemp.bottom + rcTemp.top) - 22;
rcTemp.bottom = 20;
::SetWindowPos(_hContTab, NULL,
rcTemp.left, rcTemp.top, rcTemp.right, rcTemp.bottom,
SWP_NOZORDER | SWP_SHOWWINDOW | SWP_NOACTIVATE);
/* resize client area for plugin */
rcTemp = rc;
rcTemp.top += 2;
rcTemp.bottom -= 22;
}
else
{
/* resize client area for plugin */
rcTemp = rc;
rcTemp.top += 2;
rcTemp.bottom -= 2;
}
/* set position of client area */
::SetWindowPos(::GetDlgItem(_hSelf, IDC_CLIENT_TAB), NULL,
rcTemp.left, rcTemp.top, rcTemp.right, rcTemp.bottom,
SWP_NOZORDER | SWP_NOACTIVATE);
}
/* resize to float window */
else
{
/* update floating size */
if (_isFloating == true)
{
for (size_t iTb = 0; iTb < _vTbData.size(); iTb++)
{
getWindowRect(_vTbData[iTb]->rcFloat);
}
}
/* draw caption */
if (iItemCnt >= 2)
{
/* resize tab if size of elements exceeds one */
rcTemp = rc;
rcTemp.top = rcTemp.bottom - 22;
rcTemp.bottom = 20;
::SetWindowPos(_hContTab, NULL,
rcTemp.left, rcTemp.top, rcTemp.right, rcTemp.bottom,
SWP_NOZORDER | SWP_SHOWWINDOW);
}
/* resize client area for plugin */
rcTemp = rc;
rcTemp.bottom -= ((iItemCnt == 1)?0:20);
::SetWindowPos(::GetDlgItem(_hSelf, IDC_CLIENT_TAB), NULL,
rcTemp.left, rcTemp.top, rcTemp.right, rcTemp.bottom,
SWP_NOZORDER | SWP_NOACTIVATE);
}
/* get active item data */
UINT iItemCnt = ::SendMessage(_hContTab, TCM_GETITEMCOUNT, 0, 0);
/* resize visible plugin windows */
for (UINT iItem = 0; iItem < iItemCnt; iItem++)
{
tcItem.mask = TCIF_PARAM;
::SendMessage(_hContTab, TCM_GETITEM, iItem, (LPARAM)&tcItem);
::SetWindowPos(((tTbData*)tcItem.lParam)->hClient, NULL,
0, 0, rcTemp.right, rcTemp.bottom,
SWP_NOZORDER);
}
}
}
void DockingCont::doClose(void)
{
INT iItemOff = 0;
INT iItemCnt = ::SendMessage(_hContTab, TCM_GETITEMCOUNT, 0, 0);
for (INT iItem = 0; iItem < iItemCnt; iItem++)
{
TCITEM tcItem = {0};
/* get item data */
SelectTab(iItemOff);
tcItem.mask = TCIF_PARAM;
::SendMessage(_hContTab, TCM_GETITEM, iItemOff, (LPARAM)&tcItem);
/* notify child windows */
if (NotifyParent(DMM_CLOSE) == 0)
{
/* delete tab */
hideToolbar((tTbData*)tcItem.lParam);
}
else
{
iItemOff++;
}
}
if (iItemOff == 0)
{
/* hide dialog first */
this->doDialog(false);
::SendMessage(_hParent, WM_SIZE, 0, 0);
}
}
void DockingCont::showToolbar(tTbData* pTbData, BOOL state)
{
if (state == SW_SHOW)
{
viewToolbar(pTbData);
}
else
{
hideToolbar(pTbData);
}
}
int DockingCont::hideToolbar(tTbData *pTbData)
{
int iItem = SearchPosInTab(pTbData);
/* delete item */
if (TRUE == ::SendMessage(_hContTab, TCM_DELETEITEM, iItem, 0))
{
UINT iItemCnt = ::SendMessage(_hContTab, TCM_GETITEMCOUNT, 0, 0);
if (iItemCnt != 0)
{
TCITEM tcItem = {0};
tcItem.mask = TCIF_PARAM;
if (iItem == iItemCnt)
{
iItem--;
}
/* activate new selected item and view plugin dialog */
_prevItem = iItem;
SelectTab(iItem);
/* hide tabs if only one element */
if (iItemCnt == 1)
{
::ShowWindow(_hContTab, SW_HIDE);
}
}
else
{
/* hide dialog */
this->doDialog(false);
/* send message to docking manager for resize */
if (_isFloating == false)
{
::SendMessage(_hParent, WM_SIZE, 0, 0);
}
}
/* keep sure, that client is hide!!! */
::ShowWindow(pTbData->hClient, SW_HIDE);
}
onSize();
return iItem;
}
void DockingCont::viewToolbar(tTbData *pTbData)
{
TCITEM tcItem = {0};
int iItemCnt = ::SendMessage(_hContTab, TCM_GETITEMCOUNT, 0, 0);
if (iItemCnt > 0)
{
UINT iItem = getActiveTb();
tcItem.mask = TCIF_PARAM;
::SendMessage(_hContTab, TCM_GETITEM, iItem, (LPARAM)&tcItem);
/* hide active dialog */
::ShowWindow(((tTbData*)tcItem.lParam)->hClient, SW_HIDE);
}
/* create new tab if it not exist */
int iTabPos = SearchPosInTab(pTbData);
if (iTabPos == -1)
{
/* set only params and text even if icon available */
tcItem.mask = TCIF_PARAM | TCIF_TEXT;
tcItem.lParam = (LPARAM)pTbData;
if (pTbData->uMask & DWS_ICONTAB)
{
/* fake here a icon before the text ... */
char szText[64];
strcpy(szText, " ");
strcat(szText, pTbData->pszName);
tcItem.pszText = szText;
tcItem.cchTextMax = strlen(szText);
}
else
{
/* ... but here put text normal into the tab */
tcItem.pszText = pTbData->pszName;
tcItem.cchTextMax = strlen(pTbData->pszName);
}
::SendMessage(_hContTab, TCM_INSERTITEM, iItemCnt, (LPARAM)&tcItem);
SelectTab(iItemCnt);
}
/* if exists select it and update data */
else
{
tcItem.mask = TCIF_PARAM;
tcItem.lParam = (LPARAM)pTbData;
::SendMessage(_hContTab, TCM_SETITEM, iTabPos, (LPARAM)&tcItem);
SelectTab(iTabPos);
}
/* show dialog and notify parent to update dialog view */
if (isVisible() == false)
{
this->doDialog();
::SendMessage(_hParent, WM_SIZE, 0, 0);
}
/* set position of client */
onSize();
}
int DockingCont::SearchPosInTab(tTbData* pTbData)
{
TCITEM tcItem = {0};
int iItemCnt = ::SendMessage(_hContTab, TCM_GETITEMCOUNT, 0, 0);
int ret = -1;
tcItem.mask = TCIF_PARAM;
for (int iItem = 0; iItem < iItemCnt; iItem++)
{
::SendMessage(_hContTab, TCM_GETITEM, iItem, (LPARAM)&tcItem);
if (((tTbData*)tcItem.lParam)->hClient == pTbData->hClient)
{
ret = iItem;
break;
}
}
return ret;
}
void DockingCont::SelectTab(int iItem)
{
if (iItem != -1)
{
TCITEM tcItem = {0};
/* get data of new active dialog */
tcItem.mask = TCIF_PARAM;
::SendMessage(_hContTab, TCM_GETITEM, iItem, (LPARAM)&tcItem);
/* show active dialog */
::ShowWindow(((tTbData*)tcItem.lParam)->hClient, SW_SHOW);
::SetFocus(((tTbData*)tcItem.lParam)->hClient);
if (iItem != _prevItem)
{
/* hide previous dialog */
::SendMessage(_hContTab, TCM_GETITEM, _prevItem, (LPARAM)&tcItem);
::ShowWindow(((tTbData*)tcItem.lParam)->hClient, SW_HIDE);
}
/* selects the pressed tab and store previous tab */
::SendMessage(_hContTab, TCM_SETCURSEL, iItem, 0);
_prevItem = iItem;
/* update caption text */
updateCaption();
onSize();
}
}
void DockingCont::updateCaption(void)
{
TCITEM tcItem = {0};
int iItem = 0;
/* get active tab */
iItem = getActiveTb();
/* get data of new active dialog */
tcItem.mask = TCIF_PARAM;
::SendMessage(_hContTab, TCM_GETITEM, iItem, (LPARAM)&tcItem);
/* update caption text */
strcpy(_pszCaption, ((tTbData*)tcItem.lParam)->pszName);
/* test if additional information are available */
if ((((tTbData*)tcItem.lParam)->uMask & DWS_ADDINFO) &&
(strlen(((tTbData*)tcItem.lParam)->pszAddInfo) != 0))
{
strcat(_pszCaption, " - ");
strcat(_pszCaption, ((tTbData*)tcItem.lParam)->pszAddInfo);
}
if (_isFloating == true)
{
::SetWindowText(_hSelf, _pszCaption);
}
else
{
::SetWindowText(_hCaption, _pszCaption);
}
}
void DockingCont::focusClient(void)
{
TCITEM tcItem = {0};
int iItem = getActiveTb();
if (iItem != -1)
{
/* get data of new active dialog */
tcItem.mask = TCIF_PARAM;
::SendMessage(_hContTab, TCM_GETITEM, iItem, (LPARAM)&tcItem);
/* set focus */
::SetFocus(((tTbData*)tcItem.lParam)->hClient);
}
}
LPARAM DockingCont::NotifyParent(UINT message)
{
return ::SendMessage(_hParent, message, 0, (LPARAM)this);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -