Annotation of mstools/samples/sdktools/ddespy/lists.c, revision 1.1.1.2

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.