|
|
1.1 ! root 1: /* ! 2: * Bitmap.c ! 3: * ! 4: * Purpose: ! 5: * bitmap and listbox support functions for netwatch.exe ! 6: * ! 7: * Owner: ! 8: * MikeSart ! 9: */ ! 10: #define UNICODE 1 ! 11: ! 12: #include <windows.h> ! 13: #include <windowsx.h> ! 14: #include "netwatch.h" ! 15: #include "rcids.h" ! 16: ! 17: /* ! 18: * function prototypes ! 19: */ ! 20: void DeleteBitmapLB(void); ! 21: ! 22: /* ! 23: * globals ! 24: */ ! 25: DWORD rgbWindowColor = 0xFF000000; // variables for the current ! 26: DWORD rgbHiliteColor = 0xFF000000; // system color settings. ! 27: DWORD rgbWindowText = 0xFF000000; // on a WM_SYSCOLORCHANGE ! 28: DWORD rgbHiliteText = 0xFF000000; // we check to see if we need ! 29: DWORD rgbGrayText = 0xFF000000; // to reload our bitmap. ! 30: DWORD rgbDDWindow = 0xFF000000; // ! 31: DWORD rgbDDHilite = 0xFF000000; // 0xFF000000 is an invalid RGB ! 32: ! 33: // an array of integers containing the tab stops, in pixels. The tab ! 34: // stops must be sorted in ascending order; back tabs are not allowed. ! 35: int rgTabs[] = { 2, 20, 38, 56, 74 }; ! 36: ! 37: // font style of font to use in listbox ! 38: typedef struct ! 39: { ! 40: int lfHeight; ! 41: int lfWeight; ! 42: BYTE lfItalic; ! 43: TCHAR lfFaceName[LF_FACESIZE]; ! 44: } FONTSTYLE; ! 45: ! 46: FONTSTYLE fontStyle = { 8, FW_NORMAL, 0, TEXT("MS Sans Serif") }; ! 47: ! 48: int dxbmpLB, dybmpLB; // dx and dy of listbox bmps ! 49: ! 50: HDC hdcMemory = NULL; // hdc to hold listbox bitmaps (for speed) ! 51: ! 52: HBITMAP hbmpOrigMemBmp = NULL; // original null bitmap in hdcMemory ! 53: HBITMAP hbmpLB = NULL; // cached listbox bitmaps ! 54: ! 55: HFONT hfontLB = NULL; // hfont of LB ! 56: HWND hwndLB = NULL; // hwnd of LB ! 57: ! 58: /* ! 59: * DeInitBmps ! 60: * ! 61: * Purpose: ! 62: * cleans up LB hfonts, hdc, and hbmps ! 63: * ! 64: * Arguments: ! 65: * ! 66: * Returns: ! 67: * hopefully ! 68: */ ! 69: VOID ! 70: DeInitBmps(VOID) ! 71: { ! 72: DeleteBitmapLB(); ! 73: if(hdcMemory) ! 74: { ! 75: DeleteDC(hdcMemory); ! 76: hdcMemory = NULL; ! 77: } ! 78: ! 79: if(hfontLB) ! 80: { ! 81: SetWindowFont(hwndLB, GetStockObject(SYSTEM_FONT), FALSE); ! 82: DeleteObject(hfontLB); ! 83: hfontLB = NULL; ! 84: } ! 85: } ! 86: ! 87: /* ! 88: * SetLBFont ! 89: * ! 90: * Purpose: ! 91: * creates a font from the global fontStyle ! 92: * sets global hfontLB to new font and WM_SETFONTs ! 93: * the hwndLB to the new font ! 94: * ! 95: * Arguments: ! 96: * ! 97: * Returns: ! 98: * yep ! 99: */ ! 100: VOID ! 101: SetLBFont(VOID) ! 102: { ! 103: LOGFONT lf; ! 104: ! 105: lf.lfHeight = fontStyle.lfHeight; ! 106: lf.lfWidth = 0; ! 107: lf.lfEscapement = 0; ! 108: lf.lfOrientation = 0; ! 109: lf.lfWeight = fontStyle.lfWeight; ! 110: lf.lfItalic = fontStyle.lfItalic; ! 111: lf.lfUnderline = 0; ! 112: lf.lfStrikeOut = 0; ! 113: lf.lfCharSet = ANSI_CHARSET; ! 114: lf.lfOutPrecision = OUT_DEFAULT_PRECIS; ! 115: lf.lfClipPrecision = CLIP_DEFAULT_PRECIS; ! 116: lf.lfQuality = DEFAULT_QUALITY; ! 117: lf.lfPitchAndFamily = DEFAULT_PITCH | FF_SWISS; ! 118: lstrcpy(lf.lfFaceName, fontStyle.lfFaceName); ! 119: ! 120: hfontLB = CreateFontIndirect(&lf); ! 121: if(hfontLB) ! 122: SetWindowFont(hwndLB, hfontLB, FALSE); ! 123: } ! 124: ! 125: /* ! 126: * InitBmps ! 127: * ! 128: * Purpose: ! 129: * inits listbox globals, creates listbox ! 130: * ! 131: * Arguments: ! 132: * HWND main hwnd of app (parent of LB) ! 133: * ! 134: * Returns: ! 135: * TRUE - success; FALSE - failed ! 136: */ ! 137: BOOL ! 138: InitBmps(HWND hwnd) ! 139: { ! 140: HDC hdcScreen; ! 141: HBITMAP hbmpTemp; ! 142: ! 143: hdcScreen = GetDC(NULL); ! 144: if(!hdcScreen) ! 145: goto CantInit; ! 146: hdcMemory = CreateCompatibleDC(hdcScreen); ! 147: if(!hdcMemory) ! 148: goto ReleaseScreenDC; ! 149: ! 150: hbmpTemp = CreateCompatibleBitmap(hdcMemory, 1, 1); ! 151: if(!hbmpTemp) ! 152: goto ReleaseMemDC; ! 153: hbmpOrigMemBmp = SelectObject(hdcMemory, hbmpTemp); // get hbmp of NULL ! 154: if(!hbmpOrigMemBmp) // bmp for hdcMemory ! 155: goto ReleaseMemDC; // for when we delete ! 156: SelectObject(hdcMemory, hbmpOrigMemBmp); // it later in life ! 157: DeleteObject(hbmpTemp); ! 158: ReleaseDC(NULL, hdcScreen); ! 159: ! 160: SetRGBValues(); // set the global RGB values ! 161: LoadBitmapLB(); // load the bmps into hdcMemory ! 162: ! 163: hwndLB = CreateWindow(TEXT("listbox"), NULL, ! 164: WS_CHILD | WS_VISIBLE | LBS_NOTIFY | LBS_NOINTEGRALHEIGHT | ! 165: WS_VSCROLL | LBS_WANTKEYBOARDINPUT | LBS_HASSTRINGS | ! 166: LBS_OWNERDRAWFIXED, ! 167: 0, 0, 0, 0, hwnd, (HMENU)IDD_lstSHARES, ghInst, NULL); ! 168: ! 169: SetLBFont(); // set the font of our listbox ! 170: return TRUE; ! 171: ! 172: /* Error recovery exits */ ! 173: ReleaseMemDC: ! 174: DeleteDC(hdcMemory); ! 175: hdcMemory = NULL; ! 176: ! 177: ReleaseScreenDC: ! 178: ReleaseDC(NULL, hdcScreen); ! 179: ! 180: CantInit: ! 181: return FALSE; ! 182: } ! 183: ! 184: /* ! 185: * SetRGBValues ! 186: * ! 187: * Purpose: ! 188: * To set various system colors in static variables. Called at ! 189: * init time and when system colors change. ! 190: * ! 191: * Arguments: ! 192: * ! 193: * Returns: ! 194: * Yes ! 195: */ ! 196: VOID ! 197: SetRGBValues(VOID) ! 198: { ! 199: rgbWindowColor = GetSysColor(COLOR_WINDOW); ! 200: rgbHiliteColor = GetSysColor(COLOR_HIGHLIGHT); ! 201: rgbWindowText = GetSysColor(COLOR_WINDOWTEXT); ! 202: rgbHiliteText = GetSysColor(COLOR_HIGHLIGHTTEXT); ! 203: rgbGrayText = GetSysColor(COLOR_GRAYTEXT); ! 204: } ! 205: ! 206: /* ! 207: * MeasureItem ! 208: * ! 209: * Purpose: ! 210: * called from msg WM_MEASUREITEM: returns max dy of listbox items ! 211: * ! 212: * Arguments: ! 213: * HWND hwnd of main window ! 214: * pmis measureitemstruct from WM_MEASUREITEM call ! 215: * ! 216: * Returns: ! 217: * uh huh ! 218: */ ! 219: VOID ! 220: MeasureItem(HANDLE hwnd, LPMEASUREITEMSTRUCT pmis) ! 221: { ! 222: HDC hDC = GetDC(hwnd); ! 223: HANDLE hFont = hfontLB; ! 224: TEXTMETRIC TM; ! 225: ! 226: if(!hFont) ! 227: hFont = GetStockObject(SYSTEM_FONT); ! 228: hFont = SelectObject(hDC, hFont); ! 229: GetTextMetrics(hDC, &TM); ! 230: SelectObject(hDC, hFont); ! 231: ReleaseDC(hwnd, hDC); ! 232: ! 233: // set the height to be max of (dyfont or dybitmap) ! 234: pmis->itemHeight = max(dybmpLB, TM.tmHeight); ! 235: } ! 236: ! 237: /* ! 238: * OutTextFormat ! 239: * ! 240: * Purpose: ! 241: * to parse the string in the listbox and draw it accordingly: ! 242: * first char == chBOLD: line is bold ! 243: * first char == chUNDERLINE: line is underlined (can follow chBOLD) ! 244: * char == chTAB: go to next column in rgTabs ! 245: * '/001#': bitblt that numbered bitmap. ! 246: * otherwise, outtext the line ! 247: * ! 248: * Arguments: ! 249: * pDI from DrawItem from WM_DRAWITEM msg ! 250: * ! 251: * Returns: ! 252: * yessir ! 253: */ ! 254: VOID ! 255: OutTextFormat(LPDRAWITEMSTRUCT pDI) ! 256: { ! 257: static TCHAR szItem[60]; ! 258: TCHAR *pch; ! 259: INT nT; ! 260: INT nTab = 0; // current tab we is on ! 261: HFONT hfDef = NULL; ! 262: HFONT hfOld = NULL; // bold or underlined font ! 263: TCHAR *pchBuff = NULL; ! 264: ! 265: nT = (ListBox_GetTextLen(pDI->hwndItem, pDI->itemID) + 1) * sizeof(TCHAR); ! 266: if(nT == LB_ERR) ! 267: return; ! 268: ! 269: // if our quick buffer is big enough ! 270: if(nT > (sizeof(szItem) / sizeof(TCHAR))) ! 271: { ! 272: pchBuff = GlobalAllocPtr(GHND, nT); ! 273: if(!pchBuff) ! 274: return; ! 275: pch = pchBuff; ! 276: } ! 277: else ! 278: { ! 279: pch = szItem; ! 280: } ! 281: ! 282: //Get the text string for this item ! 283: ListBox_GetText(pDI->hwndItem, pDI->itemID, pch); ! 284: ! 285: // erase background ! 286: ExtTextOut(pDI->hDC, 0, 0, ETO_OPAQUE, &pDI->rcItem, NULL, 0, NULL); ! 287: ! 288: // underline or bold this line? Only check first & second char ! 289: if(*pch == chBOLD || *pch == chUNDERLINE) ! 290: { ! 291: LOGFONT lf; ! 292: ! 293: hfOld = GetWindowFont(pDI->hwndItem); ! 294: if(!hfOld) ! 295: hfOld = GetStockObject(SYSTEM_FONT); ! 296: GetObject(hfOld, sizeof(lf), &lf); ! 297: ! 298: if(*pch == chBOLD) ! 299: { ! 300: lf.lfWeight = FW_BOLD; ! 301: pch++; ! 302: } ! 303: if(*pch == chUNDERLINE) ! 304: { ! 305: lf.lfUnderline = TRUE; ! 306: pch++; ! 307: } ! 308: ! 309: hfDef = CreateFontIndirect(&lf); ! 310: if(hfDef) ! 311: SelectObject(pDI->hDC, hfDef); ! 312: } ! 313: ! 314: // selected or nonselected bmps? ! 315: nT = (ODS_SELECTED & pDI->itemState) ? (BMWIDTH * NUMBMPS) : 0; ! 316: ! 317: // parse the string ! 318: for(; *pch; pch++) ! 319: { ! 320: TCHAR *pchT; ! 321: RECT rc; ! 322: ! 323: if(*pch == chBITMAP) // do we have a bitmap? ! 324: { ! 325: ++pch; ! 326: // draw the bitmap ! 327: BitBlt(pDI->hDC, pDI->rcItem.left + rgTabs[nTab], ! 328: pDI->rcItem.top, BMWIDTH, BMHEIGHT, hdcMemory, ! 329: nT + (int)(*pch - TEXT('0')) * BMWIDTH, 0, SRCCOPY); ! 330: continue; ! 331: } ! 332: ! 333: if(*pch == chTAB) // move to next tabstop? ! 334: { ! 335: nTab++; ! 336: continue; ! 337: } ! 338: ! 339: pchT = pch; // find end of the column of text ! 340: while(*pchT && (*pchT != chTAB)) ! 341: pchT++; ! 342: ! 343: // set rect to drawtext in ! 344: SetRect(&rc, pDI->rcItem.left + rgTabs[nTab], pDI->rcItem.top, ! 345: pDI->rcItem.right, pDI->rcItem.bottom); ! 346: ! 347: // draw the text ! 348: ExtTextOut(pDI->hDC, rc.left, rc.top + 1, ETO_OPAQUE | ETO_CLIPPED, ! 349: &rc, pch, pchT - pch, NULL); ! 350: pch = pchT - 1; // move to end of this column ! 351: } ! 352: ! 353: if(hfDef) // delete underline or bold font if we created it ! 354: { ! 355: SelectObject(pDI->hDC, hfOld); ! 356: DeleteObject(hfDef); ! 357: } ! 358: ! 359: GlobalFreeNullPtr(pchBuff); ! 360: } ! 361: ! 362: /* ! 363: * DrawItem ! 364: * ! 365: * Purpose: ! 366: * Handles WM_DRAWITEM for both drive and directory listboxes. ! 367: * ! 368: * Parameters: ! 369: * pDI LPDRAWITEMSTRUCT passed from the WM_DRAWITEM message. ! 370: * ! 371: * Return Value: ! 372: * ya ! 373: */ ! 374: VOID ! 375: DrawItem(LPDRAWITEMSTRUCT pDI) ! 376: { ! 377: COLORREF crText, crBack; ! 378: ! 379: if((int)pDI->itemID < 0) ! 380: return; ! 381: ! 382: if((ODA_DRAWENTIRE | ODA_SELECT) & pDI->itemAction) ! 383: { ! 384: if(pDI->itemState & ODS_SELECTED) ! 385: { ! 386: // Select the appropriate text colors ! 387: crText = SetTextColor(pDI->hDC, rgbHiliteText); ! 388: crBack = SetBkColor(pDI->hDC, rgbHiliteColor); ! 389: } ! 390: ! 391: // parse and spit out bmps and text ! 392: OutTextFormat(pDI); ! 393: ! 394: // Restore original colors if we changed them above. ! 395: if(pDI->itemState & ODS_SELECTED) ! 396: { ! 397: SetTextColor(pDI->hDC, crText); ! 398: SetBkColor(pDI->hDC, crBack); ! 399: } ! 400: } ! 401: ! 402: if((ODA_FOCUS & pDI->itemAction) || (ODS_FOCUS & pDI->itemState)) ! 403: DrawFocusRect(pDI->hDC, &pDI->rcItem); ! 404: } ! 405: ! 406: /* ! 407: * RgbInvertRgb ! 408: * ! 409: * Purpose: ! 410: * To reverse the byte order of the RGB value (for file format ! 411: * ! 412: * Arguments: ! 413: * ! 414: * Returns: ! 415: * New color value (RGB to BGR) ! 416: */ ! 417: #define RgbInvertRgb(_rgbOld) \ ! 418: (LONG)RGB(GetBValue(_rgbOld), GetGValue(_rgbOld), GetRValue(_rgbOld)) ! 419: ! 420: /* ! 421: * LoadAlterBitmap (mostly stolen from commdlg) ! 422: * ! 423: * Purpose: ! 424: * Loads the IDB_LB bitmap and gives all the pixels that are ! 425: * RGBREPLACE a new color. ! 426: * ! 427: * Assumption: ! 428: * This function will work on one bitmap during it's lifetime. ! 429: * (Due to the fact that it finds RGBREPLACE once and then ! 430: * operates on that offset whenever called again because under NT, ! 431: * it appears that the bitmap is cached, so the second time you go ! 432: * looking for RGBREPLACE, it won't be found.) You could load the ! 433: * resource, copy it, then modify the copy as a workaround. But I ! 434: * chose the cheap way out as I will only ever modify one bmp. ! 435: * ! 436: * Arguments: ! 437: * rgbInstead rgb value to replace defined RGBREPLACE with ! 438: * ! 439: * Returns: ! 440: * NULL - failed or hbmp of new modified bitmap ! 441: */ ! 442: HBITMAP ! 443: LoadAlterBitmap(DWORD rgbInstead) ! 444: { ! 445: static WORD qlng = 0; // offset into color table ! 446: HANDLE hbmp = NULL; ! 447: LPBITMAPINFOHEADER qbihInfo; ! 448: HDC hdcScreen; ! 449: HANDLE hresLoad; ! 450: HANDLE hres; ! 451: LPBYTE qbBits; ! 452: DWORD rgbReplace; ! 453: ! 454: // load our listbox bmps resource ! 455: hresLoad = FindResource(ghInst, MAKEINTRESOURCE(IDB_LB), RT_BITMAP); ! 456: if(hresLoad == NULL) ! 457: return NULL; ! 458: hres = LoadResource(ghInst, hresLoad); ! 459: if(hres == NULL) ! 460: return NULL; ! 461: ! 462: rgbReplace = RgbInvertRgb(RGBREPLACE); ! 463: rgbInstead = RgbInvertRgb(rgbInstead); ! 464: qbihInfo = (LPBITMAPINFOHEADER)LockResource(hres); ! 465: ! 466: // if we haven't found the color offset yet, find it ! 467: if(!qlng) ! 468: { ! 469: for(qlng = (WORD)qbihInfo->biSize; ; qlng += sizeof(DWORD)) ! 470: { ! 471: if(*((LPBYTE)(qbihInfo) + qlng) == rgbReplace) ! 472: break; ! 473: } ! 474: } ! 475: ! 476: // replace that color value with our new one ! 477: *(DWORD *)((LPBYTE)(qbihInfo) + qlng) = (DWORD)rgbInstead; ! 478: ! 479: // Skip over the header structure ! 480: qbBits = (LPBYTE)(qbihInfo + 1); ! 481: ! 482: // Skip the color table entries, if any ! 483: qbBits += (1 << (qbihInfo->biBitCount)) * sizeof(RGBQUAD); ! 484: ! 485: // Create a color bitmap compatible with the display device ! 486: hdcScreen = GetDC(NULL); ! 487: if(hdcScreen != NULL) ! 488: { ! 489: hbmp = CreateDIBitmap(hdcScreen, qbihInfo, (LONG)CBM_INIT, ! 490: qbBits, (LPBITMAPINFO) qbihInfo, DIB_RGB_COLORS); ! 491: ReleaseDC(NULL, hdcScreen); ! 492: } ! 493: ! 494: UnlockResource(hres); ! 495: FreeResource(hres); ! 496: ! 497: return hbmp; ! 498: } ! 499: ! 500: /* ! 501: * DeleteBitmapLB ! 502: * ! 503: * Purpose: ! 504: * Get rid of hbmpLB, if it exists ! 505: * ! 506: * Arguments: ! 507: * ! 508: * Returns: ! 509: * Si senor ! 510: */ ! 511: VOID ! 512: DeleteBitmapLB(VOID) ! 513: { ! 514: if(hbmpOrigMemBmp) ! 515: { ! 516: SelectObject(hdcMemory, hbmpOrigMemBmp); ! 517: if(hbmpLB != NULL) ! 518: { ! 519: DeleteObject(hbmpLB); ! 520: hbmpLB = NULL; ! 521: } ! 522: } ! 523: } ! 524: ! 525: /* ! 526: * LoadBitmapLB (mostly stolen from commdlg) ! 527: * ! 528: * Purpose: ! 529: * Creates the listbox bitmap. If an appropriate bitmap ! 530: * already exists, it just returns immediately. Otherwise, it ! 531: * loads the bitmap and creates a larger bitmap with both regular ! 532: * and highlight colors. ! 533: * ! 534: * Arguments: ! 535: * ! 536: * Returns: ! 537: * TRUE - success; FALSE - failure ! 538: */ ! 539: BOOL ! 540: LoadBitmapLB(VOID) ! 541: { ! 542: BITMAP bmp; ! 543: HANDLE hbmp, hbmpOrig; ! 544: HDC hdcTemp; ! 545: BOOL bWorked = FALSE; ! 546: ! 547: // check for existing bitmap and validity ! 548: if( (hbmpLB != NULL) && ! 549: (rgbWindowColor == rgbDDWindow) && ! 550: (rgbHiliteColor == rgbDDHilite)) ! 551: { ! 552: if(SelectObject(hdcMemory, hbmpLB)) ! 553: return TRUE; ! 554: } ! 555: ! 556: DeleteBitmapLB(); ! 557: ! 558: rgbDDWindow = rgbWindowColor; ! 559: rgbDDHilite = rgbHiliteColor; ! 560: ! 561: if(!(hdcTemp = CreateCompatibleDC(hdcMemory))) ! 562: goto LoadExit; ! 563: ! 564: if(!(hbmp = LoadAlterBitmap(rgbWindowColor))) ! 565: goto DeleteTempDC; ! 566: ! 567: GetObject(hbmp, sizeof(BITMAP), (LPBYTE) &bmp); ! 568: dybmpLB = bmp.bmHeight; ! 569: dxbmpLB = bmp.bmWidth; ! 570: ! 571: hbmpOrig = SelectObject(hdcTemp, hbmp); ! 572: ! 573: hbmpLB = CreateDiscardableBitmap(hdcTemp, dxbmpLB*2, dybmpLB); ! 574: if(!hbmpLB) ! 575: goto DeleteTempBmp; ! 576: ! 577: if(!SelectObject(hdcMemory, hbmpLB)) ! 578: { ! 579: DeleteBitmapLB(); ! 580: goto DeleteTempBmp; ! 581: } ! 582: ! 583: BitBlt(hdcMemory, 0, 0, dxbmpLB, dybmpLB, // copy unhighlited bmps ! 584: hdcTemp, 0, 0, SRCCOPY); // into hdcMemory ! 585: SelectObject(hdcTemp, hbmpOrig); ! 586: ! 587: DeleteObject(hbmp); ! 588: ! 589: if(!(hbmp = LoadAlterBitmap(rgbHiliteColor))) ! 590: goto DeleteTempDC; ! 591: ! 592: hbmpOrig = SelectObject(hdcTemp, hbmp); ! 593: BitBlt(hdcMemory, dxbmpLB, 0, dxbmpLB, dybmpLB, // copy highlited bmps ! 594: hdcTemp, 0, 0, SRCCOPY); // into hdcMemory ! 595: SelectObject(hdcTemp, hbmpOrig); ! 596: ! 597: bWorked = TRUE; ! 598: ! 599: DeleteTempBmp: ! 600: DeleteObject(hbmp); ! 601: DeleteTempDC: ! 602: DeleteDC(hdcTemp); ! 603: LoadExit: ! 604: return bWorked; ! 605: } ! 606: ! 607: void ! 608: BlitIcon(HDC hdc, LONG x, LONG y, int nBitmap) ! 609: { ! 610: if(hdcMemory) ! 611: { ! 612: BitBlt(hdc, x, y, BMWIDTH, BMHEIGHT, hdcMemory, ! 613: BMWIDTH * nBitmap, 0, SRCCOPY); ! 614: } ! 615: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.