| /* |
| * Tab control |
| * |
| * Copyright 1998 Anders Carlsson |
| * Copyright 1999 Alex Priem <alexp@sci.kun.nl> |
| * |
| * TODO: |
| * Image list support |
| * Multiline support |
| * Unicode support |
| * Updown control support |
| * Look and feel |
| * |
| */ |
| |
| #include <string.h> |
| |
| #include "commctrl.h" |
| #include "tab.h" |
| #include "win.h" |
| #include "debug.h" |
| |
| |
| #define TAB_GetInfoPtr(hwnd) ((TAB_INFO *)GetWindowLongA(hwnd,0)) |
| |
| static void TAB_Refresh (HWND hwnd, HDC hdc); |
| |
| static BOOL |
| TAB_SendSimpleNotify (HWND hwnd, UINT code) |
| { |
| NMHDR nmhdr; |
| |
| nmhdr.hwndFrom = hwnd; |
| nmhdr.idFrom = GetWindowLongA(hwnd, GWL_ID); |
| nmhdr.code = code; |
| |
| return (BOOL) SendMessageA (GetParent (hwnd), WM_NOTIFY, |
| (WPARAM) nmhdr.idFrom, (LPARAM) &nmhdr); |
| } |
| |
| |
| static VOID |
| TAB_RelayEvent (HWND hwndTip, HWND hwndMsg, UINT uMsg, |
| WPARAM wParam, LPARAM lParam) |
| { |
| MSG msg; |
| |
| msg.hwnd = hwndMsg; |
| msg.message = uMsg; |
| msg.wParam = wParam; |
| msg.lParam = lParam; |
| msg.time = GetMessageTime (); |
| msg.pt.x = LOWORD(GetMessagePos ()); |
| msg.pt.y = HIWORD(GetMessagePos ()); |
| |
| SendMessageA (hwndTip, TTM_RELAYEVENT, 0, (LPARAM)&msg); |
| } |
| |
| |
| |
| static LRESULT |
| TAB_GetCurSel (HWND hwnd) |
| { |
| TAB_INFO *infoPtr = TAB_GetInfoPtr(hwnd); |
| |
| return infoPtr->iSelected; |
| } |
| |
| static LRESULT |
| TAB_GetCurFocus (HWND hwnd) |
| { |
| TAB_INFO *infoPtr = TAB_GetInfoPtr(hwnd); |
| |
| return infoPtr->uFocus; |
| } |
| |
| static LRESULT |
| TAB_GetToolTips (HWND hwnd, WPARAM wParam, LPARAM lParam) |
| { |
| TAB_INFO *infoPtr = TAB_GetInfoPtr(hwnd); |
| |
| if (infoPtr == NULL) return 0; |
| return infoPtr->hwndToolTip; |
| } |
| |
| |
| static LRESULT |
| TAB_SetCurSel (HWND hwnd,WPARAM wParam) |
| { |
| TAB_INFO *infoPtr = TAB_GetInfoPtr(hwnd); |
| INT iItem=(INT) wParam; |
| INT prevItem; |
| |
| prevItem=-1; |
| if ((iItem >= 0) && (iItem < infoPtr->uNumItem)) { |
| prevItem=infoPtr->iSelected; |
| infoPtr->iSelected=iItem; |
| } |
| return prevItem; |
| } |
| |
| static LRESULT |
| TAB_SetCurFocus (HWND hwnd,WPARAM wParam) |
| { |
| TAB_INFO *infoPtr = TAB_GetInfoPtr(hwnd); |
| INT iItem=(INT) wParam; |
| HDC hdc; |
| |
| if ((iItem < 0) || (iItem > infoPtr->uNumItem)) return 0; |
| |
| infoPtr->uFocus=iItem; |
| if (GetWindowLongA(hwnd, GWL_STYLE) & TCS_BUTTONS) { |
| FIXME (tab,"Should set input focus\n"); |
| } else { |
| if (infoPtr->iSelected != iItem) { |
| if (TAB_SendSimpleNotify(hwnd, TCN_SELCHANGING)!=TRUE) { |
| infoPtr->iSelected = iItem; |
| TAB_SendSimpleNotify(hwnd, TCN_SELCHANGE); |
| hdc = GetDC (hwnd); |
| TAB_Refresh (hwnd, hdc); |
| ReleaseDC (hwnd, hdc); |
| } |
| } |
| } |
| return 0; |
| } |
| |
| static LRESULT |
| TAB_SetToolTips (HWND hwnd, WPARAM wParam, LPARAM lParam) |
| { |
| TAB_INFO *infoPtr = TAB_GetInfoPtr(hwnd); |
| |
| if (infoPtr == NULL) return 0; |
| infoPtr->hwndToolTip = (HWND)wParam; |
| return 0; |
| } |
| |
| |
| static HWND TAB_InternalHitTest (TAB_INFO *infoPtr, POINT pt, |
| UINT *flags) |
| |
| { |
| RECT rect; |
| int iCount; |
| |
| for (iCount = 0; iCount < infoPtr->uNumItem; iCount++) { |
| rect = infoPtr->items[iCount].rect; |
| if (PtInRect (&rect, pt)) return iCount; |
| } |
| *flags=TCHT_NOWHERE; |
| return -1; |
| } |
| |
| static LRESULT |
| TAB_HitTest (HWND hwnd, WPARAM wParam, LPARAM lParam) |
| { |
| TAB_INFO *infoPtr = TAB_GetInfoPtr(hwnd); |
| LPTCHITTESTINFO lptest=(LPTCHITTESTINFO) lParam; |
| |
| return TAB_InternalHitTest (infoPtr,lptest->pt,&lptest->flags); |
| } |
| |
| |
| static LRESULT |
| TAB_LButtonDown (HWND hwnd, WPARAM wParam, LPARAM lParam) |
| { |
| TAB_INFO *infoPtr = TAB_GetInfoPtr(hwnd); |
| |
| if (infoPtr->hwndToolTip) |
| TAB_RelayEvent (infoPtr->hwndToolTip, hwnd, |
| WM_LBUTTONDOWN, wParam, lParam); |
| |
| if (GetWindowLongA(hwnd, GWL_STYLE) & TCS_FOCUSONBUTTONDOWN ) { |
| SetFocus (hwnd); |
| } |
| return 0; |
| } |
| |
| static LRESULT |
| TAB_LButtonUp (HWND hwnd, WPARAM wParam, LPARAM lParam) |
| { |
| TAB_INFO *infoPtr = TAB_GetInfoPtr(hwnd); |
| POINT pt; |
| INT newItem,dummy; |
| HDC hdc; |
| |
| if (infoPtr->hwndToolTip) |
| TAB_RelayEvent (infoPtr->hwndToolTip, hwnd, |
| WM_LBUTTONDOWN, wParam, lParam); |
| |
| pt.x = (INT)LOWORD(lParam); |
| pt.y = (INT)HIWORD(lParam); |
| |
| newItem=TAB_InternalHitTest (infoPtr,pt,&dummy); |
| if (!newItem) return 0; |
| TRACE(tab, "On Tab, item %d\n", newItem); |
| |
| if (infoPtr->iSelected != newItem) { |
| if (TAB_SendSimpleNotify(hwnd, TCN_SELCHANGING)!=TRUE) { |
| infoPtr->iSelected = newItem; |
| TAB_SendSimpleNotify(hwnd, TCN_SELCHANGE); |
| hdc = GetDC (hwnd); |
| TAB_Refresh (hwnd, hdc); |
| ReleaseDC (hwnd, hdc); |
| } |
| } |
| TAB_SendSimpleNotify(hwnd, NM_CLICK); |
| |
| return 0; |
| } |
| |
| static LRESULT |
| TAB_RButtonDown (HWND hwnd, WPARAM wParam, LPARAM lParam) |
| { |
| TAB_SendSimpleNotify(hwnd, NM_RCLICK); |
| return 0; |
| } |
| |
| static LRESULT |
| TAB_MouseMove (HWND hwnd, WPARAM wParam, LPARAM lParam) |
| { |
| TAB_INFO *infoPtr = TAB_GetInfoPtr(hwnd); |
| |
| if (infoPtr->hwndToolTip) |
| TAB_RelayEvent (infoPtr->hwndToolTip, hwnd, |
| WM_LBUTTONDOWN, wParam, lParam); |
| return 0; |
| } |
| |
| static LRESULT |
| TAB_AdjustRect (HWND hwnd, WPARAM wParam, LPARAM lParam) |
| { |
| |
| if (wParam==TRUE) { |
| FIXME (tab,"Should set display rectangle\n"); |
| } else { |
| FIXME (tab,"Should set window rectangle\n"); |
| } |
| |
| return 0; |
| } |
| |
| static void |
| TAB_SetItemBounds (HWND hwnd) |
| { |
| TAB_INFO *infoPtr = TAB_GetInfoPtr(hwnd); |
| RECT rect; |
| HFONT hFont, hOldFont; |
| INT i, left; |
| SIZE size; |
| HDC hdc; |
| |
| /* FIXME: Is this needed? */ |
| GetClientRect (hwnd, &rect); |
| left += (size.cx + 11); |
| |
| hdc = GetDC(hwnd); |
| |
| hFont = infoPtr->hFont ? infoPtr->hFont : GetStockObject (SYSTEM_FONT); |
| hOldFont = SelectObject (hdc, hFont); |
| |
| left = rect.left; |
| |
| for (i = 0; i < infoPtr->uNumItem; i++) |
| { |
| if (GetWindowLongA(hwnd, GWL_STYLE) & TCS_BOTTOM) { |
| infoPtr->items[i].rect.bottom = rect.bottom; |
| infoPtr->items[i].rect.top = rect.bottom-20; |
| } else { |
| infoPtr->items[i].rect.top = rect.top; |
| infoPtr->items[i].rect.bottom = rect.top + 20; |
| } |
| infoPtr->items[i].rect.left = left; |
| |
| GetTextExtentPoint32A(hdc, |
| infoPtr->items[i].pszText, |
| lstrlenA(infoPtr->items[i].pszText), &size); |
| infoPtr->items[i].rect.right = left + size.cx+2*5; |
| TRACE(tab, "TextSize: %i\n ", size.cx); |
| TRACE(tab, "Rect: T %i, L %i, B %i, R %i\n", |
| infoPtr->items[i].rect.top, |
| infoPtr->items[i].rect.left, |
| infoPtr->items[i].rect.bottom, |
| infoPtr->items[i].rect.right); |
| left += (size.cx + 11); |
| } |
| |
| SelectObject (hdc, hOldFont); |
| ReleaseDC (hwnd, hdc); |
| } |
| |
| static void |
| TAB_DrawItem (HWND hwnd, HDC hdc, INT iItem) |
| { |
| TAB_INFO *infoPtr = TAB_GetInfoPtr(hwnd); |
| TAB_ITEM *pti = &infoPtr->items[iItem]; |
| RECT r; |
| INT oldBkMode,cx,cy; |
| HBRUSH hbr = CreateSolidBrush(RGB(255,255,255)); |
| //HBRUSH hbr = CreateSolidBrush (COLOR_BACKGROUND); |
| |
| HPEN hwPen = GetSysColorPen (COLOR_3DHILIGHT); |
| HPEN hbPen = GetSysColorPen (COLOR_BTNSHADOW); |
| HPEN hsdPen = GetSysColorPen (COLOR_BTNTEXT); |
| HPEN htmpPen = (HPEN)NULL; |
| |
| CopyRect(&r, &pti->rect); |
| |
| /* demo */ |
| FillRect(hdc, &r, hbr); |
| |
| |
| |
| |
| htmpPen = hwPen; |
| htmpPen = SelectObject (hdc, htmpPen); |
| if (GetWindowLongA(hwnd, GWL_STYLE) & TCS_BOTTOM) { |
| MoveToEx (hdc, r.left, r.top, NULL); |
| LineTo (hdc, r.left, r.bottom - 2); |
| LineTo (hdc, r.left +2, r.bottom); |
| LineTo (hdc, r.right -1, r.bottom); |
| htmpPen = SelectObject (hdc, hbPen); |
| MoveToEx (hdc, r.right-1, r.top, NULL); |
| LineTo (hdc,r.right-1, r.bottom-1); |
| hbPen = SelectObject (hdc, hsdPen); |
| MoveToEx (hdc, r.right, r.top+1, NULL); |
| LineTo(hdc, r.right,r.bottom); |
| } else { |
| MoveToEx (hdc, r.left, r.bottom, NULL); |
| LineTo (hdc, r.left, r.top + 2); |
| LineTo (hdc, r.left +2, r.top); |
| LineTo (hdc, r.right -1, r.top); |
| htmpPen = SelectObject (hdc, hbPen); |
| MoveToEx (hdc, r.right-1, r.bottom, NULL); |
| LineTo (hdc,r.right-1, r.top+1); |
| hbPen = SelectObject (hdc, hsdPen); |
| MoveToEx (hdc, r.right, r.bottom-1, NULL); |
| LineTo(hdc, r.right,r.top); |
| } |
| |
| hsdPen = SelectObject(hdc,htmpPen); |
| |
| oldBkMode = SetBkMode(hdc, TRANSPARENT); |
| r.left += 3; |
| r.right -= 3; |
| |
| if (infoPtr->himl) { |
| ImageList_Draw (infoPtr->himl, iItem, hdc, |
| r.left, r.top+1, ILD_NORMAL); |
| ImageList_GetIconSize (infoPtr->himl, &cx, &cy); |
| r.left+=cx+3; |
| } |
| SetTextColor (hdc, COLOR_BTNTEXT); |
| DrawTextA(hdc, pti->pszText, lstrlenA(pti->pszText), |
| &r, DT_LEFT|DT_SINGLELINE|DT_VCENTER); |
| if (oldBkMode != TRANSPARENT) |
| SetBkMode(hdc, oldBkMode); |
| } |
| |
| static void |
| TAB_DrawBorder (HWND hwnd, HDC hdc) |
| { |
| HPEN htmPen; |
| HPEN hwPen = GetSysColorPen (COLOR_3DHILIGHT); |
| HPEN hbPen = GetSysColorPen (COLOR_3DDKSHADOW); |
| HPEN hShade = GetSysColorPen (COLOR_BTNSHADOW); |
| |
| RECT rect; |
| |
| htmPen = SelectObject (hdc, hwPen); |
| GetClientRect (hwnd, &rect); |
| |
| MoveToEx (hdc, rect.left, rect.bottom, NULL); |
| LineTo (hdc, rect.left, rect.top+20); |
| |
| LineTo (hdc, rect.right, rect.top+20); |
| |
| hwPen = SelectObject (hdc, htmPen); |
| LineTo (hdc, rect.right, rect.bottom ); |
| LineTo (hdc, rect.left, rect.bottom); |
| hbPen = SelectObject (hdc, hShade ); |
| MoveToEx (hdc, rect.right-1, rect.top+20, NULL); |
| LineTo (hdc, rect.right-1, rect.bottom-1); |
| LineTo (hdc, rect.left, rect.bottom-1); |
| hShade = SelectObject(hdc, hShade); |
| } |
| |
| |
| static void |
| TAB_Refresh (HWND hwnd, HDC hdc) |
| { |
| TAB_INFO *infoPtr = TAB_GetInfoPtr(hwnd); |
| HFONT hOldFont; |
| INT i; |
| |
| if (!infoPtr->DoRedraw) return; |
| |
| TAB_DrawBorder (hwnd, hdc); |
| |
| hOldFont = SelectObject (hdc, infoPtr->hFont); |
| for (i = 0; i < infoPtr->uNumItem; i++) { |
| TAB_DrawItem (hwnd, hdc, i); |
| } |
| SelectObject (hdc, hOldFont); |
| } |
| |
| static LRESULT |
| TAB_SetRedraw (HWND hwnd, WPARAM wParam) |
| { |
| TAB_INFO *infoPtr = TAB_GetInfoPtr(hwnd); |
| |
| infoPtr->DoRedraw=(BOOL) wParam; |
| return 0; |
| } |
| |
| static LRESULT |
| TAB_Paint (HWND hwnd, WPARAM wParam) |
| { |
| HDC hdc; |
| PAINTSTRUCT ps; |
| |
| hdc = wParam== 0 ? BeginPaint (hwnd, &ps) : (HDC)wParam; |
| TAB_Refresh (hwnd, hdc); |
| |
| if(!wParam) |
| EndPaint (hwnd, &ps); |
| return 0; |
| } |
| |
| static LRESULT |
| TAB_InsertItem (HWND hwnd, WPARAM wParam, LPARAM lParam) |
| { |
| |
| TAB_INFO *infoPtr = TAB_GetInfoPtr(hwnd); |
| TCITEMA *pti; |
| HDC hdc; |
| INT iItem, len; |
| RECT rect; |
| |
| GetClientRect (hwnd, &rect); |
| TRACE(tab, "Rect: %x T %i, L %i, B %i, R %i\n", hwnd, |
| rect.top, rect.left, rect.bottom, rect.right); |
| |
| pti = (TCITEMA *)lParam; |
| iItem = (INT)wParam; |
| |
| if (iItem < 0) return -1; |
| if (iItem > infoPtr->uNumItem) |
| iItem = infoPtr->uNumItem; |
| |
| if (infoPtr->uNumItem == 0) { |
| infoPtr->items = COMCTL32_Alloc (sizeof (TAB_ITEM)); |
| infoPtr->uNumItem++; |
| } |
| else { |
| TAB_ITEM *oldItems = infoPtr->items; |
| |
| infoPtr->uNumItem++; |
| infoPtr->items = COMCTL32_Alloc (sizeof (TAB_ITEM) * infoPtr->uNumItem); |
| |
| /* pre insert copy */ |
| if (iItem > 0) { |
| memcpy (&infoPtr->items[0], &oldItems[0], |
| iItem * sizeof(TAB_ITEM)); |
| } |
| |
| /* post insert copy */ |
| if (iItem < infoPtr->uNumItem - 1) { |
| memcpy (&infoPtr->items[iItem+1], &oldItems[iItem], |
| (infoPtr->uNumItem - iItem - 1) * sizeof(TAB_ITEM)); |
| |
| } |
| |
| COMCTL32_Free (oldItems); |
| } |
| |
| infoPtr->items[iItem].mask = pti->mask; |
| if (pti->mask & TCIF_TEXT) { |
| len = lstrlenA (pti->pszText); |
| infoPtr->items[iItem].pszText = COMCTL32_Alloc (len+1); |
| lstrcpyA (infoPtr->items[iItem].pszText, pti->pszText); |
| infoPtr->items[iItem].cchTextMax = pti->cchTextMax; |
| } |
| |
| if (pti->mask & TCIF_IMAGE) |
| infoPtr->items[iItem].iImage = pti->iImage; |
| |
| if (pti->mask & TCIF_PARAM) |
| infoPtr->items[iItem].lParam = pti->lParam; |
| |
| hdc = GetDC (hwnd); |
| TAB_Refresh (hwnd, hdc); |
| ReleaseDC (hwnd, hdc); |
| |
| TRACE(tab, "[%04x]: added item %d '%s'\n", |
| hwnd, iItem, infoPtr->items[iItem].pszText); |
| |
| TAB_SetItemBounds(hwnd); |
| return iItem; |
| } |
| |
| static LRESULT |
| TAB_SetItemA (HWND hwnd, WPARAM wParam, LPARAM lParam) |
| { |
| TAB_INFO *infoPtr = TAB_GetInfoPtr(hwnd); |
| TCITEMA *tabItem; |
| TAB_ITEM *wineItem; |
| INT iItem,len; |
| |
| iItem=(INT) wParam; |
| tabItem=(LPTCITEMA ) lParam; |
| TRACE (tab,"%d %p\n",iItem, tabItem); |
| if ((iItem<0) || (iItem>infoPtr->uNumItem)) return FALSE; |
| |
| wineItem=& infoPtr->items[iItem]; |
| |
| if (tabItem->mask & TCIF_IMAGE) |
| wineItem->iImage=tabItem->iImage; |
| |
| if (tabItem->mask & TCIF_PARAM) |
| wineItem->lParam=tabItem->lParam; |
| |
| if (tabItem->mask & TCIF_RTLREADING) |
| FIXME (tab,"TCIF_RTLREADING\n"); |
| |
| if (tabItem->mask & TCIF_STATE) |
| wineItem->dwState=tabItem->dwState; |
| |
| if (tabItem->mask & TCIF_TEXT) { |
| len=lstrlenA (tabItem->pszText); |
| if (len>wineItem->cchTextMax) |
| wineItem->pszText= COMCTL32_ReAlloc (wineItem->pszText, len+1); |
| lstrcpynA (wineItem->pszText, tabItem->pszText, len); |
| } |
| |
| return TRUE; |
| } |
| |
| static LRESULT |
| TAB_GetItemCount (HWND hwnd, WPARAM wParam, LPARAM lParam) |
| { |
| TAB_INFO *infoPtr = TAB_GetInfoPtr(hwnd); |
| |
| return infoPtr->uNumItem; |
| } |
| |
| |
| static LRESULT |
| TAB_GetItemA (HWND hwnd, WPARAM wParam, LPARAM lParam) |
| { |
| TAB_INFO *infoPtr = TAB_GetInfoPtr(hwnd); |
| TCITEMA *tabItem; |
| TAB_ITEM *wineItem; |
| INT iItem; |
| |
| iItem=(INT) wParam; |
| tabItem=(LPTCITEMA) lParam; |
| TRACE (tab,"\n"); |
| if ((iItem<0) || (iItem>infoPtr->uNumItem)) return FALSE; |
| |
| wineItem=& infoPtr->items[iItem]; |
| |
| if (tabItem->mask & TCIF_IMAGE) |
| tabItem->iImage=wineItem->iImage; |
| |
| if (tabItem->mask & TCIF_PARAM) |
| tabItem->lParam=wineItem->lParam; |
| |
| if (tabItem->mask & TCIF_RTLREADING) |
| FIXME (tab, "TCIF_RTLREADING\n"); |
| |
| if (tabItem->mask & TCIF_STATE) |
| tabItem->dwState=wineItem->dwState; |
| |
| if (tabItem->mask & TCIF_TEXT) |
| lstrcpynA (tabItem->pszText, wineItem->pszText, tabItem->cchTextMax); |
| |
| return TRUE; |
| } |
| |
| static LRESULT |
| TAB_DeleteItem (HWND hwnd, WPARAM wParam, LPARAM lParam) |
| { |
| FIXME (tab,"stub \n"); |
| return TRUE; |
| } |
| |
| static LRESULT |
| TAB_DeleteAllItems (HWND hwnd, WPARAM wParam, LPARAM lParam) |
| { |
| TAB_INFO *infoPtr = TAB_GetInfoPtr(hwnd); |
| |
| COMCTL32_Free (infoPtr->items); |
| infoPtr->uNumItem=0; |
| |
| return TRUE; |
| } |
| |
| |
| static LRESULT |
| TAB_GetFont (HWND hwnd, WPARAM wParam, LPARAM lParam) |
| { |
| TAB_INFO *infoPtr = TAB_GetInfoPtr(hwnd); |
| |
| TRACE (tab,"\n"); |
| return (LRESULT)infoPtr->hFont; |
| } |
| |
| static LRESULT |
| TAB_SetFont (HWND hwnd, WPARAM wParam, LPARAM lParam) |
| |
| { |
| TAB_INFO *infoPtr = TAB_GetInfoPtr(hwnd); |
| TEXTMETRICA tm; |
| HFONT hFont, hOldFont; |
| HDC hdc; |
| |
| TRACE (tab,"%x %lx\n",wParam, lParam); |
| |
| infoPtr->hFont = (HFONT)wParam; |
| |
| hFont = infoPtr->hFont ? infoPtr->hFont : GetStockObject (SYSTEM_FONT); |
| |
| hdc = GetDC (0); |
| hOldFont = SelectObject (hdc, hFont); |
| GetTextMetricsA (hdc, &tm); |
| infoPtr->nHeight= tm.tmHeight + tm.tmExternalLeading; |
| SelectObject (hdc, hOldFont); |
| |
| if (lParam) TAB_Refresh (hwnd,hdc); |
| ReleaseDC (0, hdc); |
| |
| return 0; |
| } |
| |
| |
| static LRESULT |
| TAB_GetImageList (HWND hwnd, WPARAM wParam, LPARAM lParam) |
| { |
| TAB_INFO *infoPtr = TAB_GetInfoPtr(hwnd); |
| |
| TRACE (tab,"\n"); |
| return (LRESULT)infoPtr->himl; |
| } |
| |
| static LRESULT |
| TAB_SetImageList (HWND hwnd, WPARAM wParam, LPARAM lParam) |
| { |
| TAB_INFO *infoPtr = TAB_GetInfoPtr(hwnd); |
| HIMAGELIST himlPrev; |
| |
| TRACE (tab,"\n"); |
| himlPrev = infoPtr->himl; |
| infoPtr->himl= (HIMAGELIST)lParam; |
| return (LRESULT)himlPrev; |
| } |
| |
| |
| static LRESULT |
| TAB_Size (HWND hwnd, WPARAM wParam, LPARAM lParam) |
| |
| { |
| RECT parent_rect; |
| HWND parent; |
| HDC hdc; |
| UINT uPosFlags,cx,cy; |
| |
| uPosFlags=0; |
| if (!wParam) { |
| parent = GetParent (hwnd); |
| GetClientRect(parent, &parent_rect); |
| cx=LOWORD (lParam); |
| cy=HIWORD (lParam); |
| if (GetWindowLongA(hwnd, GWL_STYLE) & CCS_NORESIZE) |
| uPosFlags |= (SWP_NOSIZE | SWP_NOMOVE); |
| |
| SetWindowPos (hwnd, 0, parent_rect.left, parent_rect.top, |
| cx, cy, uPosFlags | SWP_NOZORDER); |
| } else { |
| FIXME (tab,"WM_SIZE flag %x %lx not handled\n", wParam, lParam); |
| } |
| |
| TAB_SetItemBounds (hwnd); |
| hdc = GetDC (hwnd); |
| TAB_Refresh (hwnd, hdc); |
| ReleaseDC (hwnd, hdc); |
| |
| return 0; |
| } |
| |
| |
| static LRESULT |
| TAB_Create (HWND hwnd, WPARAM wParam, LPARAM lParam) |
| { |
| TAB_INFO *infoPtr; |
| |
| infoPtr = (TAB_INFO *)COMCTL32_Alloc (sizeof(TAB_INFO)); |
| SetWindowLongA(hwnd, 0, (DWORD)infoPtr); |
| |
| infoPtr->uNumItem = 0; |
| infoPtr->hFont = 0; |
| infoPtr->items = 0; |
| infoPtr->hcurArrow = LoadCursorA (0, IDC_ARROWA); |
| infoPtr->iSelected = -1; |
| infoPtr->hwndToolTip=0; |
| |
| TRACE(tab, "Created tab control, hwnd [%04x]\n", hwnd); |
| if (GetWindowLongA(hwnd, GWL_STYLE) & TCS_TOOLTIPS) { |
| /* Create tooltip control */ |
| infoPtr->hwndToolTip = |
| CreateWindowExA (0, TOOLTIPS_CLASSA, NULL, 0, |
| CW_USEDEFAULT, CW_USEDEFAULT, |
| CW_USEDEFAULT, CW_USEDEFAULT, |
| hwnd, 0, 0, 0); |
| |
| /* Send NM_TOOLTIPSCREATED notification */ |
| if (infoPtr->hwndToolTip) { |
| NMTOOLTIPSCREATED nmttc; |
| |
| nmttc.hdr.hwndFrom = hwnd; |
| nmttc.hdr.idFrom = GetWindowLongA(hwnd, GWL_ID); |
| nmttc.hdr.code = NM_TOOLTIPSCREATED; |
| nmttc.hwndToolTips = infoPtr->hwndToolTip; |
| |
| SendMessageA (GetParent (hwnd), WM_NOTIFY, |
| (WPARAM)GetWindowLongA(hwnd, GWL_ID), (LPARAM)&nmttc); |
| } |
| } |
| |
| |
| return 0; |
| } |
| |
| static LRESULT |
| TAB_Destroy (HWND hwnd, WPARAM wParam, LPARAM lParam) |
| { |
| TAB_INFO *infoPtr = TAB_GetInfoPtr(hwnd); |
| INT iItem; |
| |
| if (infoPtr->items) { |
| for (iItem = 0; iItem < infoPtr->uNumItem; iItem++) { |
| if (infoPtr->items[iItem].pszText) |
| COMCTL32_Free (infoPtr->items[iItem].pszText); |
| } |
| COMCTL32_Free (infoPtr->items); |
| } |
| |
| if (infoPtr->hwndToolTip) |
| DestroyWindow (infoPtr->hwndToolTip); |
| |
| COMCTL32_Free (infoPtr); |
| return 0; |
| } |
| |
| LRESULT WINAPI |
| TAB_WindowProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) |
| { |
| switch (uMsg) |
| { |
| |
| case TCM_GETIMAGELIST: |
| return TAB_GetImageList (hwnd, wParam, lParam); |
| |
| case TCM_SETIMAGELIST: |
| return TAB_SetImageList (hwnd, wParam, lParam); |
| |
| case TCM_GETITEMCOUNT: |
| return TAB_GetItemCount (hwnd, wParam, lParam); |
| |
| case TCM_GETITEMA: |
| return TAB_GetItemA (hwnd, wParam, lParam); |
| |
| case TCM_GETITEMW: |
| FIXME (tab, "Unimplemented msg TCM_GETITEM32W\n"); |
| return 0; |
| |
| case TCM_SETITEMA: |
| return TAB_SetItemA (hwnd, wParam, lParam); |
| |
| case TCM_SETITEMW: |
| FIXME (tab, "Unimplemented msg TCM_GETITEM32W\n"); |
| return 0; |
| |
| case TCM_DELETEITEM: |
| return TAB_DeleteItem (hwnd, wParam, lParam); |
| |
| case TCM_DELETEALLITEMS: |
| return TAB_DeleteAllItems (hwnd, wParam, lParam); |
| |
| case TCM_GETITEMRECT: |
| FIXME (tab, "Unimplemented msg TCM_GETITEMRECT\n"); |
| return 0; |
| |
| case TCM_GETCURSEL: |
| return TAB_GetCurSel (hwnd); |
| |
| case TCM_HITTEST: |
| return TAB_HitTest (hwnd, wParam, lParam); |
| |
| case TCM_SETCURSEL: |
| return TAB_SetCurSel (hwnd, wParam); |
| |
| case TCM_INSERTITEMA: |
| return TAB_InsertItem (hwnd, wParam, lParam); |
| |
| case TCM_INSERTITEMW: |
| FIXME (tab, "Unimplemented msg TCM_INSERTITEM32W\n"); |
| return 0; |
| |
| case TCM_SETITEMEXTRA: |
| FIXME (tab, "Unimplemented msg TCM_SETITEMEXTRA\n"); |
| return 0; |
| |
| case TCM_ADJUSTRECT: |
| return TAB_AdjustRect (hwnd, wParam, lParam); |
| |
| case TCM_SETITEMSIZE: |
| FIXME (tab, "Unimplemented msg TCM_SETITEMSIZE\n"); |
| return 0; |
| |
| case TCM_REMOVEIMAGE: |
| FIXME (tab, "Unimplemented msg TCM_REMOVEIMAGE\n"); |
| return 0; |
| |
| case TCM_SETPADDING: |
| FIXME (tab, "Unimplemented msg TCM_SETPADDING\n"); |
| return 0; |
| |
| case TCM_GETROWCOUNT: |
| FIXME (tab, "Unimplemented msg TCM_GETROWCOUNT\n"); |
| return 0; |
| |
| case TCM_GETTOOLTIPS: |
| return TAB_GetToolTips (hwnd, wParam, lParam); |
| |
| case TCM_SETTOOLTIPS: |
| return TAB_SetToolTips (hwnd, wParam, lParam); |
| |
| case TCM_GETCURFOCUS: |
| return TAB_GetCurFocus (hwnd); |
| |
| case TCM_SETCURFOCUS: |
| return TAB_SetCurFocus (hwnd, wParam); |
| |
| case TCM_SETMINTTABWIDTH: |
| FIXME (tab, "Unimplemented msg TCM_SETMINTTABWIDTH\n"); |
| return 0; |
| |
| case TCM_DESELECTALL: |
| FIXME (tab, "Unimplemented msg TCM_DESELECTALL\n"); |
| return 0; |
| |
| case WM_GETFONT: |
| return TAB_GetFont (hwnd, wParam, lParam); |
| |
| case WM_SETFONT: |
| return TAB_SetFont (hwnd, wParam, lParam); |
| |
| case WM_CREATE: |
| return TAB_Create (hwnd, wParam, lParam); |
| |
| case WM_DESTROY: |
| return TAB_Destroy (hwnd, wParam, lParam); |
| |
| case WM_GETDLGCODE: |
| return DLGC_WANTARROWS | DLGC_WANTCHARS; |
| |
| case WM_LBUTTONDOWN: |
| return TAB_LButtonDown (hwnd, wParam, lParam); |
| |
| case WM_LBUTTONUP: |
| return TAB_LButtonUp (hwnd, wParam, lParam); |
| |
| case WM_RBUTTONDOWN: |
| return TAB_RButtonDown (hwnd, wParam, lParam); |
| |
| case WM_MOUSEMOVE: |
| return TAB_MouseMove (hwnd, wParam, lParam); |
| |
| case WM_PAINT: |
| return TAB_Paint (hwnd, wParam); |
| case WM_SIZE: |
| return TAB_Size (hwnd, wParam, lParam); |
| |
| case WM_SETREDRAW: |
| return TAB_SetRedraw (hwnd, wParam); |
| |
| |
| default: |
| if (uMsg >= WM_USER) |
| ERR (tab, "unknown msg %04x wp=%08x lp=%08lx\n", |
| uMsg, wParam, lParam); |
| return DefWindowProcA (hwnd, uMsg, wParam, lParam); |
| } |
| return 0; |
| } |
| |
| |
| VOID |
| TAB_Register (VOID) |
| { |
| WNDCLASSA wndClass; |
| |
| if (GlobalFindAtomA (WC_TABCONTROLA)) return; |
| |
| ZeroMemory (&wndClass, sizeof(WNDCLASSA)); |
| wndClass.style = CS_GLOBALCLASS | CS_DBLCLKS | CS_SAVEBITS; |
| wndClass.lpfnWndProc = (WNDPROC)TAB_WindowProc; |
| wndClass.cbClsExtra = 0; |
| wndClass.cbWndExtra = sizeof(TAB_INFO *); |
| wndClass.hCursor = LoadCursorA (0, IDC_ARROWA); |
| wndClass.hbrBackground = 0; |
| wndClass.lpszClassName = WC_TABCONTROLA; |
| |
| RegisterClassA (&wndClass); |
| } |
| |
| |
| VOID |
| TAB_Unregister (VOID) |
| { |
| if (GlobalFindAtomA (WC_TABCONTROLA)) |
| UnregisterClassA (WC_TABCONTROLA, (HINSTANCE)NULL); |
| } |
| |