|
|
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.