|
|
Microsoft Windows NT Build 511 (SDK Final Release) 07-24-1993
/*
* Bitmap.c
*
* Purpose:
* bitmap and listbox support functions for netwatch.exe
*
* Owner:
* MikeSart
*/
#define UNICODE 1
#include <windows.h>
#include <windowsx.h>
#include "netwatch.h"
#include "rcids.h"
/*
* function prototypes
*/
void DeleteBitmapLB(void);
/*
* globals
*/
DWORD rgbWindowColor = 0xFF000000; // variables for the current
DWORD rgbHiliteColor = 0xFF000000; // system color settings.
DWORD rgbWindowText = 0xFF000000; // on a WM_SYSCOLORCHANGE
DWORD rgbHiliteText = 0xFF000000; // we check to see if we need
DWORD rgbGrayText = 0xFF000000; // to reload our bitmap.
DWORD rgbDDWindow = 0xFF000000; //
DWORD rgbDDHilite = 0xFF000000; // 0xFF000000 is an invalid RGB
// an array of integers containing the tab stops, in pixels. The tab
// stops must be sorted in ascending order; back tabs are not allowed.
int rgTabs[] = { 2, 20, 38, 56, 74 };
// font style of font to use in listbox
typedef struct
{
int lfHeight;
int lfWeight;
BYTE lfItalic;
TCHAR lfFaceName[LF_FACESIZE];
} FONTSTYLE;
FONTSTYLE fontStyle = { 8, FW_NORMAL, 0, TEXT("MS Sans Serif") };
int dxbmpLB, dybmpLB; // dx and dy of listbox bmps
HDC hdcMemory = NULL; // hdc to hold listbox bitmaps (for speed)
HBITMAP hbmpOrigMemBmp = NULL; // original null bitmap in hdcMemory
HBITMAP hbmpLB = NULL; // cached listbox bitmaps
HFONT hfontLB = NULL; // hfont of LB
HWND hwndLB = NULL; // hwnd of LB
/*
* DeInitBmps
*
* Purpose:
* cleans up LB hfonts, hdc, and hbmps
*
* Arguments:
*
* Returns:
* hopefully
*/
VOID
DeInitBmps(VOID)
{
DeleteBitmapLB();
if(hdcMemory)
{
DeleteDC(hdcMemory);
hdcMemory = NULL;
}
if(hfontLB)
{
SetWindowFont(hwndLB, GetStockObject(SYSTEM_FONT), FALSE);
DeleteObject(hfontLB);
hfontLB = NULL;
}
}
/*
* SetLBFont
*
* Purpose:
* creates a font from the global fontStyle
* sets global hfontLB to new font and WM_SETFONTs
* the hwndLB to the new font
*
* Arguments:
*
* Returns:
* yep
*/
VOID
SetLBFont(VOID)
{
LOGFONT lf;
lf.lfHeight = fontStyle.lfHeight;
lf.lfWidth = 0;
lf.lfEscapement = 0;
lf.lfOrientation = 0;
lf.lfWeight = fontStyle.lfWeight;
lf.lfItalic = fontStyle.lfItalic;
lf.lfUnderline = 0;
lf.lfStrikeOut = 0;
lf.lfCharSet = ANSI_CHARSET;
lf.lfOutPrecision = OUT_DEFAULT_PRECIS;
lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
lf.lfQuality = DEFAULT_QUALITY;
lf.lfPitchAndFamily = DEFAULT_PITCH | FF_SWISS;
lstrcpy(lf.lfFaceName, fontStyle.lfFaceName);
hfontLB = CreateFontIndirect(&lf);
if(hfontLB)
SetWindowFont(hwndLB, hfontLB, FALSE);
}
/*
* InitBmps
*
* Purpose:
* inits listbox globals, creates listbox
*
* Arguments:
* HWND main hwnd of app (parent of LB)
*
* Returns:
* TRUE - success; FALSE - failed
*/
BOOL
InitBmps(HWND hwnd)
{
HDC hdcScreen;
HBITMAP hbmpTemp;
hdcScreen = GetDC(NULL);
if(!hdcScreen)
goto CantInit;
hdcMemory = CreateCompatibleDC(hdcScreen);
if(!hdcMemory)
goto ReleaseScreenDC;
hbmpTemp = CreateCompatibleBitmap(hdcMemory, 1, 1);
if(!hbmpTemp)
goto ReleaseMemDC;
hbmpOrigMemBmp = SelectObject(hdcMemory, hbmpTemp); // get hbmp of NULL
if(!hbmpOrigMemBmp) // bmp for hdcMemory
goto ReleaseMemDC; // for when we delete
SelectObject(hdcMemory, hbmpOrigMemBmp); // it later in life
DeleteObject(hbmpTemp);
ReleaseDC(NULL, hdcScreen);
SetRGBValues(); // set the global RGB values
LoadBitmapLB(); // load the bmps into hdcMemory
hwndLB = CreateWindow(TEXT("listbox"), NULL,
WS_CHILD | WS_VISIBLE | LBS_NOTIFY | LBS_NOINTEGRALHEIGHT |
WS_VSCROLL | LBS_WANTKEYBOARDINPUT | LBS_HASSTRINGS |
LBS_OWNERDRAWFIXED,
0, 0, 0, 0, hwnd, (HMENU)IDD_lstSHARES, ghInst, NULL);
SetLBFont(); // set the font of our listbox
return TRUE;
/* Error recovery exits */
ReleaseMemDC:
DeleteDC(hdcMemory);
hdcMemory = NULL;
ReleaseScreenDC:
ReleaseDC(NULL, hdcScreen);
CantInit:
return FALSE;
}
/*
* SetRGBValues
*
* Purpose:
* To set various system colors in static variables. Called at
* init time and when system colors change.
*
* Arguments:
*
* Returns:
* Yes
*/
VOID
SetRGBValues(VOID)
{
rgbWindowColor = GetSysColor(COLOR_WINDOW);
rgbHiliteColor = GetSysColor(COLOR_HIGHLIGHT);
rgbWindowText = GetSysColor(COLOR_WINDOWTEXT);
rgbHiliteText = GetSysColor(COLOR_HIGHLIGHTTEXT);
rgbGrayText = GetSysColor(COLOR_GRAYTEXT);
}
/*
* MeasureItem
*
* Purpose:
* called from msg WM_MEASUREITEM: returns max dy of listbox items
*
* Arguments:
* HWND hwnd of main window
* pmis measureitemstruct from WM_MEASUREITEM call
*
* Returns:
* uh huh
*/
VOID
MeasureItem(HANDLE hwnd, LPMEASUREITEMSTRUCT pmis)
{
HDC hDC = GetDC(hwnd);
HANDLE hFont = hfontLB;
TEXTMETRIC TM;
if(!hFont)
hFont = GetStockObject(SYSTEM_FONT);
hFont = SelectObject(hDC, hFont);
GetTextMetrics(hDC, &TM);
SelectObject(hDC, hFont);
ReleaseDC(hwnd, hDC);
// set the height to be max of (dyfont or dybitmap)
pmis->itemHeight = max(dybmpLB, TM.tmHeight);
}
/*
* OutTextFormat
*
* Purpose:
* to parse the string in the listbox and draw it accordingly:
* first char == chBOLD: line is bold
* first char == chUNDERLINE: line is underlined (can follow chBOLD)
* char == chTAB: go to next column in rgTabs
* '/001#': bitblt that numbered bitmap.
* otherwise, outtext the line
*
* Arguments:
* pDI from DrawItem from WM_DRAWITEM msg
*
* Returns:
* yessir
*/
VOID
OutTextFormat(LPDRAWITEMSTRUCT pDI)
{
static TCHAR szItem[60];
TCHAR *pch;
INT nT;
INT nTab = 0; // current tab we is on
HFONT hfDef = NULL;
HFONT hfOld = NULL; // bold or underlined font
TCHAR *pchBuff = NULL;
nT = (ListBox_GetTextLen(pDI->hwndItem, pDI->itemID) + 1) * sizeof(TCHAR);
if(nT == LB_ERR)
return;
// if our quick buffer is big enough
if(nT > (sizeof(szItem) / sizeof(TCHAR)))
{
pchBuff = GlobalAllocPtr(GHND, nT);
if(!pchBuff)
return;
pch = pchBuff;
}
else
{
pch = szItem;
}
//Get the text string for this item
ListBox_GetText(pDI->hwndItem, pDI->itemID, pch);
// erase background
ExtTextOut(pDI->hDC, 0, 0, ETO_OPAQUE, &pDI->rcItem, NULL, 0, NULL);
// underline or bold this line? Only check first & second char
if(*pch == chBOLD || *pch == chUNDERLINE)
{
LOGFONT lf;
hfOld = GetWindowFont(pDI->hwndItem);
if(!hfOld)
hfOld = GetStockObject(SYSTEM_FONT);
GetObject(hfOld, sizeof(lf), &lf);
if(*pch == chBOLD)
{
lf.lfWeight = FW_BOLD;
pch++;
}
if(*pch == chUNDERLINE)
{
lf.lfUnderline = TRUE;
pch++;
}
hfDef = CreateFontIndirect(&lf);
if(hfDef)
SelectObject(pDI->hDC, hfDef);
}
// selected or nonselected bmps?
nT = (ODS_SELECTED & pDI->itemState) ? (BMWIDTH * NUMBMPS) : 0;
// parse the string
for(; *pch; pch++)
{
TCHAR *pchT;
RECT rc;
if(*pch == chBITMAP) // do we have a bitmap?
{
++pch;
// draw the bitmap
BitBlt(pDI->hDC, pDI->rcItem.left + rgTabs[nTab],
pDI->rcItem.top, BMWIDTH, BMHEIGHT, hdcMemory,
nT + (int)(*pch - TEXT('0')) * BMWIDTH, 0, SRCCOPY);
continue;
}
if(*pch == chTAB) // move to next tabstop?
{
nTab++;
continue;
}
pchT = pch; // find end of the column of text
while(*pchT && (*pchT != chTAB))
pchT++;
// set rect to drawtext in
SetRect(&rc, pDI->rcItem.left + rgTabs[nTab], pDI->rcItem.top,
pDI->rcItem.right, pDI->rcItem.bottom);
// draw the text
ExtTextOut(pDI->hDC, rc.left, rc.top + 1, ETO_OPAQUE | ETO_CLIPPED,
&rc, pch, pchT - pch, NULL);
pch = pchT - 1; // move to end of this column
}
if(hfDef) // delete underline or bold font if we created it
{
SelectObject(pDI->hDC, hfOld);
DeleteObject(hfDef);
}
GlobalFreeNullPtr(pchBuff);
}
/*
* DrawItem
*
* Purpose:
* Handles WM_DRAWITEM for both drive and directory listboxes.
*
* Parameters:
* pDI LPDRAWITEMSTRUCT passed from the WM_DRAWITEM message.
*
* Return Value:
* ya
*/
VOID
DrawItem(LPDRAWITEMSTRUCT pDI)
{
COLORREF crText, crBack;
if((int)pDI->itemID < 0)
return;
if((ODA_DRAWENTIRE | ODA_SELECT) & pDI->itemAction)
{
if(pDI->itemState & ODS_SELECTED)
{
// Select the appropriate text colors
crText = SetTextColor(pDI->hDC, rgbHiliteText);
crBack = SetBkColor(pDI->hDC, rgbHiliteColor);
}
// parse and spit out bmps and text
OutTextFormat(pDI);
// Restore original colors if we changed them above.
if(pDI->itemState & ODS_SELECTED)
{
SetTextColor(pDI->hDC, crText);
SetBkColor(pDI->hDC, crBack);
}
}
if((ODA_FOCUS & pDI->itemAction) || (ODS_FOCUS & pDI->itemState))
DrawFocusRect(pDI->hDC, &pDI->rcItem);
}
/*
* RgbInvertRgb
*
* Purpose:
* To reverse the byte order of the RGB value (for file format
*
* Arguments:
*
* Returns:
* New color value (RGB to BGR)
*/
#define RgbInvertRgb(_rgbOld) \
(LONG)RGB(GetBValue(_rgbOld), GetGValue(_rgbOld), GetRValue(_rgbOld))
/*
* LoadAlterBitmap (mostly stolen from commdlg)
*
* Purpose:
* Loads the IDB_LB bitmap and gives all the pixels that are
* RGBREPLACE a new color.
*
* Assumption:
* This function will work on one bitmap during it's lifetime.
* (Due to the fact that it finds RGBREPLACE once and then
* operates on that offset whenever called again because under NT,
* it appears that the bitmap is cached, so the second time you go
* looking for RGBREPLACE, it won't be found.) You could load the
* resource, copy it, then modify the copy as a workaround. But I
* chose the cheap way out as I will only ever modify one bmp.
*
* Arguments:
* rgbInstead rgb value to replace defined RGBREPLACE with
*
* Returns:
* NULL - failed or hbmp of new modified bitmap
*/
HBITMAP
LoadAlterBitmap(DWORD rgbInstead)
{
static WORD qlng = 0; // offset into color table
HANDLE hbmp = NULL;
LPBITMAPINFOHEADER qbihInfo;
HDC hdcScreen;
HANDLE hresLoad;
HANDLE hres;
LPBYTE qbBits;
DWORD rgbReplace;
// load our listbox bmps resource
hresLoad = FindResource(ghInst, MAKEINTRESOURCE(IDB_LB), RT_BITMAP);
if(hresLoad == NULL)
return NULL;
hres = LoadResource(ghInst, hresLoad);
if(hres == NULL)
return NULL;
rgbReplace = RgbInvertRgb(RGBREPLACE);
rgbInstead = RgbInvertRgb(rgbInstead);
qbihInfo = (LPBITMAPINFOHEADER)LockResource(hres);
// if we haven't found the color offset yet, find it
if(!qlng)
{
for(qlng = (WORD)qbihInfo->biSize; ; qlng += sizeof(DWORD))
{
if(*((LPBYTE)(qbihInfo) + qlng) == rgbReplace)
break;
}
}
// replace that color value with our new one
*(DWORD *)((LPBYTE)(qbihInfo) + qlng) = (DWORD)rgbInstead;
// Skip over the header structure
qbBits = (LPBYTE)(qbihInfo + 1);
// Skip the color table entries, if any
qbBits += (1 << (qbihInfo->biBitCount)) * sizeof(RGBQUAD);
// Create a color bitmap compatible with the display device
hdcScreen = GetDC(NULL);
if(hdcScreen != NULL)
{
hbmp = CreateDIBitmap(hdcScreen, qbihInfo, (LONG)CBM_INIT,
qbBits, (LPBITMAPINFO) qbihInfo, DIB_RGB_COLORS);
ReleaseDC(NULL, hdcScreen);
}
UnlockResource(hres);
FreeResource(hres);
return hbmp;
}
/*
* DeleteBitmapLB
*
* Purpose:
* Get rid of hbmpLB, if it exists
*
* Arguments:
*
* Returns:
* Si senor
*/
VOID
DeleteBitmapLB(VOID)
{
if(hbmpOrigMemBmp)
{
SelectObject(hdcMemory, hbmpOrigMemBmp);
if(hbmpLB != NULL)
{
DeleteObject(hbmpLB);
hbmpLB = NULL;
}
}
}
/*
* LoadBitmapLB (mostly stolen from commdlg)
*
* Purpose:
* Creates the listbox bitmap. If an appropriate bitmap
* already exists, it just returns immediately. Otherwise, it
* loads the bitmap and creates a larger bitmap with both regular
* and highlight colors.
*
* Arguments:
*
* Returns:
* TRUE - success; FALSE - failure
*/
BOOL
LoadBitmapLB(VOID)
{
BITMAP bmp;
HANDLE hbmp, hbmpOrig;
HDC hdcTemp;
BOOL bWorked = FALSE;
// check for existing bitmap and validity
if( (hbmpLB != NULL) &&
(rgbWindowColor == rgbDDWindow) &&
(rgbHiliteColor == rgbDDHilite))
{
if(SelectObject(hdcMemory, hbmpLB))
return TRUE;
}
DeleteBitmapLB();
rgbDDWindow = rgbWindowColor;
rgbDDHilite = rgbHiliteColor;
if(!(hdcTemp = CreateCompatibleDC(hdcMemory)))
goto LoadExit;
if(!(hbmp = LoadAlterBitmap(rgbWindowColor)))
goto DeleteTempDC;
GetObject(hbmp, sizeof(BITMAP), (LPBYTE) &bmp);
dybmpLB = bmp.bmHeight;
dxbmpLB = bmp.bmWidth;
hbmpOrig = SelectObject(hdcTemp, hbmp);
hbmpLB = CreateDiscardableBitmap(hdcTemp, dxbmpLB*2, dybmpLB);
if(!hbmpLB)
goto DeleteTempBmp;
if(!SelectObject(hdcMemory, hbmpLB))
{
DeleteBitmapLB();
goto DeleteTempBmp;
}
BitBlt(hdcMemory, 0, 0, dxbmpLB, dybmpLB, // copy unhighlited bmps
hdcTemp, 0, 0, SRCCOPY); // into hdcMemory
SelectObject(hdcTemp, hbmpOrig);
DeleteObject(hbmp);
if(!(hbmp = LoadAlterBitmap(rgbHiliteColor)))
goto DeleteTempDC;
hbmpOrig = SelectObject(hdcTemp, hbmp);
BitBlt(hdcMemory, dxbmpLB, 0, dxbmpLB, dybmpLB, // copy highlited bmps
hdcTemp, 0, 0, SRCCOPY); // into hdcMemory
SelectObject(hdcTemp, hbmpOrig);
bWorked = TRUE;
DeleteTempBmp:
DeleteObject(hbmp);
DeleteTempDC:
DeleteDC(hdcTemp);
LoadExit:
return bWorked;
}
void
BlitIcon(HDC hdc, LONG x, LONG y, int nBitmap)
{
if(hdcMemory)
{
BitBlt(hdc, x, y, BMWIDTH, BMHEIGHT, hdcMemory,
BMWIDTH * nBitmap, 0, SRCCOPY);
}
}
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.