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 (iTextWidthAvailrcText.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.toprcIcon.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)); 
}