home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
C Programming Starter Kit 2.0
/
SamsPublishing-CProgrammingStarterKit-v2.0-Win31.iso
/
bc45
/
truetype.pak
/
TRUETYPE.C
< prev
next >
Wrap
C/C++ Source or Header
|
1997-07-23
|
25KB
|
724 lines
// Borland C++ - (C) Copyright 1991, 1992 by Borland International
/*******************************************************************
program - TrueType.c
purpose - a Windows program to demo True Type fonts.
This program shows off two features of Windows 3.1: True Type
fonts, and common dialogs.
True Type fonts are scalable fonts supplied by the system. This
program demonstrates resizing and rotation of True Type characters
within a window, and allows the user to select the True Type font to
be used.
The dialog used in selecting the font is a Windows 3.1 "common
dialog." By including commdlg.h, a series of common dialogs becomes
available to the program. To invoke the font dialog, a CHOOSEFONTS
structure is filled out, and ChooseFont() is called. This system
routine handles all the dialog processing needed to select a font via
a dialog box.
In contrast, the About Box dialog herein is programmed in the
normal manner. A dialog process is provided, and a thunk for it is
created explicitly; Windows provides no automated handling for this
program-specific dialog.
Change font attributes through the menu selections. Resize the
window to see the text resized; the text "fan" will always reach the
bottom and the right side of the window.
*******************************************************************/
#define STRICT
#include <windows.h>
#pragma hdrstop
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <commdlg.h>
#include <windowsx.h>
#include "TrueType.h"
// data initialized by first instance
typedef struct tagSETUPDATA
{
char szAppName[10]; // name of application
} SETUPDATA;
SETUPDATA SetUpData;
// Data that can be referenced throughout the
// program but not passed to other instances
HINSTANCE hInst; // hInstance of application
HWND hwnd; // hWnd of main window
HANDLE hdlg; // handle of dialog resource
DLGPROC lpDlgProc; // ptr to proc for dialog box
HWND hDlgBox; // handle of dialog box
LOGFONT MainFontRec; // logical font records,...
LOGFONT CornerFontRec; // ...which store font data...
LOGFONT BorlandFontRec; // ...for different fonts.
COLORREF FanColor[10]; // color array for "fan" of text
BOOL ShadowAll; // TRUE iff fan text gets shadows
BOOL ShowAlignmentMarks; // TRUE iff we show baselines of fan
#define ROUND(x) (floor(x + .5))
#define SQR(x) (pow(x,2))
#define TITLE_LENGTH 30
LPCSTR ArcText = "TrueType"; // text seen along arc of fan
const char* FanText = "Borland C++ for Windows"; // text for leaves of fan
const char* BorlandText = "Borland"; // text for lower right window corner
const int Radius = 100; // radius of fan "hub"
const float Deg2Rad = M_PI / 18; // conversion factor, degrees->radians
// function prototypes
int PASCAL WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpszCmdLine, int cmdShow);
void Init(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpszCmdLine, int cmdShow);
void InitFirst(HINSTANCE hInstance);
void InitEvery(HINSTANCE hInstance, int cmdShow);
LRESULT CALLBACK _export WndProc(HWND hWnd, UINT message,
WPARAM wParam, LPARAM lParam);
BOOL CALLBACK _export DlgBoxProc(HWND hDlg, UINT message,
WPARAM wParam, LPARAM lParam);
void wmCreate(void);
void cmAbout(void);
void cmAlignmentMarks(void);
void cmFonts(HWND);
void cmShadows(void);
void DoPaint(void);
void cm(void);
//*******************************************************************
// WinMain - TrueType main
//
// parameters:
// hInstance - The instance of this instance of this
// application.
// hPrevInstance - The instance of the previous instance
// of this application. This will be 0
// if this is the first instance.
// lpszCmdLine - A long pointer to the command line that
// started this application.
// cmdShow - Indicates how the window is to be shown
// initially. ie. SW_SHOWNORMAL, SW_HIDE,
// SW_MIMIMIZE.
//
// returns:
// wParam from last message.
//
//*******************************************************************
int PASCAL WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpszCmdLine, int cmdShow)
{
MSG msg;
// Go init this application.
Init(hInstance, hPrevInstance, lpszCmdLine, cmdShow);
// Get and dispatch messages for this applicaton.
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
} // while
return(msg.wParam);
} // end of WinMain()
#if !defined(__WIN32__)
//*******************************************************************
// InitAdded - done only for added instances of TrueType demo
//
// parameters:
// hPrevInstance - The instance of the previous instance
// of this application.
//
//*******************************************************************
#pragma argsused
void InitAdded(HINSTANCE hPrevInstance)
{
// get the results of the initialization of first instance
GetInstanceData(hPrevInstance, (BYTE*) &SetUpData, sizeof(SETUPDATA));
} // end of InitAdded()
#endif
//*******************************************************************
// Init - init the TrueType demo application
//
// parameters:
// hInstance - The instance of this instance of this
// application.
// hPrevInstance - The instance of the previous instance
// of this application. This will be 0
// if this is the first instance.
// lpszCmdLine - A long pointer to the command line that
// started this application.
// cmdShow - Indicates how the window is to be shown
// initially. ie. SW_SHOWNORMAL, SW_HIDE,
// SW_MIMIMIZE.
//
//*******************************************************************
#pragma argsused
void Init(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpszCmdLine, int cmdShow)
{
#if defined(__WIN32__)
InitFirst(hInstance);
#else
if (!hPrevInstance) // if no prev instance, this is first
InitFirst(hInstance);
else // this is not first instance
InitAdded(hPrevInstance);
#endif
InitEvery(hInstance, cmdShow); // init for all instances
} // end of Init()
//*******************************************************************
// InitFirst - done only for first instance of TrueType demo
//
// parameters:
// hInstance - The instance of this instance of this
// application.
//
//*******************************************************************
void InitFirst(HINSTANCE hInstance)
{
WNDCLASS wcTTFClass;
// Get string from resource with application name.
LoadString(hInstance, IDS_NAME, (LPSTR) SetUpData.szAppName, 10);
// Define the window class for this application.
wcTTFClass.style = CS_HREDRAW | CS_VREDRAW;
wcTTFClass.lpfnWndProc = WndProc;
wcTTFClass.cbClsExtra = 0;
wcTTFClass.cbWndExtra = 0;
wcTTFClass.hInstance = hInstance;
wcTTFClass.hIcon = LoadIcon(hInstance, SetUpData.szAppName);
wcTTFClass.hCursor = LoadCursor(NULL, IDC_ARROW);
wcTTFClass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
wcTTFClass.lpszClassName = SetUpData.szAppName;
wcTTFClass.lpszMenuName = SetUpData.szAppName;
// Register the class
RegisterClass(&wcTTFClass);
} // end of InitFirst()
//*******************************************************************
// InitEvery - done for every instance of TrueType demo program
//
// parameters:
// hInstance - The instance of this instance of this
// application.
// cmdShow - Indicates how the window is to be shown
// initially. ie. SW_SHOWNORMAL, SW_HIDE,
// SW_MIMIMIZE.
//
//*******************************************************************
#pragma argsused
void InitEvery(HINSTANCE hInstance, int cmdShow)
{
char title[TITLE_LENGTH+1];
hInst = hInstance; // save for use by window procs
// fetch in the window title from the stringtable resource
LoadString(hInstance, IDS_TITLE, (LPSTR)title, TITLE_LENGTH);
// Create applications main window.
hwnd = CreateWindow(SetUpData.szAppName, // window class name
(LPSTR)title, // window title
WS_OVERLAPPEDWINDOW, // window style
CW_USEDEFAULT, // x etc.: use defaults
CW_USEDEFAULT, // y
CW_USEDEFAULT, // cx
CW_USEDEFAULT, // cy
NULL, // no parent for this window
NULL, // use the class menu
hInstance, // who created this window
NULL // no parms to pass on
);
ShowWindow(hwnd, cmdShow);
UpdateWindow(hwnd);
} // end of InitEvery()
//*******************************************************************
// WndProc - handles messages for this application
//
// parameters:
// hWnd - The window handle for this message
// message - The message number
// wParam - The WPARAM parameter for this message
// lParam - The LPARAM parameter for this message
//
// returns:
// depends on message.
//
//*******************************************************************
LRESULT CALLBACK _export WndProc(HWND hWnd, UINT message,
WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_CREATE:
wmCreate();
break;
case WM_COMMAND:
switch (GET_WM_COMMAND_ID(wParam, lParam))
{
case CM_ABOUT:
cmAbout();
break;
case CM_EXIT:
// Tell windows to destroy our window.
DestroyWindow(hWnd);
break;
case CM_ALIGNMENTMARKS:
cmAlignmentMarks();
break;
case CM_FONTS:
cmFonts(hWnd);
break;
case CM_SHADOWS:
cmShadows();
break;
default:
break;
} // switch wParam
break;
case WM_PAINT:
DoPaint();
break;
case WM_GETMINMAXINFO:
// Limit the minimum size of the window to 300x300,
// so the fonts don't get too small
((POINT far *)lParam)[3].x = 300;
((POINT far *)lParam)[3].y = 300;
break;
case WM_DESTROY:
// This is the end if we were closed by a DestroyWindow call.
PostQuitMessage(0);
break;
default:
return(DefWindowProc(hWnd, message, wParam, lParam));
} // switch message
return(0L);
} // end of WndProc()
//*******************************************************************
// DlgBoxProc - handle dialog messages
//
// parameters:
// hDlg - The window handle for this message
// message - The message number
// wParam - The WPARAM parameter for this message
// lParam - The LPARAM parameter for this message
//
//*******************************************************************
#pragma argsused
BOOL CALLBACK _export DlgBoxProc(HWND hDlg, UINT message,
WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_SYSCOMMAND:
// Pass WM_SYSCOMMAND messages on to main window so both
// main window and dialog box get iconized, minimized etc.
// in parallel.
SendMessage(hwnd, message, wParam, lParam);
break;
case WM_COMMAND:
// regardless of the command (only ID_OK should arrive)
// we want to exit the dialog
EndDialog(hDlg, TRUE);
break;
default:
return FALSE;
} // switch
return(TRUE);
} // end of DlgBoxProc()
static void
MeasureText (HDC hDC, const char *str, SIZE *size)
{
#if defined(__WIN32__)
GetTextExtentPoint(hDC, str, strlen(str), size);
#else
DWORD d = GetTextExtent(hDC, str, strlen(str));
size->cx = LOWORD(d);
size->cy = HIWORD(d);
#endif
}
//*************************************************************************
// DoPaint -- this is the WM_PAINT action routine for the main window.
// It places the TrueType logo in the upper left corner of the window, draws
// a "fan hub" around it, and draws "fan leaves" of text out from the hub.
// These leaves are scaled to reach the bottom and the right edge of the
// window, by defining an ellipse centered on the TrueType logo which just
// touches those two edges. The text strings span the distance from the
// hub to the ellipse along radial lines, and are both scaled and rotated.
// Depending on user-set state variables, the ellipse and baselines
// for the text fan may be shown (ShowAlignmentMarks), and/or the text may
// be shadowed (ShadowAll). Other attributes, such as bolding or
// italicization, may be selected from the font dialog box.
//*************************************************************************
void DoPaint()
{
PAINTSTRUCT PaintInfo;
HDC hDC;
LOGFONT FontRec;
UINT FmSize;
OUTLINETEXTMETRIC *FontMetric;
int FontHeight, x, y, j, k;
UINT BaseWidth, DesiredExtent;
float Theta;
LPCSTR P;
RECT R;
int d;
SIZE size;
#if defined(__WIN32__)
POINT point;
#endif
UINT FanTextLen = strlen(FanText);
BeginPaint(hwnd, &PaintInfo);
hDC = PaintInfo.hdc;
P = ArcText;
// save device context; easiest way to preserve current state
SaveDC(hDC);
// set initial font data (for TrueType logo)
FontRec = CornerFontRec;
SetBkMode(hDC, TRANSPARENT);
SetTextColor(hDC, RGB(128,128,128));
FontRec.lfHeight = FontRec.lfHeight * 2;
FontRec.lfWidth = floor(FontRec.lfWidth * 2.1);
// create the TrueType logo
SelectObject(hDC, CreateFontIndirect(&FontRec));
TextOut(hDC, 18, 5, "T", 1);
SetTextColor(hDC, RGB(0,0,0));
TextOut(hDC, 32, 13,"T", 1);
// determine window dimensions & set up fan text parameters
GetClientRect(hwnd, &R);
FontRec = MainFontRec;
DeleteObject(SelectObject(hDC, CreateFontIndirect(&FontRec)));
FmSize = GetOutlineTextMetrics(hDC, 0, 0);
FontMetric = (OUTLINETEXTMETRIC*)malloc(FmSize);
FontMetric->otmpFamilyName = 0;
FontMetric->otmpFaceName = 0;
FontMetric->otmpStyleName = 0;
FontMetric->otmpFullName = 0;
GetOutlineTextMetrics(hDC, FmSize, FontMetric);
FontHeight = FontMetric->otmTextMetrics.tmHeight;
#if defined(__WIN32__)
SetViewportOrgEx(hDC, FontHeight+2, 0, &point);
#else
SetViewportOrg(hDC, FontHeight+2, 0);
#endif
MeasureText(hDC, FanText, &size);
BaseWidth = size.cx;
R.right -= FontHeight+2;
// get a "black brush" for drawing operations
SelectObject(hDC, GetStockObject(NULL_BRUSH));
// if we want to show the alignment marks, draw the bounding ellipse
if (ShowAlignmentMarks)
{
Ellipse(hDC, -R.right, -R.bottom, R.right, R.bottom);
}
// draw the "hub" of the fan
Ellipse(hDC, -(Radius-5), -(Radius-5), (Radius-5), Radius-5);
Ellipse(hDC, -(Radius-10), -(Radius-10), (Radius-10), Radius-10);
SetTextColor(hDC, FanColor[0]);
// loop over the "fan leaves"
for ( d = 27; d <= 36; d++)
{
x = ROUND(Radius * cos(d * Deg2Rad));
y = ROUND(Radius * sin(-d * Deg2Rad)); // -d because y axis is inverted
Theta = -d * Deg2Rad;
if (x)
{
Theta = atan((R.right / (R.bottom * 1.0)) * (y / (x * 1.0)));
}
j = ROUND(R.right * cos(Theta));
k = ROUND(R.bottom * sin(Theta));
if (ShowAlignmentMarks)
{
#if defined(__WIN32__)
MoveToEx(hDC, x,y, &point);
#else
MoveTo(hDC, x, y);
#endif
LineTo(hDC, j,k);
}
DesiredExtent = ROUND(sqrt(SQR(x*1.0 - j) + SQR(y*1.0 - k))) - 5;
FontRec = MainFontRec;
FontRec.lfEscapement = d * 100;
FontRec.lfWidth = floor((FontMetric->otmTextMetrics.tmAveCharWidth) *
(DesiredExtent / (BaseWidth * 1.0)));
DeleteObject(SelectObject(hDC, CreateFontIndirect(&FontRec)));
MeasureText(hDC, FanText, &size);
for ( ;(size.cx > DesiredExtent) && (FontRec.lfWidth);
FontRec.lfWidth-- )
{
// Shave off some character width until the string fits
DeleteObject(SelectObject(hDC, CreateFontIndirect(&FontRec)));
MeasureText(hDC, FanText, &size);
}
// Expand the string if necessary to make it fit the desired extent
if (size.cx < DesiredExtent)
{ SetTextJustification(hDC,DesiredExtent - size.cx, 3); }
if (ShadowAll)
{
SetTextColor(hDC, RGB(0,0,0));
TextOut(hDC, x+2, y+1, FanText, FanTextLen);
}
SetTextColor(hDC, FanColor[d - 27]);
TextOut(hDC, x, y, FanText, FanTextLen);
// clear justifier's internal error accumulator
SetTextJustification(hDC,0,0);
if (P[0])
{
FontRec = CornerFontRec;
FontRec.lfEscapement = (d+10) * 100;
FontRec.lfWidth = 0;
DeleteObject(SelectObject(hDC, CreateFontIndirect(&FontRec)));
SetTextColor(hDC, 0);
x = floor((Radius - FontHeight - 5) * cos(d * Deg2Rad));
y = floor((Radius - FontHeight - 5) * sin(-d * Deg2Rad));
TextOut(hDC, x, y, P, 1);
P++;
} // if
} // for d
free(FontMetric);
// lose the fan font, selecting in the Borland text font
DeleteObject(SelectObject(hDC, CreateFontIndirect(&BorlandFontRec)));
MeasureText(hDC, BorlandText, &size);
SetTextColor(hDC, RGB(0,0,0));
// write the Borland text in the lower right corner, with a shadow effect
TextOut(hDC, R.right - size.cx, R.bottom - size.cy, BorlandText,
strlen(BorlandText));
SetTextColor(hDC, RGB(255,0,0));
TextOut(hDC, R.right - size.cx - 5, R.bottom - size.cy, BorlandText,
strlen(BorlandText));
DeleteObject(SelectObject(hDC, GetStockObject(SYSTEM_FONT)));
// restore the saved DC; easiest way to reset to entry state
RestoreDC(hDC, -1);
EndPaint(hwnd, &PaintInfo);
} // end of DoPaint()
//*************************************************************************
// wmCreate -- action routine for the WM_CREATE message. This routine
// sets up font record data and colors for use in the painting routines,
// and creates a thunk for the dialog process
//*************************************************************************
void wmCreate(void)
{
// create the font data for the main font
MainFontRec.lfHeight = 26;
MainFontRec.lfWidth = 10;
MainFontRec.lfEscapement = 0;
MainFontRec.lfOrientation = 0;
MainFontRec.lfWeight = FW_BOLD;
MainFontRec.lfItalic = 0;
MainFontRec.lfUnderline = 0;
MainFontRec.lfStrikeOut = 0;
MainFontRec.lfCharSet = ANSI_CHARSET;
MainFontRec.lfOutPrecision = OUT_DEFAULT_PRECIS;
MainFontRec.lfClipPrecision = CLIP_DEFAULT_PRECIS;
MainFontRec.lfQuality = PROOF_QUALITY;
MainFontRec.lfPitchAndFamily = VARIABLE_PITCH | FF_ROMAN;
strcpy(MainFontRec.lfFaceName,"Times New Roman");
// structure copy (!) into corner font
CornerFontRec = MainFontRec;
// copy again inot Borland font, but switch to Arial typeface, new size
BorlandFontRec = MainFontRec;
BorlandFontRec.lfHeight = 60;
BorlandFontRec.lfWidth = 0; // choose best width for this height
BorlandFontRec.lfWeight = 900;
strcpy(BorlandFontRec.lfFaceName, "Arial");
// Array of colors used to color the fan text
FanColor[0] = RGB(255,0,0);
FanColor[1] = RGB(128,0,0);
FanColor[2] = RGB(255,128,0);
FanColor[3] = RGB(80,80,0);
FanColor[4] = RGB(80,255,0);
FanColor[5] = RGB(0,128,0);
FanColor[6] = RGB(0,128,255);
FanColor[7] = RGB(0,0,255);
FanColor[8] = RGB(128,128,128);
FanColor[9] = RGB(255,0,0);
ShadowAll = 0;
ShowAlignmentMarks = 0;
} // end of wmCreate()
/*********************************************************************
cmXxxx routines -- these are action routines for menu commands
*********************************************************************/
//*************************************************************************
// cmShadows -- toggle the ShadowsAll flag, and set the menu checkmark
// as appropriate
//*************************************************************************
void cmShadows(void)
{
ShadowAll = !ShadowAll;
if (ShadowAll)
{
CheckMenuItem(GetMenu(hwnd), CM_SHADOWS, MF_BYCOMMAND | MF_CHECKED);
}
else
{
CheckMenuItem(GetMenu(hwnd), CM_SHADOWS,
MF_BYCOMMAND | MF_UNCHECKED);
}
// Erase if going Shadow -> no Shadow
InvalidateRect(hwnd, NULL, !ShadowAll);
} // end of cmShadows()
//*************************************************************************
// cmAlignmentMarks -- toggle the state of ShowAlignmentMarks, and toggle
// the checkmark in the menu to match
//*************************************************************************
void cmAlignmentMarks(void)
{
ShowAlignmentMarks = !ShowAlignmentMarks;
if (ShowAlignmentMarks)
{
CheckMenuItem(GetMenu(hwnd), CM_ALIGNMENTMARKS,
MF_BYCOMMAND | MF_CHECKED);
}
else
{
CheckMenuItem(GetMenu(hwnd), CM_ALIGNMENTMARKS,
MF_BYCOMMAND | MF_UNCHECKED);
}
// Erase if going Marks -> no Marks
InvalidateRect(hwnd, NULL, !ShowAlignmentMarks);
} // end of cmAlignmentMarks()
//*************************************************************************
// cmAbout -- invoke the "About" dialog. Its return code is ignored, since
// the About dialog doesn't return anything to the program.
//*************************************************************************
#pragma warn -eff
void cmAbout(void)
{
lpDlgProc = (DLGPROC) MakeProcInstance( (FARPROC) DlgBoxProc, hInst);
DialogBox(hInst, "About", hwnd, lpDlgProc);
FreeProcInstance ( (FARPROC) lpDlgProc );
} // end of cmAbout()
#pragma warn .eff
//*************************************************************************
// cmFonts -- use the Choose Fonts common dialog to get a new font spec
// from the user. To do this, we fill out a CHOOSEFONTS structure and
// pass it to the ChooseFonts routine. Windows 3.1 takes care of the rest!
//*************************************************************************
void cmFonts(HWND hWnd)
{
CHOOSEFONT CF;
LOGFONT FontRec = MainFontRec;
CF.lStructSize = sizeof(CF);
CF.hwndOwner = hWnd;
CF.Flags = CF_ANSIONLY | CF_TTONLY | CF_SCREENFONTS |
CF_INITTOLOGFONTSTRUCT | CF_ENABLETEMPLATE;
CF.nFontType = SCREEN_FONTTYPE;
CF.lpLogFont = &FontRec;
CF.nSizeMin = 20;
CF.nSizeMax = 20;
CF.lpTemplateName = "FontDlg";
CF.hInstance = hInst;
if (ChooseFont(&CF))
{
// Only get the font name, weight, and italics;
// we don't care about size
strcpy(MainFontRec.lfFaceName, FontRec.lfFaceName);
MainFontRec.lfWeight = FontRec.lfWeight;
MainFontRec.lfItalic = FontRec.lfItalic;
InvalidateRect(hwnd, NULL, TRUE);
}
} // end of cmFonts()