windows-nt/Source/XPSP1/NT/admin/netui/liccpa/test/licsetup/ctls.c
2020-09-26 16:20:57 +08:00

504 lines
11 KiB
C

#define OEMRESOURCE // setting this gets OBM_ constants in windows.h
#include <windows.h>
#include "ctls.h"
#pragma hdrstop
#define MyModuleHandle GetModuleHandle( NULL )
#define MYASSERT(x)
#define MyFree(x) LocalFree( x )
PWSTR DuplicateString( PWSTR pszOriginal )
{
PWSTR pszCopy;
pszCopy = LocalAlloc( LPTR, ( 1 + lstrlenW( pszOriginal ) ) * sizeof( *pszOriginal ) );
if ( NULL != pszCopy )
{
lstrcpy( pszCopy, pszOriginal );
}
return pszCopy;
}
////////////////////////////////////////////
//
// Bitmap control
//
////////////////////////////////////////////
PCWSTR szBMPCLASS = L"_mybmp";
LRESULT
BmpClassWndProc(
IN HWND hwnd,
IN UINT msg,
IN WPARAM wParam,
IN LPARAM lParam
);
BOOL
InitializeBmpClass(
VOID
)
{
WNDCLASS wc;
BOOL b;
if(GetClassInfo(MyModuleHandle,szBMPCLASS,&wc)) {
b = TRUE;
} else {
wc.lpszClassName = szBMPCLASS;
wc.style = CS_GLOBALCLASS;
wc.lpfnWndProc = BmpClassWndProc;
wc.hInstance = MyModuleHandle;
wc.hIcon = NULL;
wc.hCursor = LoadCursor(NULL,IDC_ARROW);
wc.hbrBackground = NULL;
wc.lpszMenuName = NULL;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
b = RegisterClass(&wc);
}
return(b);
}
VOID
DestroyBmpClass(
VOID
)
{
WNDCLASS wc;
if(GetClassInfo(MyModuleHandle,szBMPCLASS,&wc)) {
//
// Hope there are no more windows using the class!
//
MYASSERT(!FindWindow(szBMPCLASS,NULL));
UnregisterClass(szBMPCLASS,MyModuleHandle);
}
}
VOID
BmpClassPaint(
IN HWND hwnd
)
{
PAINTSTRUCT ps;
unsigned BmpId;
HDC hdc, hdcMem;
HBITMAP hbm,hbmOld;
BITMAP bm;
BmpId = GetDlgCtrlID(hwnd);
hdc = BeginPaint(hwnd,&ps);
if(hbm = LoadBitmap((HINSTANCE)GetWindowLong(hwnd,GWL_HINSTANCE),MAKEINTRESOURCE(BmpId))) {
GetObject(hbm, sizeof(bm),&bm);
if(hdcMem = CreateCompatibleDC(hdc)) {
if(hbmOld = SelectObject(hdcMem,hbm)) {
BitBlt(hdc,0,0,bm.bmWidth,bm.bmHeight,hdcMem,0,0,SRCCOPY);
SelectObject(hdcMem,hbmOld);
}
DeleteDC(hdcMem);
}
DeleteObject(hbm);
}
EndPaint(hwnd,&ps);
}
LRESULT
BmpClassWndProc(
IN HWND hwnd,
IN UINT msg,
IN WPARAM wParam,
IN LPARAM lParam
)
{
switch(msg) {
case WM_NCCREATE:
SetWindowLong(
hwnd,
GWL_STYLE,
GetWindowLong(hwnd,GWL_STYLE) | WS_BORDER
);
return(TRUE);
case WM_PAINT:
BmpClassPaint(hwnd);
return(0);
}
return(DefWindowProc(hwnd,msg,wParam,lParam));
}
////////////////////////////////////////////
//
// Action item list control
//
////////////////////////////////////////////
//
// Define locations in extra window storage
//
#define AIL_FONT (0)
#define AIL_BOLDFONT (sizeof(LONG))
#define AIL_BOLDITEM (2*sizeof(LONG))
#define AIL_TEXT (3*sizeof(LONG))
#define AIL_LINECOUNT (4*sizeof(LONG))
#define AIL_FREEFONTS (5*sizeof(LONG))
#define AIL_EXTRA 6
PCWSTR szActionItemListClassName = L"$$$ActionItemList";
VOID
ActionItemListPaint(
IN HWND hwnd
)
{
PAINTSTRUCT PaintStruct;
PWSTR p,Text;
UINT LineCount;
HFONT OldFont,Font,BoldFont;
UINT HighlightedItem;
UINT i;
int Length;
int y;
int yDelta;
HBITMAP Bitmap,OldBitmap;
BITMAP bitmap;
HDC MemoryDC;
SIZE Size;
RECT rect;
int Spacing;
#define BORDER 3
if(!BeginPaint(hwnd,&PaintStruct)) {
return;
}
//
// If no text, nothing to do.
//
if(Text = (PWSTR)GetWindowLong(hwnd,AIL_TEXT)) {
LineCount = (UINT)GetWindowLong(hwnd,AIL_LINECOUNT);
}
if(!Text || !LineCount) {
return;
}
//
// Get value indicating which item is to be bolded.
//
HighlightedItem = (UINT)GetWindowLong(hwnd,AIL_BOLDITEM);
//
// Get font handles.
//
Font = (HFONT)GetWindowLong(hwnd,AIL_FONT);
BoldFont = (HFONT)GetWindowLong(hwnd,AIL_BOLDFONT);
//
// Select the non-boldface font to get the handle of
// the currently selected font.
//
OldFont = SelectObject(PaintStruct.hdc,Font);
//
// Set text background color.
//
SetBkColor(PaintStruct.hdc,GetSysColor(COLOR_3DFACE));
//
// Load the little triangle bitmap and create a compatible DC for it.
//
Bitmap = LoadBitmap(NULL,MAKEINTRESOURCE(OBM_MNARROW));
if(MemoryDC = CreateCompatibleDC(PaintStruct.hdc)) {
OldBitmap = SelectObject(MemoryDC,Bitmap);
GetObject(Bitmap,sizeof(BITMAP),&bitmap);
}
Spacing = GetSystemMetrics(SM_CXICON) / 2;
//
// Treat the text as a series of lines and draw each one.
//
p = Text;
y = 0;
for(i=0; i<LineCount; i++) {
//
// Calculate the line's height based on the boldface font.
// This is used to get to the y coord of the next line.
//
SelectObject(PaintStruct.hdc,BoldFont);
GetClientRect(hwnd,&rect);
rect.left = (2 * BORDER) + Spacing;
rect.bottom = 0;
DrawText(PaintStruct.hdc,p,lstrlen(p),&rect,DT_CALCRECT|DT_WORDBREAK);
yDelta = rect.bottom + (2*BORDER);
//
// Change font to non-boldface for this line if necessary.
//
if(i != HighlightedItem) {
SelectObject(PaintStruct.hdc,Font);
}
rect.top = y + BORDER;
rect.left = (2 * BORDER) + Spacing;
rect.bottom = rect.top + yDelta;
//
// Draw the line's text.
//
Length = lstrlen(p);
DrawText(PaintStruct.hdc,p,Length,&rect,DT_WORDBREAK);
//
// Draw the little triangle thing if necessary.
//
if((i == HighlightedItem) && Bitmap && MemoryDC) {
GetTextExtentPoint(PaintStruct.hdc,L"WWWWW",5,&Size);
BitBlt(
PaintStruct.hdc,
BORDER,
y + ((Size.cy - bitmap.bmHeight) / 2) + BORDER,
bitmap.bmWidth,
bitmap.bmHeight,
MemoryDC,
0,0,
0x220326 // (NOT src) AND dest [DSna]
);
}
//
// Point to next line's text.
//
p += Length + 1;
y += yDelta;
}
//
// Clean up.
//
if(OldFont) {
SelectObject(PaintStruct.hdc,OldFont);
}
if(MemoryDC) {
if(OldBitmap) {
SelectObject(MemoryDC,OldBitmap);
}
if(Bitmap) {
DeleteObject(Bitmap);
}
DeleteDC(MemoryDC);
}
EndPaint(hwnd,&PaintStruct);
}
LRESULT
ActionItemListWndProc(
IN HWND hwnd,
IN UINT msg,
IN WPARAM wParam,
IN LPARAM lParam
)
{
LRESULT rc;
HFONT OldFont,Font,BoldFont;
LOGFONT LogFont;
PWSTR Text;
PWSTR p;
UINT LineCount;
BOOL FreeFont,FreeBoldFont;
switch(msg) {
case WM_CREATE:
//
// Create fonts.
//
OldFont = (HFONT)SendMessage(GetParent(hwnd),WM_GETFONT,0,0);
if(!OldFont) {
//
// Using system font.
//
OldFont = GetStockObject(DEFAULT_GUI_FONT);
}
FreeFont = TRUE;
FreeBoldFont = TRUE;
if(OldFont && GetObject(OldFont,sizeof(LOGFONT),&LogFont)) {
LogFont.lfWeight = 400;
Font = CreateFontIndirect(&LogFont);
if(!Font) {
Font = GetStockObject(DEFAULT_GUI_FONT);
FreeFont = FALSE;
}
LogFont.lfWeight = 700;
BoldFont = CreateFontIndirect(&LogFont);
if(!BoldFont) {
BoldFont = Font;
FreeBoldFont = FALSE;
}
}
SetWindowLong(hwnd,AIL_FONT,(LONG)Font);
SetWindowLong(hwnd,AIL_BOLDFONT,(LONG)BoldFont);
SetWindowLong(hwnd,AIL_BOLDITEM,0);
SetWindowLong(hwnd,AIL_TEXT,0);
SetWindowLong(hwnd,AIL_LINECOUNT,0);
SetWindowLong(hwnd,AIL_FREEFONTS,MAKELONG(FreeFont,FreeBoldFont));
rc = 0;
break;
case WM_DESTROY:
//
// Get rid of fonts we created if necessary.
//
FreeFont = (BOOL)GetWindowLong(hwnd,AIL_FREEFONTS);
FreeBoldFont = HIWORD(FreeFont);
FreeFont = LOWORD(FreeFont);
if(FreeFont && (Font = (HFONT)GetWindowLong(hwnd,AIL_FONT))) {
DeleteObject(Font);
}
if(FreeBoldFont && (BoldFont = (HFONT)GetWindowLong(hwnd,AIL_BOLDFONT))) {
DeleteObject(BoldFont);
}
if(Text = (PWSTR)GetWindowLong(hwnd,AIL_TEXT)) {
MyFree(Text);
}
rc = 0;
break;
case WM_SETTEXT:
//
// Free old text and remember new text.
//
if(Text = (PWSTR)GetWindowLong(hwnd,AIL_TEXT)) {
MyFree(Text);
}
LineCount = 0;
if(Text = DuplicateString((PVOID)lParam)) {
//
// Count lines in the text. This is equal to the number of
// newlines. We require that the last line have a newline
// to be counted.
//
for(LineCount=0,p=Text; *p; p++) {
if(*p == L'\r') {
*p = L' ';
} else {
if(*p == L'\n') {
*p = 0;
LineCount++;
}
}
}
}
//
// Cheat a little: we expect wParam to be the 0-based index
// of the boldfaced line. Callers will have to use SendMessage
// instead of SetWindowText().
//
SetWindowLong(hwnd,AIL_BOLDITEM,(LONG)wParam);
SetWindowLong(hwnd,AIL_LINECOUNT,LineCount);
SetWindowLong(hwnd,AIL_TEXT,(LONG)Text);
rc = (Text != NULL);
break;
case WM_PAINT:
ActionItemListPaint(hwnd);
rc = 0;
break;
default:
rc = DefWindowProc(hwnd,msg,wParam,lParam);
break;
}
return(rc);
}
BOOL
RegisterActionItemListControl(
IN BOOL Init
)
{
WNDCLASS wc;
BOOL b;
static BOOL Registered;
if(Init) {
if(Registered) {
b = TRUE;
} else {
wc.style = CS_PARENTDC;
wc.lpfnWndProc = ActionItemListWndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = AIL_EXTRA * sizeof(LONG);
wc.hInstance = MyModuleHandle;
wc.hIcon = NULL;
wc.hCursor = LoadCursor(NULL,IDC_ARROW);
wc.hbrBackground = (HBRUSH)(COLOR_3DFACE + 1);
wc.lpszMenuName = NULL;
wc.lpszClassName = szActionItemListClassName;
if(b = (RegisterClass(&wc) != 0)) {
Registered = TRUE;
}
}
} else {
if(Registered) {
if(b = UnregisterClass(szActionItemListClassName,MyModuleHandle)) {
Registered = FALSE;
}
} else {
b = TRUE;
}
}
return(b);
}