#include static const TCHAR szToolDockWndClass[] = TEXT("ImageSoftToolDockWndClass"); typedef struct _TOOLDOCKWND_INIT { PTOOLBAR_DOCKS TbDocks; PDOCKBAR_ITEM Item; } TOOLDOCKWND_INIT, *PTOOLDOCKWND_INIT; static UINT TbdCalculateInsertIndex(PTOOLBAR_DOCKS TbDocks, DOCK_POSITION Position, POINT pt) { RECT rcRebar; UINT Ret = 0; GetWindowRect(TbDocks->hRebar[Position], &rcRebar); switch (Position) { case TOP_DOCK: case BOTTOM_DOCK: if (pt.y > rcRebar.top + ((rcRebar.bottom - rcRebar.top) / 2)) Ret = (UINT)-1; break; case LEFT_DOCK: case RIGHT_DOCK: if (pt.x > rcRebar.left + ((rcRebar.right - rcRebar.left) / 2)) Ret = (UINT)-1; break; default: break; } return Ret; } INT TbdAdjustUpdateClientRect(PTOOLBAR_DOCKS TbDocks, PRECT rcClient) { INT i, DocksVisible = 0; for (i = 0; i < DOCKS_COUNT; i++) { if (TbDocks->hRebar[i] != NULL) { DocksVisible++; } } if (DocksVisible != 0) { rcClient->top += TbDocks->rcRebar[TOP_DOCK].bottom; rcClient->left += TbDocks->rcRebar[LEFT_DOCK].right; rcClient->right -= TbDocks->rcRebar[RIGHT_DOCK].right; rcClient->bottom -= TbDocks->rcRebar[BOTTOM_DOCK].bottom; } TbDocks->rcClient = *rcClient; return DocksVisible; } HDWP TbdDeferDocks(HDWP hWinPosInfo, PTOOLBAR_DOCKS TbDocks) { LONG cx, cy; HDWP hRet = hWinPosInfo; cx = TbDocks->rcClient.right - TbDocks->rcClient.left; cy = TbDocks->rcClient.bottom - TbDocks->rcClient.top; /* Top dock */ if (TbDocks->hRebar[TOP_DOCK] != NULL) { hRet = DeferWindowPos(hRet, TbDocks->hRebar[TOP_DOCK], NULL, TbDocks->rcClient.left - TbDocks->rcRebar[LEFT_DOCK].right, TbDocks->rcClient.top - TbDocks->rcRebar[TOP_DOCK].bottom, cx + TbDocks->rcRebar[LEFT_DOCK].right + TbDocks->rcRebar[RIGHT_DOCK].right, TbDocks->rcRebar[TOP_DOCK].bottom, SWP_NOZORDER); if (hRet == NULL) return NULL; } /* Left dock */ if (TbDocks->hRebar[LEFT_DOCK] != NULL) { hRet = DeferWindowPos(hRet, TbDocks->hRebar[LEFT_DOCK], NULL, TbDocks->rcClient.left - TbDocks->rcRebar[LEFT_DOCK].right, TbDocks->rcClient.top, TbDocks->rcRebar[LEFT_DOCK].right, cy, SWP_NOZORDER); if (hRet == NULL) return NULL; } /* Right dock */ if (TbDocks->hRebar[RIGHT_DOCK] != NULL) { hRet = DeferWindowPos(hRet, TbDocks->hRebar[RIGHT_DOCK], NULL, TbDocks->rcClient.right, TbDocks->rcClient.top, TbDocks->rcRebar[RIGHT_DOCK].right, cy, SWP_NOZORDER); if (hRet == NULL) return NULL; } /* Bottom dock */ if (TbDocks->hRebar[BOTTOM_DOCK] != NULL) { hRet = DeferWindowPos(hRet, TbDocks->hRebar[BOTTOM_DOCK], NULL, TbDocks->rcClient.left - TbDocks->rcRebar[LEFT_DOCK].right, TbDocks->rcClient.bottom, cx + TbDocks->rcRebar[LEFT_DOCK].right + TbDocks->rcRebar[RIGHT_DOCK].right, TbDocks->rcRebar[BOTTOM_DOCK].bottom, SWP_NOZORDER); if (hRet == NULL) return NULL; } return hRet; } static PDOCKBAR_ITEM TbnDockbarItemFromBandId(PTOOLBAR_DOCKS TbDocks, DOCK_POSITION Position, UINT uBand) { REBARBANDINFO rbi = {0}; rbi.cbSize = sizeof(rbi); rbi.fMask = RBBIM_LPARAM; if (SendMessage(TbDocks->hRebar[Position], RB_GETBANDINFO, (WPARAM)uBand, (LPARAM)&rbi)) { return (PDOCKBAR_ITEM)rbi.lParam; } return NULL; } static VOID TbnRebarChangeSize(PTOOLBAR_DOCKS TbDocks, DOCK_POSITION Position) { LONG cRebar; TbDocks->rcRebar[Position].left = 0; TbDocks->rcRebar[Position].top = 0; cRebar = (LONG)SendMessage(TbDocks->hRebar[Position], RB_GETBARHEIGHT, 0, 0); switch (Position) { case TOP_DOCK: case BOTTOM_DOCK: TbDocks->rcRebar[Position].bottom = cRebar; break; case LEFT_DOCK: case RIGHT_DOCK: TbDocks->rcRebar[Position].right = cRebar; break; default: break; } if (TbDocks->ParentResize != NULL) { RECT rcClient = {0}; GetClientRect(TbDocks->hParent, &rcClient); TbDocks->ParentResize(TbDocks->Context, rcClient.right - rcClient.left, rcClient.bottom - rcClient.top); } } static VOID TbnRebarChevronPushed(PTOOLBAR_DOCKS TbDocks, DOCK_POSITION Position, LPNMREBARCHEVRON lpnm) { PDOCKBAR_ITEM Item; Item = TbnDockbarItemFromBandId(TbDocks, Position, lpnm->uBand); if (Item != NULL && Item->Callbacks->ChevronPushed) { Item->Callbacks->ChevronPushed(TbDocks, &Item->DockBar, Item->Context, Item->hWndClient, lpnm); } } static LRESULT TbnRebarBeginDrag(PTOOLBAR_DOCKS TbDocks, DOCK_POSITION Position, LPNMREBAR lpnmrb) { PDOCKBAR_ITEM Item; Item = TbnDockbarItemFromBandId(TbDocks, Position, lpnmrb->uBand); if (Item != NULL) { TbDocks->Dragging = Item; TbDocks->DraggingBandId = lpnmrb->wID; return FALSE; } return TRUE; } static VOID TbnRebarEndDrag(PTOOLBAR_DOCKS TbDocks, DOCK_POSITION Position, LPNMREBAR lpnmrb) { PDOCKBAR_ITEM Item; Item = TbnDockbarItemFromBandId(TbDocks, Position, lpnmrb->uBand); if (Item != NULL) { /* Nothing to do */ } } BOOL TbdDockBarIdFromClientWindow(PTOOLBAR_DOCKS TbDocks, HWND hWndClient, UINT *Id) { PDOCKBAR_ITEM Item; BOOL Ret = FALSE; Item = TbDocks->Items; while (Item != NULL) { if (Item->hWndClient == hWndClient) { *Id = Item->DockBar.BarId; Ret = TRUE; break; } Item = Item->Next; } return Ret; } BOOL TbdHandleNotifications(PTOOLBAR_DOCKS TbDocks, LPNMHDR pnmh, LRESULT *Result) { BOOL Handled = FALSE; if (pnmh->hwndFrom != NULL) { DOCK_POSITION Position; for (Position = TOP_DOCK; Position < NO_DOCK; Position++) { if (pnmh->hwndFrom == TbDocks->hRebar[Position]) { switch (pnmh->code) { case RBN_HEIGHTCHANGE: { TbnRebarChangeSize(TbDocks, Position); break; } case RBN_BEGINDRAG: { *Result = TbnRebarBeginDrag(TbDocks, Position, (LPNMREBAR)pnmh); break; } case RBN_ENDDRAG: { TbnRebarEndDrag(TbDocks, Position, (LPNMREBAR)pnmh); break; } case RBN_CHEVRONPUSHED: { TbnRebarChevronPushed(TbDocks, Position, (LPNMREBARCHEVRON)pnmh); break; } } Handled = TRUE; break; } } } return Handled; } static BOOL TbdCreateToolbarWnd(PTOOLBAR_DOCKS TbDocks, PDOCKBAR_ITEM Item, DOCK_POSITION PrevPosition, UINT PrevBandIndex, LPREBARBANDINFO rbi, POINT pt, HWND hRebar, UINT uBand, BOOL Drag) { LPCTSTR lpCaption = NULL; TOOLDOCKWND_INIT Init; HWND hToolbar; Init.TbDocks = TbDocks; Init.Item = Item; if (rbi->fMask & RBBIM_TEXT) { lpCaption = rbi->lpText; } Item->Callbacks->DockBand(TbDocks, &Item->DockBar, Item->Context, PrevPosition, NO_DOCK, rbi); if (rbi->fMask & RBBIM_CHILD) Item->hWndClient = rbi->hwndChild; else Item->hWndClient = NULL; if ((rbi->fMask & (RBBIM_CHILDSIZE | RBBIM_SIZE)) == (RBBIM_CHILDSIZE | RBBIM_SIZE)) { RECT rcWnd; static const DWORD dwStyle = WS_POPUPWINDOW | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_DLGFRAME; static const DWORD dwExStyle = WS_EX_TOOLWINDOW; rcWnd.left = pt.x - GetSystemMetrics(SM_CXFIXEDFRAME) - (GetSystemMetrics(SM_CYSMCAPTION) / 2); rcWnd.top = pt.y + GetSystemMetrics(SM_CYFIXEDFRAME) + (GetSystemMetrics(SM_CYSMCAPTION) / 2); rcWnd.right = rcWnd.left + rbi->cx; rcWnd.bottom = rcWnd.top + rbi->cyMinChild; if (AdjustWindowRectEx(&rcWnd, dwStyle, FALSE, dwExStyle)) { hToolbar = CreateWindowEx(dwExStyle, szToolDockWndClass, lpCaption, dwStyle, rcWnd.left, rcWnd.top, rcWnd.right - rcWnd.left, rcWnd.bottom - rcWnd.top, TbDocks->hParent, NULL, hInstance, &Init); if (hToolbar != NULL) { RECT rcClient; if (uBand != (UINT)-1) { /* delete the band before showing the client window, otherwise deleting the band will cause the client window to be hidden, regardless of whether the band was hidden before being deleted or not */ SendMessage(hRebar, RB_DELETEBAND, (WPARAM)uBand, 0); } if (Item->hWndClient != NULL) { GetClientRect(hToolbar, &rcClient); SetParent(Item->hWndClient, hToolbar); SetWindowPos(Item->hWndClient, NULL, 0, 0, rcClient.right, rcClient.bottom, SWP_NOZORDER); SetWindowPos(Item->hWndClient, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW); } SetWindowPos(hToolbar, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW); if (Drag) { SetCursor(LoadCursor(NULL, IDC_ARROW)); SendMessage(hToolbar, WM_NCLBUTTONDOWN, HTCAPTION, MAKELPARAM(pt.x, pt.y)); } return TRUE; } } } return FALSE; } static BOOL TdbInsertToolbar(PTOOLBAR_DOCKS TbDocks, PDOCKBAR_ITEM Item, DOCK_POSITION Position) { LPTSTR lpCaption = NULL; REBARBANDINFO rbi = {0}; BOOL Ret = FALSE; rbi.cbSize = sizeof(rbi); rbi.fMask = RBBIM_ID | RBBIM_STYLE | RBBIM_LPARAM; rbi.wID = Item->DockBar.BarId; rbi.fStyle = RBBS_GRIPPERALWAYS; rbi.lParam = (LPARAM)Item; if (Item->DockBar.DisplayTextId != 0) { if (AllocAndLoadString(&lpCaption, hInstance, Item->DockBar.DisplayTextId)) { rbi.fMask |= RBBIM_TEXT; rbi.lpText = lpCaption; } } if (Item->hWndClient != NULL) { rbi.fMask |= RBBIM_CHILD; rbi.hwndChild = Item->hWndClient; } switch (Item->DockBar.Position) { case NO_DOCK: { POINT pt = {0}; /* FIXME - calculate size */ Ret = TbdCreateToolbarWnd(TbDocks, Item, Item->DockBar.Position, (UINT)-1, &rbi, pt, NULL, (UINT)-1, FALSE); break; } default: { UINT Index = -1; BOOL AddBand = TRUE; if (Item->Callbacks->InsertBand != NULL) { AddBand = Item->Callbacks->InsertBand(TbDocks, &Item->DockBar, Item->Context, &Index, &rbi); } if (AddBand) { Item->Callbacks->DockBand(TbDocks, &Item->DockBar, Item->Context, NO_DOCK, Item->DockBar.Position, &rbi); if (rbi.fMask & RBBIM_CHILD) Item->hWndClient = rbi.hwndChild; else Item->hWndClient = NULL; Ret = SendMessage(TbDocks->hRebar[Position], RB_INSERTBAND, (WPARAM)Index, (LPARAM)&rbi) != 0; if (Ret) { Item->PrevDock = Position; Item->PrevBandIndex = (UINT)SendMessage(TbDocks->hRebar[Position], RB_IDTOINDEX, (WPARAM)Item->DockBar.BarId, 0); } } break; } } if (lpCaption != NULL) { LocalFree((HLOCAL)lpCaption); } return Ret; } BOOL TbdAddToolbar(PTOOLBAR_DOCKS TbDocks, const DOCKBAR *Dockbar, PVOID Context, const DOCKBAR_ITEM_CALLBACKS *Callbacks) { PDOCKBAR_ITEM Item; HWND hRebar; hRebar = TbDocks->hRebar[Dockbar->Position]; if (hRebar != NULL) { Item = HeapAlloc(ProcessHeap, 0, sizeof(DOCKBAR_ITEM)); if (Item != NULL) { /* Initialize the item */ Item->DockBar = *Dockbar; Item->Context = Context; Item->hWndTool = NULL; Item->PrevDock = Dockbar->Position; Item->Callbacks = Callbacks; /* Create the client control */ if (Callbacks->CreateClient != NULL && !Callbacks->CreateClient(TbDocks, &Item->DockBar, Context, hRebar, &Item->hWndClient)) { HeapFree(ProcessHeap, 0, Item); return FALSE; } /* Insert the item into the list */ Item->Next = TbDocks->Items; TbDocks->Items = Item; return TdbInsertToolbar(TbDocks, Item, Dockbar->Position); } } return FALSE; } #define GWLP_TBDOCKS 0 #define GWLP_DOCKITEM (GWLP_TBDOCKS + sizeof(PTOOLBAR_DOCKS)) #define TD_EXTRA_BYTES (GWLP_DOCKITEM + sizeof(PDOCKBAR_ITEM)) static LRESULT CALLBACK ToolDockWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { PTOOLBAR_DOCKS TbDocks; PDOCKBAR_ITEM Item; LRESULT Ret = 0; /* Get the window context */ TbDocks = (PTOOLBAR_DOCKS)GetWindowLongPtr(hwnd, GWLP_TBDOCKS); Item = (PDOCKBAR_ITEM)GetWindowLongPtr(hwnd, GWLP_DOCKITEM); if ((TbDocks == NULL || Item == NULL) && uMsg != WM_CREATE) { goto HandleDefaultMessage; } switch (uMsg) { case WM_NCACTIVATE: { TbdHandleActivation(TbDocks, hwnd, &wParam, &lParam); goto HandleDefaultMessage; } case WM_CREATE: { TbDocks = ((PTOOLDOCKWND_INIT)(((LPCREATESTRUCT)lParam)->lpCreateParams))->TbDocks; Item = ((PTOOLDOCKWND_INIT)(((LPCREATESTRUCT)lParam)->lpCreateParams))->Item; Item->hWndTool = hwnd; SetWindowLongPtr(hwnd, GWLP_TBDOCKS, (LONG_PTR)TbDocks); SetWindowLongPtr(hwnd, GWLP_DOCKITEM, (LONG_PTR)Item); Ret = TRUE; break; } case WM_DESTROY: { Item->hWndTool = NULL; SetWindowLongPtr(hwnd, GWLP_USERDATA, 0); SetWindowLongPtr(hwnd, GWLP_DOCKITEM, 0); break; } default: { HandleDefaultMessage: Ret = DefWindowProc(hwnd, uMsg, wParam, lParam); break; } } return Ret; } static LRESULT CALLBACK RebarSubclassProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData) { LRESULT Ret; Ret = DefSubclassProc(hWnd, uMsg, wParam, lParam); if (uMsg == WM_MOUSEMOVE && (wParam & MK_LBUTTON)) { DOCK_POSITION Position, DragTo = NO_DOCK; RECT rcClient; POINT pt; PTOOLBAR_DOCKS TbDocks = (PTOOLBAR_DOCKS)dwRefData; SIZE szTearOff; szTearOff.cx = GetSystemMetrics(SM_CXCURSOR); szTearOff.cy = GetSystemMetrics(SM_CYCURSOR); /* * Check if we're dragging and if it's time to remove the band */ if (TbDocks->Dragging != NULL && GetCapture() == hWnd) { GetClientRect(hWnd, &rcClient); InflateRect(&rcClient, szTearOff.cx, szTearOff.cy); pt.x = GET_X_LPARAM(lParam); pt.y = GET_Y_LPARAM(lParam); if (!PtInRect(&rcClient, pt)) { REBARBANDINFO rbi; UINT uBand; RECT rc; /* Save all rebar band information, don't query RBBIM_HEADERSIZE because it seems to cause problems with toolbars*/ rbi.cbSize = sizeof(rbi); rbi.fMask = RBBIM_BACKGROUND | RBBIM_CHILD | RBBIM_CHILDSIZE | RBBIM_COLORS | RBBIM_IDEALSIZE | RBBIM_ID | RBBIM_IMAGE | RBBIM_LPARAM | RBBIM_SIZE | RBBIM_STYLE | RBBIM_TEXT; rbi.lpText = TbDocks->szTempText; rbi.cch = sizeof(TbDocks->szTempText); uBand = (UINT)SendMessage(hWnd, RB_IDTOINDEX, (WPARAM)TbDocks->DraggingBandId, 0); if (uBand != (UINT)-1 && SendMessage(hWnd, RB_GETBANDINFO, (WPARAM)uBand, (LPARAM)&rbi)) { MapWindowPoints(hWnd, HWND_DESKTOP, &pt, 1); /* Check if the user is trying to drag it into another dock */ for (Position = TOP_DOCK; Position < NO_DOCK; Position++) { if (TbDocks->hRebar[Position] != NULL && TbDocks->hRebar[Position] != hWnd && GetWindowRect(TbDocks->hRebar[Position], &rc)) { InflateRect(&rc, szTearOff.cx, szTearOff.cy); if (PtInRect(&rc, pt)) { DragTo = Position; break; } } } /* Get the current dock */ for (Position = TOP_DOCK; Position < NO_DOCK; Position++) { if (TbDocks->hRebar[Position] == hWnd) { break; } } ReleaseCapture(); if (SendMessage(hWnd, RB_SHOWBAND, (WPARAM)uBand, FALSE)) { /* Change the parent to the new rebar control */ if (TbDocks->Dragging->hWndClient != NULL) { SetWindowPos(TbDocks->Dragging->hWndClient, NULL, 0, 0, 0, 0, SWP_HIDEWINDOW | SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER); SetParent(TbDocks->Dragging->hWndClient, TbDocks->hRebar[DragTo]); SetWindowPos(TbDocks->Dragging->hWndClient, NULL, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOZORDER); } if (DragTo == NO_DOCK) { if (!TbdCreateToolbarWnd(TbDocks, TbDocks->Dragging, Position, uBand, &rbi, pt, hWnd, uBand, TRUE)) { goto MoveFailed; } } else { BOOL Moved = FALSE; /* Remove the band from the current rebar control */ if (SendMessage(hWnd, RB_DELETEBAND, (WPARAM)uBand, 0)) { UINT uIndex; /* Calculate where to insert the new bar */ uIndex = TbdCalculateInsertIndex(TbDocks, DragTo, pt); SetActiveWindow(TbDocks->hRebar[DragTo]); TbDocks->Dragging->Callbacks->DockBand(TbDocks, &TbDocks->Dragging->DockBar, TbDocks->Dragging->Context, Position, DragTo, &rbi); if (rbi.fMask & RBBIM_CHILD) TbDocks->Dragging->hWndClient = rbi.hwndChild; else TbDocks->Dragging->hWndClient = NULL; /* Insert the toolbar into the new rebar */ rbi.fMask |= RBBIM_STYLE; rbi.fStyle |= RBBS_HIDDEN; if (SendMessage(TbDocks->hRebar[DragTo], RB_INSERTBAND, (WPARAM)uIndex, (LPARAM)&rbi)) { uBand = (UINT)SendMessage(TbDocks->hRebar[DragTo], RB_IDTOINDEX, (WPARAM)TbDocks->DraggingBandId, 0); SendMessage(TbDocks->hRebar[DragTo], RB_SHOWBAND, (WPARAM)uBand, TRUE); /* Simulate a mouse click to continue dragging */ if (uBand != (UINT)-1 && TbDocks->Dragging->hWndClient != NULL && GetWindowRect(TbDocks->Dragging->hWndClient, &rc)) { switch (DragTo) { case LEFT_DOCK: case RIGHT_DOCK: pt.x = rc.left + ((rc.right - rc.left) / 2); pt.y = rc.top - 1; break; default: pt.x = rc.left - 1; pt.y = rc.top + ((rc.bottom - rc.top) / 2); break; } MapWindowPoints(HWND_DESKTOP, TbDocks->hRebar[DragTo], &pt, 1); SetCursor(LoadCursor(NULL, IDC_SIZEALL)); SendMessage(TbDocks->hRebar[DragTo], WM_LBUTTONDOWN, wParam, MAKELPARAM(pt.x, pt.y)); Moved = TRUE; } } } if (!Moved) { MoveFailed: TbDocks->Dragging = NULL; SendMessage(hWnd, RB_SHOWBAND, (WPARAM)uBand, TRUE); } } } } } } } return Ret; } VOID TbdHandleEnabling(PTOOLBAR_DOCKS TbDocks, HWND hWnd, BOOL Enable) { PDOCKBAR_ITEM Item; Item = TbDocks->Items; while (Item != NULL) { if (Item->hWndTool != NULL && Item->hWndTool != hWnd) { EnableWindow(Item->hWndTool, Enable); } Item = Item->Next; } } VOID TbdHandleActivation(PTOOLBAR_DOCKS TbDocks, HWND hWnd, WPARAM *wParam, LPARAM *lParam) { BOOL SynchronizeSiblings = TRUE; BOOL KeepActive = *(BOOL*)wParam; HWND hWndActivate = *(HWND*)lParam; PDOCKBAR_ITEM Item; Item = TbDocks->Items; while (Item != NULL) { if (Item->hWndTool != NULL && Item->hWndTool == hWndActivate) { KeepActive = TRUE; SynchronizeSiblings = FALSE; break; } Item = Item->Next; } if (hWndActivate != (HWND)-1) { if (SynchronizeSiblings) { Item = TbDocks->Items; while (Item != NULL) { if (Item->hWndTool != NULL && Item->hWndTool != hWnd && Item->hWndTool != hWndActivate) { SendMessage(Item->hWndTool, WM_NCACTIVATE, (WPARAM)KeepActive, (LPARAM)-1); } Item = Item->Next; } } } else *lParam = 0; *wParam = (WPARAM)KeepActive; } VOID TbdShowFloatingToolbars(PTOOLBAR_DOCKS TbDocks, BOOL Show) { PDOCKBAR_ITEM Item; Item = TbDocks->Items; while (Item != NULL) { if (Item->hWndTool != NULL) { if ((Show && !IsWindowVisible(Item->hWndTool)) || (!Show && IsWindowVisible(Item->hWndTool))) { ShowWindow(Item->hWndTool, (Show ? SW_SHOW : SW_HIDE)); } } Item = Item->Next; } } VOID TbdInitializeDocks(PTOOLBAR_DOCKS TbDocks, HWND hWndParent, PVOID Context, PDOCKBAR_PARENTRESIZE ParentResizeProc) { DWORD rbStyle = WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | CCS_NODIVIDER | CCS_NOPARENTALIGN | CCS_NOMOVEY | CCS_NOMOVEX | RBS_VARHEIGHT | RBS_AUTOSIZE; DOCK_POSITION Position; TbDocks->hParent = hWndParent; TbDocks->Context = Context; TbDocks->ParentResize = ParentResizeProc; for (Position = TOP_DOCK; Position < NO_DOCK; Position++) { switch (Position) { case LEFT_DOCK: case RIGHT_DOCK: rbStyle |= CCS_VERT; break; default: rbStyle &= ~CCS_VERT; break; } TbDocks->hRebar[Position] = CreateWindowEx(WS_EX_TOOLWINDOW, REBARCLASSNAME, NULL, rbStyle, 0, 0, 0, 0, TbDocks->hParent, NULL, hInstance, NULL); if (TbDocks->hRebar[Position] != NULL) { SetWindowSubclass(TbDocks->hRebar[Position], RebarSubclassProc, 1, (DWORD_PTR)TbDocks); } } } BOOL TbdInitImpl(VOID) { WNDCLASSEX wc = {0}; wc.cbSize = sizeof(WNDCLASSEX); wc.style = CS_HREDRAW | CS_VREDRAW; wc.lpfnWndProc = ToolDockWndProc; wc.cbWndExtra = TD_EXTRA_BYTES; wc.hInstance = hInstance; wc.hCursor = LoadCursor(NULL, IDC_ARROW); wc.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1); wc.lpszClassName = szToolDockWndClass; return RegisterClassEx(&wc) != (ATOM)0; } VOID TbdUninitImpl(VOID) { UnregisterClass(szToolDockWndClass, hInstance); }