|
|
1.1 ! root 1: /* ! 2: * LISTS.C ! 3: * ! 4: * This file implements a generalized multi-collumn listbox with a standard ! 5: * frame window. ! 6: */ ! 7: #include <windows.h> ! 8: #include <windowsx.h> ! 9: #include <string.h> ! 10: #include <stdlib.h> ! 11: #include "ddespy.h" ! 12: #include "globals.h" ! 13: #include "lists.h" ! 14: ! 15: int CompareItems(PSTR psz1, PSTR psz2, INT SortCol, INT cCols); ! 16: int CmpCols(PSTR psz1, PSTR psz2, INT SortCol); ! 17: void DrawLBItem(LPDRAWITEMSTRUCT lpdis); ! 18: long CALLBACK MCLBClientWndProc(HWND hwnd, UINT msg, WPARAM wParam, LONG lPAram); ! 19: ! 20: UINT cyHeading; ! 21: ! 22: HWND CreateMCLBFrame( ! 23: HWND hwndParent, ! 24: LPSTR lpszTitle, // frame title string ! 25: UINT dwStyle, // frame styles ! 26: HICON hIcon, ! 27: HBRUSH hbrBkgnd, // background for heading. ! 28: LPSTR lpszHeadings) // tab delimited list of headings. The number of ! 29: // headings indicate the number of collumns. ! 30: { ! 31: static BOOL fRegistered = FALSE; ! 32: MCLBCREATESTRUCT mclbcs; ! 33: ! 34: if (!fRegistered) { ! 35: WNDCLASS wc; ! 36: HDC hdc; ! 37: TEXTMETRIC tm; ! 38: ! 39: wc.style = WS_OVERLAPPED | CS_HREDRAW | CS_VREDRAW; ! 40: wc.lpfnWndProc = MCLBClientWndProc; ! 41: wc.cbClsExtra = 0; ! 42: wc.cbWndExtra = 4; ! 43: wc.hInstance = hInst; ! 44: wc.hIcon = hIcon; ! 45: wc.hCursor = NULL; ! 46: wc.hbrBackground = hbrBkgnd; ! 47: wc.lpszMenuName = NULL; ! 48: wc.lpszClassName = RefString(IDS_LISTCLASS); ! 49: RegisterClass(&wc); ! 50: ! 51: hdc = GetDC(GetDesktopWindow()); ! 52: GetTextMetrics(hdc, &tm); ! 53: cyHeading = tm.tmHeight; ! 54: ReleaseDC(GetDesktopWindow(), hdc); ! 55: ! 56: fRegistered = TRUE; ! 57: } ! 58: mclbcs.lpszHeadings = lpszHeadings; ! 59: ! 60: return(CreateWindow(RefString(IDS_LISTCLASS), lpszTitle, dwStyle, ! 61: CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, ! 62: hwndParent, NULL, hInst, (LPSTR)&mclbcs)); ! 63: } ! 64: ! 65: ! 66: LONG CALLBACK MCLBClientWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) ! 67: { ! 68: MCLBSTRUCT *pmclb; ! 69: RECT rc; ! 70: INT i; ! 71: ! 72: if (msg == WM_CREATE) { ! 73: PSTR psz; ! 74: MCLBCREATESTRUCT FAR *pcs; ! 75: ! 76: pcs = (MCLBCREATESTRUCT FAR *)((LPCREATESTRUCT)lParam)->lpCreateParams; ! 77: pmclb = (MCLBSTRUCT *)LocalAlloc(LPTR, sizeof(MCLBSTRUCT)); ! 78: psz = (PSTR)LocalAlloc(LPTR, _fstrlen(pcs->lpszHeadings) + 1); ! 79: _fstrcpy((LPSTR)psz, pcs->lpszHeadings); ! 80: pmclb->pszHeadings = psz; ! 81: pmclb->cCols = 1; ! 82: while ((psz = strchr(psz, '\t'))) { ! 83: pmclb->cCols++; ! 84: psz++; ! 85: } ! 86: pmclb->SortCol = 0; ! 87: SetWindowLong(hwnd, 0, (UINT)pmclb); ! 88: GetClientRect(hwnd, &rc); ! 89: pmclb->hwndLB = CreateWindow(RefString(IDS_LBOX), szNULL, MYLBSTYLE | WS_VISIBLE, ! 90: 0, 0, 0, 0, hwnd, (HMENU)pmclb->cCols, hInst, NULL); ! 91: return(pmclb->hwndLB ? 0 : -1); ! 92: } ! 93: ! 94: pmclb = (MCLBSTRUCT *)GetWindowLong(hwnd, 0); ! 95: ! 96: switch (msg) { ! 97: case WM_PAINT: ! 98: { ! 99: PAINTSTRUCT ps; ! 100: DRAWITEMSTRUCT dis; ! 101: ! 102: BeginPaint(hwnd, &ps); ! 103: SetBkMode(ps.hdc, TRANSPARENT); ! 104: dis.hwndItem = hwnd; ! 105: dis.hDC = ps.hdc; ! 106: GetClientRect(hwnd, &dis.rcItem); ! 107: dis.rcItem.bottom = dis.rcItem.top + cyHeading; ! 108: dis.CtlType = ODT_BUTTON; // hack to avoid erasure ! 109: dis.CtlID = pmclb->cCols; ! 110: dis.itemID = 0; ! 111: dis.itemAction = ODA_DRAWENTIRE; ! 112: dis.itemData = (UINT)(LPSTR)pmclb->pszHeadings; ! 113: dis.itemState = 0; ! 114: DrawLBItem(&dis); ! 115: EndPaint(hwnd, &ps); ! 116: } ! 117: break; ! 118: ! 119: case WM_SIZE: ! 120: MoveWindow(pmclb->hwndLB, 0, cyHeading, LOWORD(lParam), ! 121: HIWORD(lParam) - cyHeading, TRUE); ! 122: break; ! 123: ! 124: case WM_LBUTTONDOWN: ! 125: { ! 126: HWND hwndLB; ! 127: INT i; ! 128: ! 129: // determine which collumn the mouse landed and sort on that collumn. ! 130: ! 131: SendMessage(hwnd, WM_SETREDRAW, 0, 0); ! 132: GetClientRect(hwnd, &rc); ! 133: InflateRect(&rc, -1, -1); ! 134: pmclb->SortCol = LOWORD(lParam) * pmclb->cCols / (rc.right - rc.left); ! 135: hwndLB = CreateWindow(RefString(IDS_LBOX), szNULL, MYLBSTYLE, 1, cyHeading + 1, ! 136: rc.right - rc.left, rc.bottom - rc.top - cyHeading, ! 137: hwnd, (HMENU)pmclb->cCols, hInst, NULL); ! 138: for (i = (INT)SendMessage(pmclb->hwndLB, LB_GETCOUNT, 0, 0); i; i--) { ! 139: SendMessage(hwndLB, LB_ADDSTRING, 0, ! 140: SendMessage(pmclb->hwndLB, LB_GETITEMDATA, i - 1, 0)); ! 141: SendMessage(pmclb->hwndLB, LB_SETITEMDATA, i - 1, 0); ! 142: } ! 143: ShowWindow(hwndLB, SW_SHOW); ! 144: ShowWindow(pmclb->hwndLB, SW_HIDE); ! 145: DestroyWindow(pmclb->hwndLB); ! 146: pmclb->hwndLB = hwndLB; ! 147: SendMessage(hwnd, WM_SETREDRAW, 1, 0); ! 148: InvalidateRect(hwnd, NULL, FALSE); ! 149: } ! 150: break; ! 151: ! 152: case WM_DELETEITEM: ! 153: ! 154: if ((UINT)((LPDELETEITEMSTRUCT)lParam)->itemData) ! 155: LocalFree(LocalHandle((PVOID)((LPDELETEITEMSTRUCT)lParam)->itemData)); ! 156: break; ! 157: ! 158: case WM_MEASUREITEM: ! 159: ((LPMEASUREITEMSTRUCT)lParam)->itemHeight = cyHeading; ! 160: break; ! 161: ! 162: case WM_DRAWITEM: ! 163: GetClientRect(hwnd, &rc); ! 164: // This fudge makes the collumns line up with the heading. ! 165: ((LPDRAWITEMSTRUCT)lParam)->rcItem.right = rc.right; ! 166: DrawLBItem((LPDRAWITEMSTRUCT)lParam); ! 167: return(DefWindowProc(hwnd, msg, wParam, lParam)); ! 168: break; ! 169: ! 170: case WM_COMPAREITEM: ! 171: return(CompareItems((PSTR)((LPCOMPAREITEMSTRUCT)lParam)->itemData1, ! 172: (PSTR)((LPCOMPAREITEMSTRUCT)lParam)->itemData2, ! 173: pmclb->SortCol, ! 174: pmclb->cCols)); ! 175: break; ! 176: ! 177: case WM_DESTROY: ! 178: LocalFree(LocalHandle((PVOID)pmclb->pszHeadings)); ! 179: LocalFree(LocalHandle((PVOID)pmclb)); ! 180: break; ! 181: ! 182: case WM_CLOSE: ! 183: for (i = 0; i < IT_COUNT && (hwndTrack[i] != hwnd); i++) { ! 184: ; ! 185: } ! 186: pro.fTrack[i] = FALSE; ! 187: hwndTrack[i] = NULL; ! 188: SetFilters(); ! 189: DestroyWindow(hwnd); ! 190: break; ! 191: ! 192: default: ! 193: return(DefWindowProc(hwnd, msg, wParam, lParam)); ! 194: } ! 195: } ! 196: ! 197: ! 198: ! 199: ! 200: /* ! 201: * Make this return FALSE if addition not needed. ! 202: * ! 203: * if pszSearch != NULL, searches for pszSearch - collumns may contain ! 204: * wild strings - "*" ! 205: * If found, the string is removed from the LB. ! 206: * Adds pszReplace to LB. ! 207: */ ! 208: VOID AddMCLBText(PSTR pszSearch, PSTR pszReplace, HWND hwndLBFrame) ! 209: { ! 210: MCLBSTRUCT *pmclb; ! 211: INT lit; ! 212: PSTR psz; ! 213: ! 214: pmclb = (MCLBSTRUCT *)GetWindowLong(hwndLBFrame, 0); ! 215: ! 216: SendMessage(pmclb->hwndLB, WM_SETREDRAW, 0, 0); ! 217: if (pszSearch != NULL) { ! 218: lit = (INT)SendMessage(pmclb->hwndLB, LB_FINDSTRING, (WPARAM)-1, (LONG)(LPSTR)pszSearch); ! 219: if (lit >= 0) { ! 220: SendMessage(pmclb->hwndLB, LB_DELETESTRING, lit, 0); ! 221: } ! 222: } ! 223: psz = (PSTR)LocalAlloc(LPTR, strlen(pszReplace) + 1); ! 224: strcpy(psz, pszReplace); ! 225: SendMessage(pmclb->hwndLB, WM_SETREDRAW, 1, 0); ! 226: SendMessage(pmclb->hwndLB, LB_ADDSTRING, 0, (LONG)(LPSTR)psz); ! 227: } ! 228: ! 229: ! 230: /* ! 231: * This function assumes that the text in cCol is an ASCII number. 0 is ! 232: * returned if it is not found. ! 233: */ ! 234: INT GetMCLBColValue(PSTR pszSearch, HWND hwndLBFrame, INT cCol) ! 235: { ! 236: MCLBSTRUCT *pmclb; ! 237: PSTR psz; ! 238: INT lit; ! 239: ! 240: pmclb = (MCLBSTRUCT *)GetWindowLong(hwndLBFrame, 0); ! 241: ! 242: lit = (INT)SendMessage(pmclb->hwndLB, LB_FINDSTRING, (WPARAM)-1, (LONG)(LPSTR)pszSearch); ! 243: if (lit < 0) { ! 244: return(0); ! 245: } ! 246: psz = (PSTR)SendMessage(pmclb->hwndLB, LB_GETITEMDATA, lit, 0); ! 247: while (--cCol && (psz = strchr(psz, '\t') + 1)) { ! 248: ; ! 249: } ! 250: if (psz) { ! 251: return(atoi(psz)); ! 252: } else { ! 253: return(0); ! 254: } ! 255: } ! 256: ! 257: ! 258: ! 259: /* ! 260: * Returns fFoundAndRemoved ! 261: */ ! 262: BOOL DeleteMCLBText(PSTR pszSearch, HWND hwndLBFrame) ! 263: { ! 264: MCLBSTRUCT *pmclb; ! 265: INT lit; ! 266: ! 267: pmclb = (MCLBSTRUCT *)GetWindowLong(hwndLBFrame, 0); ! 268: lit = (INT)SendMessage(pmclb->hwndLB, LB_FINDSTRING, (WPARAM)-1, ! 269: (LONG)(LPSTR)pszSearch); ! 270: if (lit >= 0) { ! 271: SendMessage(pmclb->hwndLB, LB_DELETESTRING, lit, 0); ! 272: return(TRUE); ! 273: } ! 274: return(FALSE); ! 275: } ! 276: ! 277: ! 278: /* ! 279: * Returns >0 if item1 comes first, <0 if item2 comes first, 0 if ==. ! 280: */ ! 281: INT CompareItems(PSTR psz1, PSTR psz2, INT SortCol, INT cCols) ! 282: { ! 283: INT i, Col; ! 284: ! 285: i = CmpCols(psz1, psz2, SortCol); ! 286: if (i != 0) { ! 287: return(i); ! 288: } ! 289: for (Col = 0; Col < cCols; Col++) { ! 290: if (Col == SortCol) { ! 291: continue; ! 292: } ! 293: i = CmpCols(psz1, psz2, Col); ! 294: if (i != 0) { ! 295: return(i); ! 296: } ! 297: } ! 298: return(0); ! 299: } ! 300: ! 301: ! 302: INT CmpCols(PSTR psz1, PSTR psz2, INT SortCol) ! 303: { ! 304: PSTR psz, pszT1, pszT2; ! 305: INT iRet; ! 306: ! 307: while (SortCol--) { ! 308: psz = strchr(psz1, '\t'); ! 309: if (psz != NULL) { ! 310: psz1 = psz + 1; ! 311: } else { ! 312: psz1 = psz1 + strlen(psz1); ! 313: } ! 314: psz = strchr(psz2, '\t'); ! 315: if (psz != NULL) { ! 316: psz2 = psz + 1; ! 317: } else { ! 318: psz2 = psz2 + strlen(psz2); ! 319: } ! 320: } ! 321: pszT1 = strchr(psz1, '\t'); ! 322: pszT2 = strchr(psz2, '\t'); ! 323: ! 324: if (pszT1) { ! 325: *pszT1 = '\0'; ! 326: } ! 327: if (pszT2) { ! 328: *pszT2 = '\0'; ! 329: } ! 330: ! 331: if (!strcmp(RefString(IDS_WILD), psz1) || !strcmp(RefString(IDS_WILD), psz2)) { ! 332: iRet = 0; ! 333: } else { ! 334: iRet = strcmp(psz1, psz2); ! 335: } ! 336: ! 337: if (pszT1) { ! 338: *pszT1 = '\t'; ! 339: } ! 340: if (pszT2) { ! 341: *pszT2 = '\t'; ! 342: } ! 343: ! 344: return(iRet); ! 345: } ! 346: ! 347: ! 348: ! 349: VOID DrawLBItem(LPDRAWITEMSTRUCT lpdis) ! 350: { ! 351: RECT rcDraw; ! 352: INT cxSection; ! 353: PSTR psz, pszEnd; ! 354: ! 355: if (!lpdis->itemData) ! 356: return; ! 357: if ((lpdis->itemAction & ODA_DRAWENTIRE) || ! 358: ((lpdis->itemAction & ODA_SELECT) && ! 359: (lpdis->itemState & ODS_SELECTED))) { ! 360: rcDraw = lpdis->rcItem; ! 361: if (lpdis->CtlType != ODT_BUTTON) { // hack to avoid erasure ! 362: HBRUSH hbr; ! 363: ! 364: hbr = CreateSolidBrush(GetSysColor(COLOR_WINDOW)); ! 365: FillRect(lpdis->hDC, &lpdis->rcItem, hbr); ! 366: DeleteObject(hbr); ! 367: } ! 368: cxSection = (rcDraw.right - rcDraw.left) / lpdis->CtlID; ! 369: psz = (PSTR)(UINT)lpdis->itemData; ! 370: rcDraw.right = rcDraw.left + cxSection; ! 371: while (pszEnd = strchr(psz, '\t')) { ! 372: *pszEnd = '\0'; ! 373: DrawText(lpdis->hDC, psz, -1, &rcDraw, DT_LEFT); ! 374: OffsetRect(&rcDraw, cxSection, 0); ! 375: *pszEnd = '\t'; ! 376: psz = pszEnd + 1; ! 377: } ! 378: DrawText(lpdis->hDC, psz, -1, &rcDraw, DT_LEFT); ! 379: ! 380: if (lpdis->itemState & ODS_SELECTED) ! 381: InvertRect(lpdis->hDC, &lpdis->rcItem); ! 382: ! 383: if (lpdis->itemState & ODS_FOCUS) ! 384: DrawFocusRect(lpdis->hDC, &lpdis->rcItem); ! 385: ! 386: } else if (lpdis->itemAction & ODA_SELECT) { ! 387: ! 388: InvertRect(lpdis->hDC, &lpdis->rcItem); ! 389: ! 390: } else if (lpdis->itemAction & ODA_FOCUS) { ! 391: ! 392: DrawFocusRect(lpdis->hDC, &lpdis->rcItem); ! 393: ! 394: } ! 395: } ! 396: ! 397:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.