www.pudn.com > ExpBar_src.zip > tasklink.c
/* * file : tasklink.c * language : ANSI/ISO C * plattform : Win32 (Windows 98/Me/NT/2000/XP) * description : implements the tasklink control for the xp-style explorer bar * * revision history: * ================= * * date: author: description: * -------------------------------------------------------------------------- * 02/17/2004 Ingo A. Kubbilun first published version 1.0 */ #include#include #include #define TLS_NOAUTOSIZE TLS_reserved static void APIPRIVATE GetHitTestRect ( HWND hwnd, PTLSTRUCT pTLS, LPRECT lpRC ) { if (GetWindowLong(hwnd,GWL_STYLE) & TLS_NOAUTOSIZE) GetClientRect(hwnd,lpRC); else { memcpy(lpRC,&pTLS->rcText,sizeof(RECT)); if (((pTLS->rcIcon.right-pTLS->rcIcon.left)>0) && ((pTLS->rcIcon.bottom-pTLS->rcIcon.top)>0)) { if (pTLS->rcIcon.left < lpRC->left) lpRC->left = pTLS->rcIcon.left; if (pTLS->rcIcon.right > lpRC->right) lpRC->right = pTLS->rcIcon.right; if (pTLS->rcIcon.top < lpRC->top) lpRC->top = pTLS->rcIcon.top; if (pTLS->rcIcon.bottom > lpRC->bottom) lpRC->bottom = pTLS->rcIcon.bottom; } } } static void APIPRIVATE ResizeTTControl ( HWND hwnd, PTLSTRUCT pTLS ) { TOOLINFO ti; if ((pTLS) && (TL_HAVE_TOOLTIP_SAFE(pTLS))) { memset(&ti,0,sizeof(ti)); ti.cbSize = sizeof(TOOLINFO); ti.uFlags = TTF_TRANSPARENT; ti.hwnd = hwnd; ti.lpszText = LPSTR_TEXTCALLBACK; ti.uId = 1; GetHitTestRect(hwnd,pTLS,&ti.rect); SendMessage(pTLS->hwndToolTip,TTM_DELTOOL,0,(LPARAM)&ti); SendMessage(pTLS->hwndToolTip,TTM_ADDTOOL,0,(LPARAM)&ti); } } static void APIPRIVATE CheckNeedRepaint ( HWND hwnd, PTLSTRUCT pTLS ) { int iState = ITEMSTATE_COLD; RECT rcClient; POINT pt; if (!pTLS->bEnabled) iState = ITEMSTATE_DISABLED; else { GetHitTestRect(hwnd,pTLS,&rcClient); if (pTLS->bKeyDown) iState = ITEMSTATE_PRESSED; else { pt.x = pTLS->iMouseX; pt.y = pTLS->iMouseY; if (PtInRect(&rcClient,pt)) { if (pTLS->bLButtonDown) iState = ITEMSTATE_PRESSED; else iState = ITEMSTATE_HOT; } else if (GetCapture()==hwnd) iState = ITEMSTATE_HOT; } } if (pTLS->iState!=iState) { pTLS->iState = iState; InvalidateRect(hwnd,NULL,TRUE); } } // iRequiredWidth only used if !(lStyle & TLS_NOAUTOSIZE) !!! static BOOL APIENTRY GetItemSize ( HWND hwnd, PTLSTRUCT pTLS, PSIZE pSI, int iRequiredWidth ) { SIZE si,siText,siSingleLine; TCHAR szText[256]; HDC hDC; HGDIOBJ hOldObj; RECT rcClient,rcText,rcClientOrig; LONG lStyle = GetWindowLong(hwnd,GWL_STYLE); LONG lExStyle = GetWindowLong(hwnd,GWL_EXSTYLE); UINT uDTStyle = 0L; int iTextWidthAvail,iTextHeightAvail,iTextHeight,iDelta,iMinY,iMaxY; if (!pTLS) return FALSE; if (lExStyle & WS_EX_RIGHT) { lStyle |= TLS_ICONRIGHT; if ((lStyle & TLS_HALIGNMASK)==TLS_LEFT) lStyle = (lStyle & ~TLS_HALIGNMASK)|TLS_RIGHT; else if ((lStyle & TLS_HALIGNMASK)==TLS_RIGHT) lStyle = (lStyle & ~TLS_HALIGNMASK)|TLS_LEFT; } if (lStyle & TLS_NOAUTOSIZE) { GetClientRect(hwnd,&rcClient); } else { if (iRequiredWidth==-1) GetClientRect(hwnd,&rcClient); else rcClient.right = iRequiredWidth; rcClient.left = rcClient.top = 0; rcClient.bottom = 32767; } memcpy(&rcClientOrig,&rcClient,sizeof(RECT)); si.cx = 0; si.cy = 0; if (pTLS->hIListNormal) { if (ImageList_GetIconSize(pTLS->hIListNormal,&si.cx,&si.cy)) si.cx += pTLS->iHSpace; } hDC = GetDC(hwnd); if (hDC) { hOldObj = SelectObject(hDC,pTLS->hFontHot); szText[0]=0x00; GetWindowText(hwnd,szText,256); if (lStyle & TLS_WORDBREAK) // multiline, use current control width { rcText.left = 0; rcText.right = rcClient.right-si.cx; if (lStyle & TLS_FOCUSRECT) rcText.right -= 2; rcText.top = 0; rcText.bottom = 0; uDTStyle = DT_EXTERNALLEADING|DT_WORDBREAK; } else { if (lStyle & TLS_END_ELLIPSIS) // singleline, use current control width { rcText.left = 0; rcText.right = rcClient.right-si.cx; if (lStyle & TLS_FOCUSRECT) rcText.right -= 2; rcText.top = 0; rcText.bottom = 0; uDTStyle = DT_END_ELLIPSIS|DT_SINGLELINE; } else // singleline, ignore current control width { rcText.left = 0; rcText.right = 0; rcText.top = 0; rcText.bottom = 0; uDTStyle = DT_SINGLELINE|DT_NOCLIP; } } uDTStyle |= DT_CALCRECT|DT_LEFT|DT_TOP; if (lExStyle & WS_EX_RTLREADING) uDTStyle |= DT_RTLREADING; siText.cy = DrawTextEx(hDC,szText,lstrlen(szText),&rcText,uDTStyle,NULL); siText.cx = rcText.right; rcText.left = 0; rcText.right = 0; rcText.top = 0; rcText.bottom = 0; uDTStyle = DT_SINGLELINE|DT_NOCLIP|DT_CALCRECT|DT_LEFT|DT_TOP; if (lExStyle & WS_EX_RTLREADING) uDTStyle |= DT_RTLREADING; siSingleLine.cy = DrawTextEx(hDC,szText,lstrlen(szText),&rcText,uDTStyle,NULL); siSingleLine.cx = rcText.right; pTLS->bMultiLine = (siText.cy>=(siSingleLine.cy<<1)) ? TRUE : FALSE; if (si.cy) { si.cx -= pTLS->iHSpace; } SelectObject(hDC,hOldObj); ReleaseDC(hwnd,hDC); if (lStyle & TLS_FOCUSRECT) { siText.cx += 2; siText.cy += 2; siSingleLine.cx += 2; siSingleLine.cy += 2; } // place icon either on the left or on the right side if (si.cy) // we do have an icon { if (lStyle & TLS_ICONRIGHT) { pTLS->rcIcon.right = rcClient.right; pTLS->rcIcon.left = pTLS->rcIcon.right-si.cx; pTLS->rcIcon.top = 0; pTLS->rcIcon.bottom = si.cy; rcClient.right -= si.cx+pTLS->iHSpace; } else { pTLS->rcIcon.left = rcClient.left; pTLS->rcIcon.right = pTLS->rcIcon.left+si.cx; pTLS->rcIcon.top = 0; pTLS->rcIcon.bottom = si.cy; rcClient.left += si.cx+pTLS->iHSpace; } } else memset(&pTLS->rcIcon,0,sizeof(RECT)); iTextWidthAvail = rcClient.right-rcClient.left; if (iTextWidthAvail<=0) memset(&pTLS->rcText,0,sizeof(RECT)); else { if (iTextWidthAvail rcText.left = rcClient.left; pTLS->rcText.right = pTLS->rcText.left+siText.cx; break; case TLS_RIGHT: pTLS->rcText.right = rcClient.right; pTLS->rcText.left = pTLS->rcText.right-siText.cx; break; default: pTLS->rcText.left = rcClient.left+(iTextWidthAvail>>1)-(siText.cx>>1); pTLS->rcText.right = pTLS->rcText.left+siText.cx; break; } if (pTLS->bMultiLine) iTextHeight = siText.cy; else iTextHeight = siSingleLine.cy; switch(lStyle & TLS_VALIGNMASK) { case TLS_TOP: pTLS->rcText.top = rcClient.top; pTLS->rcText.bottom = pTLS->rcText.top+iTextHeight; break; case TLS_BOTTOM: if (lStyle & TLS_NOAUTOSIZE) { pTLS->rcText.bottom = rcClient.bottom; pTLS->rcText.top = pTLS->rcText.bottom-iTextHeight; if (pTLS->rcText.top<0) pTLS->rcText.top = 0; } else { pTLS->rcText.top = rcClient.top; pTLS->rcText.bottom = pTLS->rcText.top+iTextHeight; } break; default: if (lStyle & TLS_NOAUTOSIZE) { iTextHeightAvail = rcClient.bottom-rcClient.top; if (iTextHeight>iTextHeightAvail) iTextHeight = iTextHeightAvail; pTLS->rcText.top = rcClient.top+(iTextHeightAvail>>1)-(iTextHeight>>1); pTLS->rcText.bottom = pTLS->rcText.top+iTextHeight; } else { pTLS->rcText.top = rcClient.top; pTLS->rcText.bottom = pTLS->rcText.top+iTextHeight; } break; } } if (si.cy) // WE DO HAVE AN ICON ////////////////////////////////////////////////////////////////// { pTLS->rcIcon.top += pTLS->rcText.top; pTLS->rcIcon.bottom += pTLS->rcText.top; if (pTLS->bMultiLine) { if (si.cy>siText.cy) // icon bigger than multiline text { iDelta = (si.cy-siText.cy)>>1; pTLS->rcText.top += iDelta; pTLS->rcText.bottom += iDelta; } else if (si.cy >1; pTLS->rcIcon.top += iDelta; pTLS->rcIcon.bottom += iDelta; } else if (si.cy>siSingleLine.cy) // icon bigger than single text (smaller than multiline) { iDelta = (siText.cy-si.cy)>>1; pTLS->rcIcon.top += iDelta; pTLS->rcIcon.bottom += iDelta; } } } else { if (si.cy >1; pTLS->rcIcon.top += iDelta; pTLS->rcIcon.bottom += iDelta; } else if (si.cy>siSingleLine.cy) // icon bigger than text { iDelta = (si.cy-siSingleLine.cy)>>1; pTLS->rcText.top += iDelta; pTLS->rcText.bottom += iDelta; } } } iMinY = pTLS->rcText.top rcIcon.top ? pTLS->rcText.top : pTLS->rcIcon.top; if (iMinY<0) { pTLS->rcText.top -= iMinY; pTLS->rcText.bottom -= iMinY; pTLS->rcIcon.top -= iMinY; pTLS->rcIcon.bottom -= iMinY; } iMaxY = pTLS->rcText.bottom>pTLS->rcIcon.bottom ? pTLS->rcText.bottom : pTLS->rcIcon.bottom; pSI->cx = rcClientOrig.right; if (lStyle & TLS_NOAUTOSIZE) { pSI->cy = rcClient.bottom; if (pTLS->rcText.bottom>rcClient.bottom) pTLS->rcText.bottom = rcClient.bottom; if (pTLS->rcIcon.bottom>rcClient.bottom) pTLS->rcIcon.bottom = rcClient.bottom; } else pSI->cy = iMaxY; SelectObject(hDC,hOldObj); ReleaseDC(hwnd,hDC); } ResizeTTControl(hwnd,pTLS); return TRUE; } LRESULT CALLBACK TaskLinkWndProc ( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam ) { switch(uMsg) { case WM_LBUTTONDOWN: case WM_LBUTTONUP: if (TL_HAVE_DONTRELAYLBDNUP) break; case WM_MBUTTONDOWN: case WM_MBUTTONUP: case WM_RBUTTONDOWN: case WM_RBUTTONUP: case WM_MOUSEMOVE: { PTLSTRUCT pTLS = (PTLSTRUCT)GetWindowLong(hwnd,GWL_USERDATA); MSG msg; if (!pTLS) break; if (TL_HAVE_TOOLTIP_SAFE(pTLS)) { msg.hwnd = hwnd; msg.message = uMsg; msg.wParam = wParam; msg.lParam = lParam; msg.pt.x = ((int)(short)LOWORD(lParam)); msg.pt.y = ((int)(short)HIWORD(lParam)); ClientToScreen(hwnd,&msg.pt); SendMessage(pTLS->hwndToolTip,TTM_RELAYEVENT,(WPARAM)0,(LPARAM)&msg); } break; } } switch(uMsg) { case WM_GETORIGDIMENSIONS: { PTLSTRUCT pTLS = (PTLSTRUCT)GetWindowLong(hwnd,GWL_USERDATA); if (pTLS) { *((int*)wParam) = pTLS->iOrigWidth; *((int*)lParam) = pTLS->iOrigHeight; } else { *((int*)wParam) = 0; *((int*)lParam) = 0; } return 0L; } case WM_CREATE: { PTLSTRUCT pTLS = (PTLSTRUCT)malloc(sizeof(TLSTRUCT)); LOGFONT lf; SIZE si; if (!pTLS) return -1L; memset(pTLS,0,sizeof(TLSTRUCT)); { RECT rcClient; GetClientRect(hwnd,&rcClient); pTLS->iOrigWidth = rcClient.right; pTLS->iOrigHeight = rcClient.bottom; } pTLS->cbSize = sizeof(TLSTRUCT); pTLS->iHSpace = 6; pTLS->bActive = TRUE; pTLS->iMouseX = -1; pTLS->iMouseY = -1; pTLS->iState = ITEMSTATE_COLD; if (TL_HAVE_TOOLTIP) { pTLS->hwndToolTip = CreateWindowEx(WS_EX_TOOLWINDOW|WS_EX_TOPMOST, TOOLTIPS_CLASS, NULL, WS_POPUP|TTS_NOPREFIX, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, hwnd, NULL, NULL, NULL); if (!pTLS->hwndToolTip) { free(pTLS); return -1L; } SetWindowPos(pTLS->hwndToolTip,HWND_TOPMOST,0,0,0,0,SWP_NOMOVE|SWP_NOSIZE|SWP_NOACTIVATE); ResizeTTControl(hwnd,pTLS); } pTLS->bEnabled = IsWindowEnabled(hwnd); if (!pTLS->bEnabled) pTLS->iState = ITEMSTATE_DISABLED; if (TL_HAVE_TOOLTIP_SAFE(pTLS)) SendMessage(pTLS->hwndToolTip,TTM_ACTIVATE,(WPARAM)((pTLS->bEnabled && pTLS->bActive) ? TRUE : FALSE),0L); pTLS->hBackground = CreateSolidBrush(GetSysColor(COLOR_3DFACE)); pTLS->crNormal = GetSysColor(COLOR_BTNTEXT); pTLS->crHot = GetSysColor(COLOR_HOTLIGHT); pTLS->crPressed = GetSysColor(COLOR_HOTLIGHT); pTLS->crDisabled = GetSysColor(COLOR_GRAYTEXT); if (GetLogFont((HFONT)GetStockObject(DEFAULT_GUI_FONT),&lf)) { lf.lfWeight = TL_HAVE_BOLD ? FW_BOLD : FW_NORMAL; lf.lfUnderline = TL_HAVE_NORMUNDERLINE ? TRUE : FALSE; pTLS->hFontNormal = CreateFontIndirect(&lf); lf.lfWeight = TL_HAVE_BOLD ? FW_BOLD : FW_NORMAL; lf.lfUnderline = TL_HAVE_HOTUNDERLINE ? TRUE : FALSE; pTLS->hFontHot = CreateFontIndirect(&lf); } SetWindowLong(hwnd,GWL_USERDATA,(LONG)pTLS); if (GetItemSize(hwnd,pTLS,&si,-1)) { SetWindowPos(hwnd,NULL,0,0,si.cx,si.cy,SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOOWNERZORDER|SWP_NOZORDER); ResizeTTControl(hwnd,pTLS); } return 0L; } case WM_DESTROY: { PTLSTRUCT pTLS = (PTLSTRUCT)GetWindowLong(hwnd,GWL_USERDATA); if ((pTLS) && (pTLS->cbSize==sizeof(TLSTRUCT))) { if (pTLS->hwndToolTip) DestroyWindow(pTLS->hwndToolTip); if (pTLS->hBackground) DeleteObject(pTLS->hBackground); if (pTLS->hFontNormal) DeleteObject(pTLS->hFontNormal); if (pTLS->hFontHot) DeleteObject(pTLS->hFontHot); free(pTLS); SetWindowLong(hwnd,GWL_USERDATA,(LONG)0L); } break; } case WM_SETFONT: { PTLSTRUCT pTLS = (PTLSTRUCT)GetWindowLong(hwnd,GWL_USERDATA); LOGFONT lf; SIZE si; if (!pTLS) return 0L; if (pTLS->hFontNormal) { DeleteObject(pTLS->hFontNormal); pTLS->hFontNormal = NULL; } if (pTLS->hFontHot) { DeleteObject(pTLS->hFontHot); pTLS->hFontHot = NULL; } if (GetLogFont( wParam ? ((HFONT)wParam) : ((HFONT)GetStockObject(DEFAULT_GUI_FONT)),&lf) ) { lf.lfWeight = TL_HAVE_BOLD ? FW_BOLD : FW_NORMAL; lf.lfUnderline = TL_HAVE_NORMUNDERLINE ? TRUE : FALSE; pTLS->hFontNormal = CreateFontIndirect(&lf); lf.lfWeight = TL_HAVE_BOLD ? FW_BOLD : FW_NORMAL; lf.lfUnderline = TL_HAVE_HOTUNDERLINE ? TRUE : FALSE; pTLS->hFontHot = CreateFontIndirect(&lf); if (GetItemSize(hwnd,pTLS,&si,-1)) { SetWindowPos(hwnd,NULL,0,0,si.cx,si.cy,SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOOWNERZORDER|SWP_NOZORDER|SWP_NOREDRAW); ResizeTTControl(hwnd,pTLS); } if (LOWORD(lParam)) InvalidateRect(hwnd,NULL,TRUE); } return 0L; } case TLM_SETFONTS: // wParam = HFONT (NULL=>GUIFont), lParam = not used { PTLSTRUCT pTLS = (PTLSTRUCT)GetWindowLong(hwnd,GWL_USERDATA); LOGFONT lf; SIZE si; if (!pTLS) return FALSE; if (pTLS->hFontNormal) { DeleteObject(pTLS->hFontNormal); pTLS->hFontNormal = NULL; } if (pTLS->hFontHot) { DeleteObject(pTLS->hFontHot); pTLS->hFontHot = NULL; } if (GetLogFont( wParam ? ((HFONT)wParam) : ((HFONT)GetStockObject(DEFAULT_GUI_FONT)),&lf) ) { lf.lfWeight = TL_HAVE_BOLD ? FW_BOLD : FW_NORMAL; lf.lfUnderline = TL_HAVE_NORMUNDERLINE ? TRUE : FALSE; pTLS->hFontNormal = CreateFontIndirect(&lf); lf.lfWeight = TL_HAVE_BOLD ? FW_BOLD : FW_NORMAL; lf.lfUnderline = TL_HAVE_HOTUNDERLINE ? TRUE : FALSE; pTLS->hFontHot = CreateFontIndirect(&lf); if (GetItemSize(hwnd,pTLS,&si,-1)) { SetWindowPos(hwnd,NULL,0,0,si.cx,si.cy,SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOOWNERZORDER|SWP_NOZORDER|SWP_NOREDRAW); ResizeTTControl(hwnd,pTLS); } } return TRUE; } case TLM_SETCOLORS: // wParam = pointer to COLORREF[5], lParam = not used { PTLSTRUCT pTLS = (PTLSTRUCT)GetWindowLong(hwnd,GWL_USERDATA); SIZE si; if (!pTLS) return FALSE; if (IsBadReadPtr((CONST VOID *)wParam,sizeof(COLORREF)*5)) // return to original colors { if (pTLS->hBackground) { DeleteObject(pTLS->hBackground); pTLS->hBackground = NULL; } pTLS->hBackground = CreateSolidBrush(GetSysColor(COLOR_3DFACE)); pTLS->crNormal = GetSysColor(COLOR_BTNTEXT); pTLS->crHot = GetSysColor(COLOR_HOTLIGHT); pTLS->crPressed = GetSysColor(COLOR_HOTLIGHT); pTLS->crDisabled = GetSysColor(COLOR_GRAYTEXT); pTLS->bColorSet = FALSE; return TRUE; } if (pTLS->hBackground) { DeleteObject(pTLS->hBackground); pTLS->hBackground = NULL; } pTLS->bColorSet = TRUE; pTLS->hBackground = CreateSolidBrush( ((COLORREF*)wParam)[0] ); pTLS->crNormal = ((COLORREF*)wParam)[1]; pTLS->crHot = ((COLORREF*)wParam)[2]; pTLS->crPressed = ((COLORREF*)wParam)[3]; pTLS->crDisabled = ((COLORREF*)wParam)[4]; if (GetItemSize(hwnd,pTLS,&si,-1)) { SetWindowPos(hwnd,NULL,0,0,si.cx,si.cy,SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOOWNERZORDER|SWP_NOZORDER|SWP_NOREDRAW); ResizeTTControl(hwnd,pTLS); } return TRUE; } case TLM_SETIMAGES: // wParam = idx, lParam = HIMAGELIST[3] { PTLSTRUCT pTLS = (PTLSTRUCT)GetWindowLong(hwnd,GWL_USERDATA); SIZE si; if (IsBadReadPtr((CONST VOID *)lParam,sizeof(HIMAGELIST)*3)) return FALSE; if (!pTLS) return FALSE; pTLS->iIndex = (int)wParam; pTLS->hIListNormal = ((HIMAGELIST*)lParam)[0]; pTLS->hIListHot = ((HIMAGELIST*)lParam)[1]; pTLS->hIListDisabled = ((HIMAGELIST*)lParam)[2]; if (GetItemSize(hwnd,pTLS,&si,-1)) { SetWindowPos(hwnd,NULL,0,0,si.cx,si.cy,SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOOWNERZORDER|SWP_NOZORDER|SWP_NOREDRAW); ResizeTTControl(hwnd,pTLS); } return TRUE; } case TLM_GETTTCTRL: { PTLSTRUCT pTLS = (PTLSTRUCT)GetWindowLong(hwnd,GWL_USERDATA); if (!pTLS) return (LPARAM)NULL; return (LPARAM)pTLS->hwndToolTip; } case TLM_SETCURSOR: // wParam = HCURSOR(NULL=standard) { PTLSTRUCT pTLS = (PTLSTRUCT)GetWindowLong(hwnd,GWL_USERDATA); if (!pTLS) return FALSE; pTLS->hCursor = (HCURSOR)wParam; if (!pTLS->hCursor) pTLS->hCursor = LoadCursor(NULL,IDC_HAND); return TRUE; } case WM_NCHITTEST: { PTLSTRUCT pTLS = (PTLSTRUCT)GetWindowLong(hwnd,GWL_USERDATA); POINT pt; RECT rcClient; if (!pTLS) break; GetHitTestRect(hwnd,pTLS,&rcClient); pt.x = (int)((short)LOWORD(lParam)); pt.y = (int)((short)HIWORD(lParam)); ScreenToClient(hwnd,&pt); if (PtInRect(&rcClient,pt)) return HTCLIENT; else return HTNOWHERE; } case WM_SETCURSOR: { PTLSTRUCT pTLS = (PTLSTRUCT)GetWindowLong(hwnd,GWL_USERDATA); if (!pTLS) return FALSE; if (!pTLS->bActive) break; if (LOWORD(lParam)==HTCLIENT) SetCursor(pTLS->hCursor ? pTLS->hCursor : LoadCursor(NULL,IDC_HAND)); else SetCursor(LoadCursor(NULL,IDC_ARROW)); return TRUE; } case WM_ERASEBKGND: return TRUE; case TLM_SETHSPACE: // wParam = HSPACE { PTLSTRUCT pTLS = (PTLSTRUCT)GetWindowLong(hwnd,GWL_USERDATA); SIZE si; if (!pTLS) return FALSE; pTLS->iHSpace = (int)wParam; if (GetItemSize(hwnd,pTLS,&si,-1)) { SetWindowPos(hwnd,NULL,0,0,si.cx,si.cy,SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOOWNERZORDER|SWP_NOZORDER|SWP_NOREDRAW); ResizeTTControl(hwnd,pTLS); } return TRUE; } case TLM_GETHSPACE: { PTLSTRUCT pTLS = (PTLSTRUCT)GetWindowLong(hwnd,GWL_USERDATA); if (!pTLS) return (LRESULT)-1; return (LRESULT)pTLS->iHSpace; } case WM_SYSCOLORCHANGE: { PTLSTRUCT pTLS = (PTLSTRUCT)GetWindowLong(hwnd,GWL_USERDATA); if (!pTLS) return 0L; if (pTLS->bColorSet) return 0L; if (pTLS->hBackground) DeleteObject(pTLS->hBackground); pTLS->hBackground = CreateSolidBrush(GetSysColor(COLOR_3DFACE)); pTLS->crNormal = GetSysColor(COLOR_BTNTEXT); pTLS->crHot = GetSysColor(COLOR_HOTLIGHT); pTLS->crPressed = GetSysColor(COLOR_HOTLIGHT); pTLS->crDisabled = GetSysColor(COLOR_GRAYTEXT); return 0L; } case WM_SIZE: { PTLSTRUCT pTLS = (PTLSTRUCT)GetWindowLong(hwnd,GWL_USERDATA); SIZE si; if (!pTLS) return FALSE; GetItemSize(hwnd,pTLS,&si,-1); break; } case WM_CALCDIMENSIONS: // wParam = LPSIZE, lParam = width of control in px (-1 = get current width) { PTLSTRUCT pTLSSave,pTLS = (PTLSTRUCT)GetWindowLong(hwnd,GWL_USERDATA); BOOL bReturn; if (!pTLS) return FALSE; if (IsBadWritePtr((VOID *)wParam,sizeof(SIZE))) return FALSE; pTLSSave = (PTLSTRUCT)malloc(sizeof(TLSTRUCT)); if (!pTLSSave) return FALSE; memcpy(pTLSSave,pTLS,sizeof(TLSTRUCT)); bReturn = GetItemSize(hwnd,pTLS,(PSIZE)wParam,(int)lParam); memcpy(pTLS,pTLSSave,sizeof(TLSTRUCT)); return bReturn; } case WM_ENABLE: { PTLSTRUCT pTLS = (PTLSTRUCT)GetWindowLong(hwnd,GWL_USERDATA); if (!pTLS) return 0L; pTLS->bEnabled = (wParam ? TRUE : FALSE); CheckNeedRepaint(hwnd,pTLS); if (TL_HAVE_TOOLTIP_SAFE(pTLS)) SendMessage(pTLS->hwndToolTip,TTM_ACTIVATE,(WPARAM)((pTLS->bEnabled && pTLS->bActive) ? TRUE : FALSE),0L); return 0L; } case TLM_ACTIVATE: // wParam = BOOL { PTLSTRUCT pTLS = (PTLSTRUCT)GetWindowLong(hwnd,GWL_USERDATA); if (!pTLS) return 0L; pTLS->bActive = (BOOL)wParam; if (!pTLS->bActive) { if (pTLS->bEnabled) { pTLS->iState = ITEMSTATE_COLD; pTLS->bLButtonDown = FALSE; pTLS->iMouseX = -1; pTLS->iMouseY = -1; InvalidateRect(hwnd,NULL,TRUE); } } if (TL_HAVE_TOOLTIP_SAFE(pTLS)) SendMessage(pTLS->hwndToolTip,TTM_ACTIVATE,(WPARAM)((pTLS->bEnabled && pTLS->bActive) ? TRUE : FALSE),0L); return 0L; } case WM_KEYDOWN: { PTLSTRUCT pTLS = (PTLSTRUCT)GetWindowLong(hwnd,GWL_USERDATA); if (!pTLS) return 0L; if ((wParam==VK_SPACE) && (pTLS->bFocus) && (pTLS->bEnabled) && (pTLS->bActive) && (GetCapture()!=hwnd)) { pTLS->bKeyDown = TRUE; CheckNeedRepaint(hwnd,pTLS); } return 0L; } case WM_KEYUP: { PTLSTRUCT pTLS = (PTLSTRUCT)GetWindowLong(hwnd,GWL_USERDATA); if (!pTLS) return 0L; if ((wParam==VK_SPACE) && (pTLS->bFocus) && (pTLS->bEnabled) && (pTLS->bActive) && (pTLS->bKeyDown)) { pTLS->bKeyDown = FALSE; CheckNeedRepaint(hwnd,pTLS); if (pTLS->bEnabled) { if (TL_HAVE_PLAYSOUND) PlaySoundThemeSound(TEXT("Explorer\\Navigating")); SendMessage(GetParent(hwnd),WM_COMMAND,(WPARAM)GetWindowLong(hwnd,GWL_ID),(LPARAM)hwnd); } } return 0L; } case WM_LBUTTONDOWN: { PTLSTRUCT pTLS = (PTLSTRUCT)GetWindowLong(hwnd,GWL_USERDATA); if (!pTLS) return 0L; if ((!pTLS->bActive) || (!pTLS->bEnabled)) return 0L; pTLS->iMouseX = (int)((short)LOWORD(lParam)); pTLS->iMouseY = (int)((short)HIWORD(lParam)); pTLS->bLButtonDown = TRUE; if ((!TL_HAVE_NSFOC) && (pTLS->bEnabled)) SetFocus(hwnd); SetCapture(hwnd); CheckNeedRepaint(hwnd,pTLS); return 0L; } case WM_LBUTTONUP: { PTLSTRUCT pTLS = (PTLSTRUCT)GetWindowLong(hwnd,GWL_USERDATA); RECT rcClient; POINT pt; if (!pTLS) return 0L; if ((!pTLS->bActive) || (!pTLS->bEnabled)) return 0L; pTLS->iMouseX = (int)((short)LOWORD(lParam)); pTLS->iMouseY = (int)((short)HIWORD(lParam)); if (pTLS->bLButtonDown) { pTLS->bLButtonDown = FALSE; CheckNeedRepaint(hwnd,pTLS); pt.x = pTLS->iMouseX; pt.y = pTLS->iMouseY; GetClientRect(hwnd,&rcClient); if (PtInRect(&rcClient,pt)) { ReleaseCapture(); if ((pTLS->bEnabled) /*&& (pTLS->iState==ITEMSTATE_HOT)*/) { if (TL_HAVE_PLAYSOUND) PlaySoundThemeSound(TEXT("Explorer\\Navigating")); SendMessage(GetParent(hwnd),WM_COMMAND,(WPARAM)GetWindowLong(hwnd,GWL_ID),(LPARAM)hwnd); } } else ReleaseCapture(); } return 0L; } case WM_MOUSELEAVE: { PTLSTRUCT pTLS = (PTLSTRUCT)GetWindowLong(hwnd,GWL_USERDATA); if (!pTLS) return 0L; pTLS->iMouseX = -1; pTLS->iMouseY = -1; pTLS->bTrackMouse = FALSE; CheckNeedRepaint(hwnd,pTLS); return 0L; } case WM_MOUSEMOVE: { PTLSTRUCT pTLS = (PTLSTRUCT)GetWindowLong(hwnd,GWL_USERDATA); TRACKMOUSEEVENT tme; if (!pTLS) return 0L; if ((!pTLS->bActive) || (!pTLS->bEnabled)) return 0L; if (!pTLS->bTrackMouse) { pTLS->bTrackMouse = TRUE; tme.cbSize = sizeof(TRACKMOUSEEVENT); tme.dwFlags = TME_LEAVE; tme.dwHoverTime = 0; tme.hwndTrack = hwnd; TrackMouseEvent(&tme); } pTLS->iMouseX = (int)((short)LOWORD(lParam)); pTLS->iMouseY = (int)((short)HIWORD(lParam)); CheckNeedRepaint(hwnd,pTLS); return 0L; } case WM_SETFOCUS: { PTLSTRUCT pTLS = (PTLSTRUCT)GetWindowLong(hwnd,GWL_USERDATA); if (!pTLS) break; pTLS->bFocus = TRUE; if (TL_HAVE_FOCUSRECT) { InvalidateRect(hwnd,NULL,TRUE); return 0L; } else break; } case WM_KILLFOCUS: { PTLSTRUCT pTLS = (PTLSTRUCT)GetWindowLong(hwnd,GWL_USERDATA); if (!pTLS) break; pTLS->bFocus = FALSE; pTLS->bKeyDown = FALSE; if (TL_HAVE_FOCUSRECT) { InvalidateRect(hwnd,NULL,TRUE); return 0L; } else break; } case WM_CAPTURECHANGED: { PTLSTRUCT pTLS = (PTLSTRUCT)GetWindowLong(hwnd,GWL_USERDATA); if (!pTLS) return 0L; pTLS->bLButtonDown = FALSE; pTLS->bTrackMouse = FALSE; pTLS->iMouseX = -1; pTLS->iMouseY = -1; CheckNeedRepaint(hwnd,pTLS); return 0L; } case WM_NOTIFY: { int idCtrl = (int)wParam; LPNMHDR lpnmh = (LPNMHDR)lParam; PTLSTRUCT pTLS = (PTLSTRUCT)GetWindowLong(hwnd,GWL_USERDATA); HWND hwndOrig; UINT idOrig; if (!pTLS) break; if ((lpnmh->hwndFrom==pTLS->hwndToolTip) && (lpnmh->code==TTN_GETDISPINFO)) { LPNMTTDISPINFO lpnmttdi = (LPNMTTDISPINFO)lParam; hwndOrig = lpnmh->hwndFrom; idOrig = lpnmh->idFrom; lpnmh->hwndFrom = hwnd; lpnmh->idFrom = GetWindowLong(hwnd,GWL_ID); lpnmh->code = TLN_GETDISPINFO; SendMessage(GetParent(hwnd),WM_NOTIFY,(WPARAM)hwnd,(LPARAM)lpnmh); lpnmh->hwndFrom = hwndOrig; lpnmh->idFrom = idOrig; lpnmh->code = TTN_GETDISPINFO; return 0L; } break; } case WM_PAINT: { PTLSTRUCT pTLS = (PTLSTRUCT)GetWindowLong(hwnd,GWL_USERDATA); PAINTSTRUCT ps; HDC hDC; POINT pt = { 0,0 }; if (!pTLS) return 0L; hDC = BeginPaint(hwnd,&ps); if (hDC) TaskLinkPaintDC(hwnd,hDC,pt,TRUE,-1); EndPaint(hwnd,&ps); return 0L; } case WM_PRINTCLIENT: { HDC hDC = (HDC)wParam; UINT uFlags = (UINT)lParam; POINT pt = {0,0}; if (hDC) { if (!((!IsWindowVisible(hwnd)) && (uFlags & PRF_CHECKVISIBLE))) TaskLinkPaintDC(hwnd,hDC,pt,uFlags & PRF_ERASEBKGND ? TRUE : FALSE,-1); return TRUE; } return FALSE; } default: break; } return DefWindowProc(hwnd,uMsg,wParam,lParam); } void APIENTRY TaskLinkPaintDC ( HWND hwnd, HDC hDC, POINT ptOffset, BOOL bPaintBackground, int iCtrlWidth ) { PTLSTRUCT pTLS = (PTLSTRUCT)GetWindowLong(hwnd,GWL_USERDATA); TLSTRUCT TLSSave; TCHAR szText[256]; HGDIOBJ hOldFont; int iOldColor,iOldBkMode; RECT rcText,rcClient; LONG lStyle = GetWindowLong(hwnd,GWL_STYLE); LONG lExStyle = GetWindowLong(hwnd,GWL_EXSTYLE); UINT uDTStyle = 0; HDC hDCMem; HBITMAP hOldBitmap,hBitmapMem; HBRUSH hBackBrush; if (!pTLS) return; if (iCtrlWidth!=-1) { SIZE si; memcpy(&TLSSave,pTLS,sizeof(TLSTRUCT)); GetItemSize(hwnd,pTLS,&si,iCtrlWidth); rcClient.left = rcClient.top = 0; rcClient.right = si.cx; rcClient.bottom = si.cy; } else GetClientRect(hwnd,&rcClient); hDCMem = CreateCompatibleDC(hDC); hBitmapMem = CreateCompatibleBitmap(hDC,rcClient.right,rcClient.bottom); if ((hDCMem) && (hBitmapMem)) { hOldBitmap = SelectObject(hDCMem,hBitmapMem); if (lExStyle & WS_EX_RIGHT) { lStyle |= TLS_ICONRIGHT; if ((lStyle & TLS_HALIGNMASK)==TLS_LEFT) lStyle = (lStyle & ~TLS_HALIGNMASK)|TLS_RIGHT; else if ((lStyle & TLS_HALIGNMASK)==TLS_RIGHT) lStyle = (lStyle & ~TLS_HALIGNMASK)|TLS_LEFT; } if (bPaintBackground) { hBackBrush = (HBRUSH)SendMessage(GetParent(hwnd),WM_CTLCOLORSTATIC,(WPARAM)hDCMem,(LPARAM)hwnd); if (((ULONG)(hBackBrush))>1) FillRect(hDCMem,&rcClient,hBackBrush); } else BitBlt(hDCMem,0,0,rcClient.right,rcClient.bottom,hDC,ptOffset.x,ptOffset.y,SRCCOPY); switch(pTLS->iState) { case ITEMSTATE_COLD: hOldFont = SelectObject(hDCMem,pTLS->hFontNormal); iOldColor = SetTextColor(hDCMem,pTLS->crNormal); break; case ITEMSTATE_PRESSED: hOldFont = SelectObject(hDCMem,pTLS->hFontHot); iOldColor = SetTextColor(hDCMem,pTLS->crPressed); break; case ITEMSTATE_HOT: hOldFont = SelectObject(hDCMem,pTLS->hFontHot); iOldColor = SetTextColor(hDCMem,pTLS->crHot); break; default: hOldFont = SelectObject(hDCMem,pTLS->hFontNormal); iOldColor = SetTextColor(hDCMem,pTLS->crDisabled); break; } iOldBkMode = SetBkMode(hDCMem,TRANSPARENT); if (pTLS->hIListNormal) { HIMAGELIST hIList; switch(pTLS->iState) { case ITEMSTATE_COLD: hIList = pTLS->hIListNormal; break; case ITEMSTATE_PRESSED: case ITEMSTATE_HOT: hIList = pTLS->hIListHot; break; default: hIList = pTLS->hIListDisabled; break; } if (!hIList) hIList = pTLS->hIListNormal; if (hIList) ImageList_Draw(hIList,pTLS->iIndex,hDCMem,pTLS->rcIcon.left,pTLS->rcIcon.top,ILD_TRANSPARENT); } szText[0]=0x00; GetWindowText(hwnd,szText,256); memcpy(&rcText,&pTLS->rcText,sizeof(RECT)); if (lStyle & TLS_FOCUSRECT) { if (pTLS->bFocus) DrawFocusRect(hDCMem,&rcText); rcText.left++; rcText.right--; rcText.top++; rcText.bottom--; } if (lStyle & TLS_WORDBREAK) // multiline, use current control width { if (pTLS->bMultiLine) uDTStyle = DT_EXTERNALLEADING|DT_WORDBREAK; else uDTStyle = DT_SINGLELINE|DT_NOCLIP; } else { if (lStyle & TLS_END_ELLIPSIS) // singleline, use current control width { uDTStyle = DT_END_ELLIPSIS|DT_SINGLELINE; } else // singleline, ignore current control width { uDTStyle = DT_SINGLELINE|DT_NOCLIP; } } if ((lStyle & TLS_HALIGNMASK)==TLS_LEFT) uDTStyle |= DT_LEFT; else if ((lStyle & TLS_HALIGNMASK)==TLS_RIGHT) uDTStyle |= DT_RIGHT; else if ((lStyle & TLS_HALIGNMASK)==TLS_CENTER) uDTStyle |= DT_CENTER; if ((lStyle & TLS_VALIGNMASK)==TLS_TOP) uDTStyle |= DT_TOP; else if ((lStyle & TLS_VALIGNMASK)==TLS_BOTTOM) uDTStyle |= DT_BOTTOM; else if ((lStyle & TLS_VALIGNMASK)==TLS_MIDDLE) uDTStyle |= DT_VCENTER; if (lExStyle & WS_EX_RTLREADING) uDTStyle |= DT_RTLREADING; DrawTextEx(hDCMem,szText,lstrlen(szText),&rcText,uDTStyle,NULL); SetBkMode(hDCMem,iOldBkMode); SetTextColor(hDCMem,iOldColor); SelectObject(hDCMem,hOldFont); BitBlt(hDC,ptOffset.x,ptOffset.y,rcClient.right,rcClient.bottom,hDCMem,0,0,SRCCOPY); SelectObject(hDCMem,hOldBitmap); } if (hBitmapMem) DeleteObject(hBitmapMem); if (hDCMem) DeleteDC(hDCMem); if (iCtrlWidth!=-1) memcpy(pTLS,&TLSSave,sizeof(TLSTRUCT)); }